diff --git a/AUTHORS b/AUTHORS
index c4519893..e66ef19f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -382,6 +382,7 @@
 Ganesh Borle <ganesh.borle@samsung.com>
 Gao Chun <chun.gao@intel.com>
 Gao Chun <gaochun.dev@gmail.com>
+Gao Yu <wanggao@tencent.com>
 Gaurav Dhol <gaurav.dhol@einfochips.com>
 Gautham Banasandra <gautham.bangalore@gmail.com>
 George Adams <geoada@amazon.com>
@@ -701,6 +702,7 @@
 Leo Wolf <jclw@ymail.com>
 Leon Han <leon.han@intel.com>
 Leung Wing Chung <lwchkg@gmail.com>
+Li Yanbo <liyanbo.monster@bytedance.com>
 Li Yin <li.yin@intel.com>
 Lidwine Genevet <lgenevet@cisco.com>
 Lin Sun <lin.sun@intel.com>
@@ -1160,6 +1162,7 @@
 Taeseong Yu <yugeeklab@gmail.com>
 Taeyeon Kim <ssg9732@gmail.com>
 Tae Shin <taeshindev@gmail.com>
+Taher Ali <taher.dasten@gmail.com>
 Takaaki Suzuki <takaakisuzuki.14@gmail.com>
 Takahiro Aoyagi <hogehoge@gachapin.jp>
 Takashi Fujita <tgfjt.mail@gmail.com>
diff --git a/DEPS b/DEPS
index 3d173db..f1542aa 100644
--- a/DEPS
+++ b/DEPS
@@ -280,19 +280,19 @@
   # 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': 'c37b3868863bc9881ce14b33125900749a673f52',
+  'skia_revision': '68f066c3359f89967005e14e89a98f3a45eca8c3',
   # 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': 'ff099f3e0d371eccaa535e6438bd9ed7ac2eb549',
+  'v8_revision': '29c881717fb023c772dff139be87b7bd44d19ef8',
   # 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': '32c38e55ed44f22a99d227036fbd9059b24ebde6',
+  'angle_revision': '6d3c637052ef59e92390ce6361bec2dc32f78e80',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '5cb6a639d49457b258f9777b9bc180d67e5b7e4e',
+  'swiftshader_revision': '603af618f19fa890a3c9943d312c75b9817e239d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -307,7 +307,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:8.20220614.2.1',
+  'fuchsia_version': 'version:8.20220622.1.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.
@@ -331,7 +331,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '2848378be56ea26376e3aff68b1b4b8aa8f8611b',
+  'freetype_revision': '117df36b4c3a5f7850a3789e92ce54d9341673ff',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -351,7 +351,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '4ea19a6a7078a6ad6b5e859bc0f7620769a38eb1',
+  'catapult_revision': 'c083518eecae6cecd78e0b63ab7288231e4e7788',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -359,7 +359,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': 'd3ba5cbbb58405bf03ee6a7d9db6bad5f737418b',
+  'devtools_frontend_revision': 'c25cc0e5482bb72083767fb92e4d2d1ec7ee226e',
   # 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.
@@ -395,7 +395,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': '9be6b99a4b9c13c8d48691e3bf04ea09b736c03d',
+  'dawn_revision': '606abfbeae8366c9fe872c8bdf5f7cff9d1668f6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -439,7 +439,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.
-  'libcxxabi_revision':    '92ef8d47d097facc2b119ee0172767cb786fcf79',
+  'libcxxabi_revision':    'b5f3d3b904425613311516b1ee27fa2bae57b1e4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -466,7 +466,7 @@
   'libcxx_revision':       'b1269813eaf5b8ac78e35e45a0f7cc320bd3e7d6',
 
   # GN CIPD package version.
-  'gn_version': 'git_revision:8883070fe77f9b484818e73e5892c08ca8a0fe7f',
+  'gn_version': 'git_revision:29accf5ac2eadfc53e687081583b7bc1592a8839',
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -756,11 +756,11 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + 'f754e2d8945e4500e4cb862d51f2a2289abb7be1',
+    'url': Var('chromium_git') + '/website.git' + '@' + '1c0cc8b06ab331fe0c6db04a98fa5dd144688058',
   },
 
   'src/ios/third_party/earl_grey2/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '2163a71a16632abd953b055cf391d66eb410a16d',
+      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '74d850b12a67049346a92073b7cb95a6293ceb50',
       'condition': 'checkout_ios',
   },
 
@@ -850,7 +850,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/linux-amd64',
-          'version': 'Wl6laXAv3QcBejp79gWdf6YQ5arK939SeUdPw0jweRsC',
+          'version': 'fotn1udKkijRy0viR_egZ-5NTnXyXeUjjd4KcvD9mHMC',
         },
       ],
       'dep_type': 'cipd',
@@ -861,7 +861,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': 'rBaMMFN6UzwoR4I8XO4qmYnsjW2yra718cbXHaNQvjYC',
+          'version': 'EsOZhu-07Fr-CbzlStDJVQkOwkIuoaNgCjXZUGutvTsC',
         },
       ],
       'dep_type': 'cipd',
@@ -872,7 +872,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/windows-amd64',
-          'version': '9HAfnCiM-qWdfeUj64pS0sz_44H0odG5K3nS6EUm8KUC',
+          'version': 'Rhw7401rTY22Q0yEEqxnwdyOYycxoKM12jN7qT6KiFoC',
         },
       ],
       'dep_type': 'cipd',
@@ -1145,7 +1145,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '39e4055004da058d34682e11ffb1f0a035289149',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1d5d7803fa53fb3a86684d45fa968ea05330dbf1',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1182,7 +1182,7 @@
     Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596',
 
   'src/third_party/flatbuffers/src':
-    Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + 'b8aaccee8248059b2af032cca0eb1d2ddbdb6cdc',
+    Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + '0fe13cb28ce5a3fb81f654b21cb37c9821194962',
 
   # Used for embedded builds. CrOS & Linux use the system version.
   'src/third_party/fontconfig/src': {
@@ -1434,7 +1434,7 @@
     Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da',
 
   'src/third_party/libyuv':
-    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'e906ba9fe9df1cdc32307dbb1dcb1223d41bfd56',
+    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'fe4a50df8e2a787e2919a8321dbe1412b94b20c6',
 
   'src/third_party/lighttpd': {
       'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
@@ -1542,7 +1542,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '2b0a2135f09e99334d902dee6052569bfc26d212',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '0eba417b2c72264fa825dc21067b9adc9b8adf70',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1660,7 +1660,7 @@
     Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f',
 
   'src/third_party/tflite/src':
-    Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '0a25ee4aef238f0c5e33647eb6d5fee072054fd8',
+    Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '0550a551f158167fa88acb17261d96e959529f70',
 
   'src/third_party/turbine': {
       'packages': [
@@ -1709,10 +1709,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'e58ed2132aa47ac110a4cce1763abfa34f4fa34e',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'ca9a3bc65360a04399c2403d140b6680d74e021d',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'cef4c767813032183d4554d3ba2dc6f1999988b9',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'e3342ef27f747463c741ff109fee70b7ddc0eb0e',
+    Var('webrtc_git') + '/src.git' + '@' + 'bf0cbcb8feb031fe98c906944207b18ede57bee0',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1733,7 +1733,7 @@
   },
 
   'src/third_party/xnnpack/src':
-    Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '108f3657bc0cc9592f88adb124a21bcf9ca63f06',
+    Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '55775ab7afc3a89ed93491e6600bb9afa4dca148',
 
   'src/tools/page_cycler/acid3':
     Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + '6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
@@ -1785,7 +1785,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7ff2a183cb21394d43e4526a1b11c50423807a13',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ff346c631e378d8fc936f9d3032f66d31203576f',
     'condition': 'checkout_src_internal',
   },
 
@@ -1815,7 +1815,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': '-UEm5uU3XGHjQkKjF-UqjE18vqRqoaMj074Ix_a8nmsC',
+        'version': 'sb-wuUZYCzLO3jj8F8-34EU_hfm2j-ZWpv_izCD9j-cC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1826,7 +1826,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'a6KSLbsYoaubZsrOcT_IRNMy6dOcrre1XrEzxWKMA1YC',
+        'version': 'RI7TbUz4rNrKXCPf2f9AeHB4tSmNfXylhWpFMZ2zk-IC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1837,7 +1837,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'liVdNj_9nO42XGCZf68gYmXhBK1ly1TQMszGmZpR9AUC',
+        'version': 'b9_HEs-hlJGHnWiQzcjc3JkFaakxaw7yDA1K3kxjMzwC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3893,6 +3893,14 @@
                '-s', 'src/third_party/skia',
                '--header', 'src/skia/ext/skia_commit_hash.h'],
   },
+  {
+    # Update dawn_version.h.
+    'name': 'lastchange_dawn',
+    'pattern': '.',
+    'action': ['python3', 'src/build/util/lastchange.py',
+               '-s', 'src/third_party/dawn',
+               '--revision', 'src/gpu/webgpu/DAWN_VERSION'],
+  },
   # Pull dsymutil binaries using checked-in hashes.
   {
     'name': 'dsymutil_mac_arm64',
diff --git a/WATCHLISTS b/WATCHLISTS
index c8aec86..8cfe08f 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -961,7 +961,7 @@
       'filepath': 'devtools',
     },
     'diagnostics_mojo': {
-      'filepath': 'chromeos/services/cros_healthd/public/mojom/',
+      'filepath': 'chromeos/ash/services/cros_healthd/public/mojom/',
     },
     'diagnostics_ui': {
       'filepath': 'ash/webui/diagnostics_ui/',
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index 91b85fb..0fdeccb 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -51,8 +51,6 @@
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/url_formatter/url_fixer.h"
 #include "components/user_prefs/user_prefs.h"
-#include "components/variations/variations_client.h"
-#include "components/variations/variations_ids_provider.h"
 #include "components/visitedlink/browser/visitedlink_writer.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -146,48 +144,6 @@
   migrate_context_storage_data("webrtc_event_logs");
 }
 
-bool ShouldSendVariationsHeaders() {
-  // Note: Normally, checking the feature second is preferred to avoid tagging
-  // clients with the trial that are not participating in the behavior. However,
-  // doing so reveals the shouldSendVariationsHeaders() result for the clients
-  // where it's true, which would require carefully considering the implications
-  // of. This can be revisited later.
-  return base::FeatureList::IsEnabled(
-             features::kWebViewSendVariationsHeaders) &&
-         Java_AwBrowserContext_shouldSendVariationsHeaders(
-             base::android::AttachCurrentThread());
-}
-
-class AwVariationsClient : public variations::VariationsClient {
- public:
-  explicit AwVariationsClient(content::BrowserContext* browser_context)
-      : browser_context_(browser_context),
-        should_send_headers_(ShouldSendVariationsHeaders()) {}
-
-  ~AwVariationsClient() override = default;
-
-  bool IsOffTheRecord() const override {
-    return browser_context_->IsOffTheRecord();
-  }
-
-  variations::mojom::VariationsHeadersPtr GetVariationsHeaders()
-      const override {
-    if (!should_send_headers_)
-      return nullptr;
-
-    const bool is_signed_in = false;
-    DCHECK_EQ(
-        variations::VariationsIdsProvider::Mode::kDontSendSignedInVariations,
-        variations::VariationsIdsProvider::GetInstance()->mode());
-    return variations::VariationsIdsProvider::GetInstance()
-        ->GetClientDataHeaders(is_signed_in);
-  }
-
- private:
-  raw_ptr<content::BrowserContext> browser_context_;
-  bool should_send_headers_;
-};
-
 }  // namespace
 
 AwBrowserContext::AwBrowserContext()
@@ -474,12 +430,6 @@
   return nullptr;
 }
 
-variations::VariationsClient* AwBrowserContext::GetVariationsClient() {
-  if (!variations_client_)
-    variations_client_ = std::make_unique<AwVariationsClient>(this);
-  return variations_client_.get();
-}
-
 content::BackgroundFetchDelegate*
 AwBrowserContext::GetBackgroundFetchDelegate() {
   return nullptr;
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h
index eac7d74c2..526043b3 100644
--- a/android_webview/browser/aw_browser_context.h
+++ b/android_webview/browser/aw_browser_context.h
@@ -105,7 +105,6 @@
       override;
   content::ClientHintsControllerDelegate* GetClientHintsControllerDelegate()
       override;
-  variations::VariationsClient* GetVariationsClient() override;
   content::BackgroundFetchDelegate* GetBackgroundFetchDelegate() override;
   content::BackgroundSyncController* GetBackgroundSyncController() override;
   content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
@@ -149,7 +148,6 @@
   std::unique_ptr<PrefService> user_pref_service_;
   std::unique_ptr<AwSSLHostStateDelegate> ssl_host_state_delegate_;
   std::unique_ptr<content::PermissionControllerDelegate> permission_manager_;
-  std::unique_ptr<variations::VariationsClient> variations_client_;
 
   SimpleFactoryKey simple_factory_key_;
 
diff --git a/android_webview/browser/aw_quota_manager_bridge.cc b/android_webview/browser/aw_quota_manager_bridge.cc
index 0fe4c17d..1b51648 100644
--- a/android_webview/browser/aw_quota_manager_bridge.cc
+++ b/android_webview/browser/aw_quota_manager_bridge.cc
@@ -193,8 +193,8 @@
           StoragePartition::REMOVE_DATA_MASK_INDEXEDDB |
           StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE |
           StoragePartition::REMOVE_DATA_MASK_WEBSQL,
-      StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY, GURL(),
-      base::Time(), base::Time::Max(), base::DoNothing());
+      StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY,
+      blink::StorageKey(), base::Time(), base::Time::Max(), base::DoNothing());
 }
 
 void AwQuotaManagerBridge::DeleteOrigin(JNIEnv* env,
diff --git a/android_webview/common/aw_features.cc b/android_webview/common/aw_features.cc
index ccc8f1d..288d796 100644
--- a/android_webview/common/aw_features.cc
+++ b/android_webview/common/aw_features.cc
@@ -94,10 +94,6 @@
 const base::Feature kWebViewRecordAppDataDirectorySize{
     "WebViewRecordAppDataDirectorySize", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Whether WebView will send variations headers on URLs where applicable.
-const base::Feature kWebViewSendVariationsHeaders{
-    "WebViewSendVariationsHeaders", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Disallows window.{alert, prompt, confirm} if triggered inside a subframe that
 // is not same origin with the main frame.
 const base::Feature kWebViewSuppressDifferentOriginSubframeJSDialogs{
diff --git a/android_webview/common/aw_features.h b/android_webview/common/aw_features.h
index cc744769..b703164 100644
--- a/android_webview/common/aw_features.h
+++ b/android_webview/common/aw_features.h
@@ -33,7 +33,6 @@
 extern const base::Feature kWebViewMixedContentAutoupgrades;
 extern const base::Feature kWebViewOriginTrials;
 extern const base::Feature kWebViewRecordAppDataDirectorySize;
-extern const base::Feature kWebViewSendVariationsHeaders;
 extern const base::Feature kWebViewSuppressDifferentOriginSubframeJSDialogs;
 extern const base::Feature kWebViewTestFeature;
 extern const base::Feature kWebViewUseMetricsUploadService;
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java
index 396e318..f27b3ff2 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java
@@ -153,7 +153,6 @@
             }
             if (TRACE) Log.i(TAG, "onReceivedError=" + request.url);
             if (mSupportLibClient.isFeatureAvailable(Features.RECEIVE_WEB_RESOURCE_ERROR)) {
-                // Note: we must pass AwWebResourceError, since this class was introduced after L.
                 mSupportLibClient.onReceivedError(
                         mWebView, new WebResourceRequestAdapter(request), error);
             } else {
@@ -193,28 +192,28 @@
             TraceEvent.begin("WebViewContentsClientAdapter.onReceivedHttpError");
             if (TRACE) Log.i(TAG, "onReceivedHttpError=" + request.url);
             if (mSupportLibClient.isFeatureAvailable(Features.RECEIVE_HTTP_ERROR)) {
-                String reasonPhrase = response.getReasonPhrase();
-                if (reasonPhrase == null || reasonPhrase.isEmpty()) {
-                    // We cannot pass a null or empty reasonPhrase, because this version of the
-                    // WebResourceResponse constructor will throw. But we may legitimately not
-                    // receive a reasonPhrase in the HTTP response, since HTTP/2 removed
-                    // Reason-Phrase from the spec (and discourages it). Instead, assign some dummy
-                    // value to avoid the crash. See http://crbug.com/925887.
-                    reasonPhrase = "UNKNOWN";
-                }
-
-                // Note: we do not create an immutable instance here, because that constructor is
-                // not available on L.
+                // Note: we use the @SystemApi constructor here because it relaxes several
+                // requirements:
+                // * response.getReasonPhrase() may legitimately be empty because HTTP/2 removed
+                //   Reason-Phrase from the spec (https://crbug.com/925887).
+                // * response.getStatusCode() may be out of the valid range if the web server is not
+                //   obeying the HTTP spec (ex. http://b/235960500).
+                //
+                // Immutability is not strictly necessary, but apps should not not need to modify
+                // the WebResourceResponse received in this callback (they can always construct
+                // their own instance).
                 mSupportLibClient.onReceivedHttpError(mWebView,
                         new WebResourceRequestAdapter(request),
-                        new WebResourceResponse(response.getMimeType(), response.getCharset(),
-                                response.getStatusCode(), reasonPhrase,
-                                response.getResponseHeaders(), response.getData()));
+                        new WebResourceResponse(/* immutable= */ true, response.getMimeType(),
+                                response.getCharset(), response.getStatusCode(),
+                                response.getReasonPhrase(), response.getResponseHeaders(),
+                                response.getData()));
             } else {
                 mWebViewClient.onReceivedHttpError(mWebView, new WebResourceRequestAdapter(request),
-                        new WebResourceResponse(true, response.getMimeType(), response.getCharset(),
-                                response.getStatusCode(), response.getReasonPhrase(),
-                                response.getResponseHeaders(), response.getData()));
+                        new WebResourceResponse(/* immutable= */ true, response.getMimeType(),
+                                response.getCharset(), response.getStatusCode(),
+                                response.getReasonPhrase(), response.getResponseHeaders(),
+                                response.getData()));
             }
             // Otherwise, the API does not exist, so do nothing.
         } finally {
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
index e68dec17..7259290 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
@@ -511,7 +511,9 @@
                                             "onGeolocationPermissionsShowPrompt",
                                             String.class,
                                             GeolocationPermissions.Callback.class)) {
-                // This is only required for pre-M versions of android.
+                // The default WebChromeClient.onGeolocationPermissionsShowPrompt() implementation
+                // is a NOOP (does not invoke the callback). Explicitly invoke the callback in
+                // chromium code to deny the permission.
                 callback.invoke(origin, false, false);
                 return;
             }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java
index fb3b8226..67c0b06 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java
@@ -6,7 +6,6 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
 
@@ -166,14 +165,6 @@
         return new AwBrowserContext(sharedPreferences, nativeAwBrowserContext, isDefault);
     }
 
-    @CalledByNative
-    public static boolean shouldSendVariationsHeaders() {
-        String packageId = PlatformServiceBridge.getInstance()
-                                   .getFirstPartyVariationsHeadersEnabledPackageId();
-        return !TextUtils.isEmpty(packageId)
-                && packageId.equals(ContextUtils.getApplicationContext().getPackageName());
-    }
-
     @NativeMethods
     interface Natives {
         AwBrowserContext getDefaultJava();
diff --git a/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridge.java b/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridge.java
index 9a8a8a6..9f6e0ef7 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridge.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridge.java
@@ -114,14 +114,6 @@
     }
 
     /**
-     * Returns a first party package ID that will send variations headers if the feature is
-     * enabled.
-     */
-    public String getFirstPartyVariationsHeadersEnabledPackageId() {
-        return "";
-    }
-
-    /**
      * Checks if app recovery mitigations are currently required and initializes SafeMode if needed.
      * This should only be called from the ":webview_service" process. All other processes should
      * query SafeModeController to receive mitigation steps.
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index 9381b541..353f009 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -280,8 +280,6 @@
                     "Enable establishing the GPU channel early in renderer startup."),
             Flag.baseFeature(ContentFeatures.OPTIMIZE_EARLY_NAVIGATION,
                     "Temporarily pauses the compositor early in navigation."),
-            Flag.baseFeature(AwFeatures.WEBVIEW_SEND_VARIATIONS_HEADERS,
-                    "Whether WebView will send variations headers on URLs where applicable."),
             Flag.baseFeature(ContentFeatures.INCLUDE_IPC_OVERHEAD_IN_NAVIGATION_START,
                     "Whether navigation metrics include ipc overhead."),
             Flag.baseFeature(ContentFeatures.AVOID_UNNECESSARY_BEFORE_UNLOAD_CHECK_POST_TASK,
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/VariationsHeadersTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/VariationsHeadersTest.java
index 29a7a59b..d622ea7 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/VariationsHeadersTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/VariationsHeadersTest.java
@@ -6,114 +6,27 @@
 
 import androidx.test.filters.MediumTest;
 
-import org.junit.After;
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import org.chromium.android_webview.AwContents;
 import org.chromium.android_webview.AwContentsStatics;
-import org.chromium.android_webview.common.PlatformServiceBridge;
-import org.chromium.base.ContextUtils;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.net.test.util.TestWebServer;
 
 /**
  * Tests that the variations headers are correctly set.
  */
 @RunWith(AwJUnit4ClassRunner.class)
-@CommandLineFlags.
-Add({"disable-field-trial-config", "force-variation-ids=4,10,34", "host-rules=MAP * 127.0.0.1",
-        "ignore-certificate-errors", "enable-features=WebViewSendVariationsHeaders"})
+@CommandLineFlags.Add({"disable-field-trial-config", "force-variation-ids=4,10,34"})
 public class VariationsHeadersTest {
-    private static final String PATH = "/ok.html";
-    private static final String HEADER_NAME = "X-Client-Data";
-
     @Rule
     public AwActivityTestRule mActivityTestRule = new AwActivityTestRule();
 
-    private String mUrl;
-    private AwContents mAwContents;
-    private TestAwContentsClient mContentsClient;
-    private TestWebServer mTestServer;
-
-    private static class TestPlatformServiceBridge extends PlatformServiceBridge {
-        private String mPackageId;
-
-        public TestPlatformServiceBridge(String packageId) {
-            mPackageId = packageId;
-        }
-
-        @Override
-        public String getFirstPartyVariationsHeadersEnabledPackageId() {
-            return mPackageId;
-        }
-    }
-
-    @Before
-    public void setUp() throws Throwable {
-        mContentsClient = new TestAwContentsClient();
-        final AwTestContainerView testContainerView =
-                mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient);
-        mAwContents = testContainerView.getAwContents();
-        mTestServer = TestWebServer.startSsl();
-        mTestServer.setServerHost("google.com");
-        mUrl = mTestServer.setResponse(PATH, "<html>ok</html>", null);
-
-        PlatformServiceBridge.injectInstance(new TestPlatformServiceBridge(
-                ContextUtils.getApplicationContext().getPackageName()));
-    }
-
-    @After
-    public void tearDown() {
-        mTestServer.shutdown();
-    }
-
     @MediumTest
     @Test
-    public void testSendsHeaderWithFeatureEnabled() throws Throwable {
-        mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), mUrl);
-        Assert.assertFalse(mTestServer.getLastRequest(PATH).headerValue(HEADER_NAME).isEmpty());
-    }
-
-    @MediumTest
-    @Test
-    public void testMatchesApiValue() throws Throwable {
-        mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), mUrl);
-        String serverHeaderValue = mTestServer.getLastRequest(PATH).headerValue(HEADER_NAME);
-        Assert.assertEquals(serverHeaderValue, AwContentsStatics.getVariationsHeader());
-    }
-
-    @CommandLineFlags.Add({"disable-features=WebViewSendVariationsHeaders"})
-    @MediumTest
-    @Test
-    public void testDoesNotSendHeaderWithFeatureDisabled() throws Throwable {
-        mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), mUrl);
-        Assert.assertEquals("", mTestServer.getLastRequest(PATH).headerValue(HEADER_NAME));
-    }
-
-    @MediumTest
-    @Test
-    public void testDoesNotSendHeaderForOtherHost() throws Throwable {
-        TestWebServer testServer = TestWebServer.startAdditionalSsl();
-        testServer.setServerHost("example.com");
-        String url = testServer.setResponse(PATH, "<html>ok</html>", null);
-        try {
-            mActivityTestRule.loadUrlSync(
-                    mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
-            Assert.assertEquals("", testServer.getLastRequest(PATH).headerValue(HEADER_NAME));
-        } finally {
-            testServer.shutdown();
-        }
-    }
-
-    @MediumTest
-    @Test
-    public void testDoesNotSendHeaderWhenPackageIdIncorrect() throws Throwable {
-        PlatformServiceBridge.injectInstance(new TestPlatformServiceBridge("foo.bar"));
-        mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), mUrl);
-        Assert.assertEquals("", mTestServer.getLastRequest(PATH).headerValue(HEADER_NAME));
+    public void testGetVariationsHeader() throws Throwable {
+        // Check the value is equal to the base64 encoded proto with the forced variations IDs.
+        Assert.assertEquals("CAQICggi", AwContentsStatics.getVariationsHeader());
     }
 }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java
index 21ae1d6..430600b 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java
@@ -40,6 +40,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.support.test.InstrumentationRegistry;
 import android.view.View;
 import android.widget.ImageView;
@@ -80,6 +81,7 @@
 import org.chromium.base.test.BaseActivityTestRule;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.Feature;
 import org.chromium.components.minidump_uploader.CrashFileManager;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -978,6 +980,10 @@
     @Test
     @LargeTest
     @Feature({"AndroidWebView"})
+    // clang-format off
+    @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R,
+        message = "https://crbug.com/1292197")
+    // clang-format on
     public void testLongPressCopy() throws Throwable {
         Context context = InstrumentationRegistry.getTargetContext();
         final long systemTime = System.currentTimeMillis();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/HomeFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/HomeFragmentTest.java
index 5a0e3e9..b22fbf9 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/HomeFragmentTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/HomeFragmentTest.java
@@ -50,6 +50,7 @@
 import org.chromium.android_webview.test.AwJUnit4ClassRunner;
 import org.chromium.base.test.BaseActivityTestRule;
 import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.Feature;
 
 import java.util.Locale;
@@ -187,6 +188,10 @@
     @Test
     @MediumTest
     @Feature({"AndroidWebView"})
+    // clang-format off
+    @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R,
+        message = "https://crbug.com/1292197")
+    // clang-format on
     public void testLongPressCopy() throws Throwable {
         Context context = InstrumentationRegistry.getTargetContext();
         // Inject a dummy PackageInfo as the current WebView package to make sure it will always be
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwComponentUpdateService.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwComponentUpdateService.java
index 77a664f6..e1bdf91 100644
--- a/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwComponentUpdateService.java
+++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwComponentUpdateService.java
@@ -32,6 +32,7 @@
  * registration. It has to be launched via JobScheduler. This is a JobService rather just a Service
  * because the new restrictions introduced in Android O+ on background execution.
  */
+// TODO(ntfschr): consider using BackgroundTaskScheduler
 @JNINamespace("android_webview")
 public class AwComponentUpdateService extends JobService {
     private static final String TAG = "AwCUS";
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwNonembeddedUmaRecorder.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwNonembeddedUmaRecorder.java
index 45326146..348f7a0 100644
--- a/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwNonembeddedUmaRecorder.java
+++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/AwNonembeddedUmaRecorder.java
@@ -153,6 +153,16 @@
         recordHistogram(record);
     }
 
+    @Override
+    public int getHistogramValueCountForTesting(String name, int sample) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getHistogramTotalCountForTesting(String name) {
+        throw new UnsupportedOperationException();
+    }
+
     private final Object mLock = new Object();
     // Service stub object
     @GuardedBy("mLock")
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/AwVariationsSeedFetcher.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/AwVariationsSeedFetcher.java
index 12564a1..be4dea64 100644
--- a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/AwVariationsSeedFetcher.java
+++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/AwVariationsSeedFetcher.java
@@ -35,9 +35,8 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * AwVariationsSeedFetcher is a JobService which periodically downloads the variations seed. We use
- * JobService instead of BackgroundTaskScheduler, since JobService is available on L+, and WebView
- * is L+ only. The job is scheduled whenever an app requests the seed, and it's been at least 1 day
+ * AwVariationsSeedFetcher is a JobService which periodically downloads the variations seed.
+ * The job is scheduled whenever an app requests the seed, and it's been at least 1 day
  * since the last fetch. If WebView is never used, the job will never run. The 1-day minimum fetch
  * period is chosen as a trade-off between seed freshness (and prompt delivery of feature
  * killswitches) and data and battery usage. Various Android versions may enforce longer periods,
@@ -45,6 +44,7 @@
  * be used outside the variations service. For the equivalent fetch in Chrome, see
  * AsyncInitTaskRunner$FetchSeedTask.
  */
+// TODO(https://crbug.com/1328637): consider using BackgroundTaskScheduler instead of JobService
 public class AwVariationsSeedFetcher extends JobService {
     @VisibleForTesting
     public static final String JOB_REQUEST_COUNT_KEY = "RequestCount";
diff --git a/android_webview/support_library/OWNERS b/android_webview/support_library/OWNERS
index c40400a..b2d5208 100644
--- a/android_webview/support_library/OWNERS
+++ b/android_webview/support_library/OWNERS
@@ -1,2 +1,4 @@
 ntfschr@chromium.org
+pbirk@chromium.org
+swestphal@chromium.org
 torne@chromium.org
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 03364fd..1fde6869 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -2326,6 +2326,7 @@
     "//ui/chromeos/events",
     "//ui/chromeos/resources",
     "//ui/chromeos/styles:cros_styles_views",
+    "//ui/chromeos/styles:cros_tokens_color_mappings",
     "//ui/color",
     "//ui/color:mixers",
     "//ui/compositor",
@@ -3024,7 +3025,9 @@
     "//chromeos/ash/components/dbus/hammerd",
     "//chromeos/ash/components/dbus/rgbkbd",
     "//chromeos/ash/components/dbus/services:test_support",
+    "//chromeos/ash/components/dbus/userdataauth",
     "//chromeos/ash/components/human_presence:human_presence",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/ash/services/assistant:test_support",
     "//chromeos/ash/services/assistant/public/cpp",
     "//chromeos/components/feature_usage",
@@ -3040,8 +3043,6 @@
     "//chromeos/dbus/human_presence:hps_proto",
     "//chromeos/dbus/power",
     "//chromeos/dbus/power:power_manager_proto",
-    "//chromeos/dbus/userdataauth",
-    "//chromeos/network:test_support",
     "//chromeos/services/assistant/public/mojom",
     "//chromeos/services/bluetooth_config:test_support",
     "//chromeos/services/network_config/public/cpp",
@@ -3457,6 +3458,7 @@
     "//cc:test_support",
     "//chromeos/ash/components/dbus/rgbkbd",
     "//chromeos/ash/components/dbus/system_clock",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/ash/services/assistant:test_support",
     "//chromeos/ash/services/assistant/public/cpp",
     "//chromeos/dbus:test_support",
@@ -3464,7 +3466,6 @@
     "//chromeos/dbus/power",
     "//chromeos/dbus/power:power_manager_proto",
     "//chromeos/login/login_state",
-    "//chromeos/network:test_support",
     "//chromeos/services/bluetooth_config:test_support",
     "//chromeos/system",
     "//chromeos/ui/frame",
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc
index f4beb27..1a6edde 100644
--- a/ash/accelerators/accelerator_controller_impl.cc
+++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -716,8 +716,10 @@
 }
 
 bool CanHandleToggleFloatingWindow() {
-  return chromeos::wm::features::IsFloatWindowEnabled() &&
-         !Shell::Get()->tablet_mode_controller()->InTabletMode();
+  if (!chromeos::wm::features::IsFloatWindowEnabled())
+    return false;
+
+  return window_util::GetActiveWindow() != nullptr;
 }
 
 // Enters capture mode image type with |source|.
@@ -854,12 +856,11 @@
 
 void HandleToggleFloating() {
   DCHECK(chromeos::wm::features::IsFloatWindowEnabled());
-  // Floating is currently not supported for tablet mode, see timeline here:
-  // https://crbug.com/1240411
-  DCHECK(!Shell::Get()->tablet_mode_controller()->InTabletMode());
-  aura::Window* window = ash::window_util::GetActiveWindow();
-  if (window)
-    chromeos::ToggleFloating(window);
+  aura::Window* window = window_util::GetActiveWindow();
+  DCHECK(window);
+  // TODO(sammiequon|shidi): Add some UI like a bounce if a window cannnot be
+  // floated.
+  chromeos::ToggleFloating(window);
   base::RecordAction(UserMetricsAction("Accel_Toggle_Floating"));
 }
 
diff --git a/ash/app_list/test/app_list_test_helper.cc b/ash/app_list/test/app_list_test_helper.cc
index cb5740f..b55399967 100644
--- a/ash/app_list/test/app_list_test_helper.cc
+++ b/ash/app_list/test/app_list_test_helper.cc
@@ -31,6 +31,7 @@
 #include "base/guid.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/animation/tween.h"
 
 namespace ash {
 
@@ -129,8 +130,10 @@
 void AppListTestHelper::StartSlideAnimationOnBubbleAppsPage(
     views::View* view,
     int vertical_offset,
-    base::TimeDelta duration) {
-  GetBubbleAppsPage()->SlideViewIntoPosition(view, vertical_offset, duration);
+    base::TimeDelta duration,
+    gfx::Tween::Type tween_type) {
+  GetBubbleAppsPage()->SlideViewIntoPosition(view, vertical_offset, duration,
+                                             tween_type);
 }
 
 void AppListTestHelper::CheckVisibility(bool visible) {
diff --git a/ash/app_list/test/app_list_test_helper.h b/ash/app_list/test/app_list_test_helper.h
index 16348e0b..8adec0c 100644
--- a/ash/app_list/test/app_list_test_helper.h
+++ b/ash/app_list/test/app_list_test_helper.h
@@ -12,6 +12,7 @@
 #include "ash/app_list/model/app_list_test_model.h"
 #include "ash/app_list/model/search/search_model.h"
 #include "ash/app_list/test_app_list_client.h"
+#include "ui/gfx/animation/tween.h"
 
 namespace base {
 class TimeDelta;
@@ -81,7 +82,8 @@
   // Slides a bubble apps page's component using a layer animation.
   void StartSlideAnimationOnBubbleAppsPage(views::View* view,
                                            int vertical_offset,
-                                           base::TimeDelta duration);
+                                           base::TimeDelta duration,
+                                           gfx::Tween::Type tween_type);
 
   // Check the visibility value of the app list and its target.
   // Fails in tests if either one doesn't match |visible|.
diff --git a/ash/app_list/views/app_list_bubble_apps_page.cc b/ash/app_list/views/app_list_bubble_apps_page.cc
index abab120..ce97e18 100644
--- a/ash/app_list/views/app_list_bubble_apps_page.cc
+++ b/ash/app_list/views/app_list_bubble_apps_page.cc
@@ -43,6 +43,7 @@
 #include "ui/compositor/layer_animator.h"
 #include "ui/compositor/layer_type.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/gfx/animation/tween.h"
 #include "ui/gfx/geometry/transform.h"
 #include "ui/gfx/text_constants.h"
 #include "ui/views/animation/animation_builder.h"
@@ -89,10 +90,6 @@
 // Insets for the separator between the continue section and apps.
 constexpr auto kSeparatorInsets = gfx::Insets::VH(0, 16);
 
-// A slide animation's tween type.
-constexpr gfx::Tween::Type kSlideAnimationTweenType =
-    gfx::Tween::LINEAR_OUT_SLOW_IN;
-
 // Delay for the show page transform and opacity animations.
 constexpr base::TimeDelta kShowPageAnimationDelay = base::Milliseconds(50);
 
@@ -272,6 +269,7 @@
   // Side-shelf uses faster animations.
   const base::TimeDelta slide_duration =
       is_side_shelf ? base::Milliseconds(150) : base::Milliseconds(250);
+  const gfx::Tween::Type tween_type = gfx::Tween::LINEAR_OUT_SLOW_IN;
 
   // Animate the views. Each section is initially offset down, then slides up
   // into its final position. For side shelf, each section is initially offset
@@ -286,7 +284,7 @@
   if (animate_continue_label_container) {
     vertical_offset += section_offset;
     SlideViewIntoPosition(continue_label_container_, vertical_offset,
-                          slide_duration);
+                          slide_duration, tween_type);
   }
   if (continue_section_->GetVisible() &&
       continue_section_->GetTasksSuggestionsCount() > 0) {
@@ -294,19 +292,23 @@
     // continue label container above.
     if (!animate_continue_label_container)
       vertical_offset += section_offset;
-    SlideViewIntoPosition(continue_section_, vertical_offset, slide_duration);
+    SlideViewIntoPosition(continue_section_, vertical_offset, slide_duration,
+                          tween_type);
   }
   if (recent_apps_->GetVisible() && recent_apps_->GetItemViewCount() > 0) {
     vertical_offset += section_offset;
-    SlideViewIntoPosition(recent_apps_, vertical_offset, slide_duration);
+    SlideViewIntoPosition(recent_apps_, vertical_offset, slide_duration,
+                          tween_type);
   }
   if (separator_->GetVisible()) {
     // The separator is not offset; it animates next to the view above it.
-    SlideViewIntoPosition(separator_, vertical_offset, slide_duration);
+    SlideViewIntoPosition(separator_, vertical_offset, slide_duration,
+                          tween_type);
   }
   if (toast_container_ && toast_container_->IsToastVisible()) {
     vertical_offset += section_offset;
-    SlideViewIntoPosition(toast_container_, vertical_offset, slide_duration);
+    SlideViewIntoPosition(toast_container_, vertical_offset, slide_duration,
+                          tween_type);
   }
 
   // The apps grid is always visible.
@@ -315,8 +317,7 @@
   // animation. No need to use SlideViewIntoPosition() because this view always
   // has a layer.
   StartSlideInAnimation(
-      scrollable_apps_grid_view_, vertical_offset, slide_duration,
-      kSlideAnimationTweenType,
+      scrollable_apps_grid_view_, vertical_offset, slide_duration, tween_type,
       base::BindRepeating(&AppListBubbleAppsPage::OnAppsGridViewAnimationEnded,
                           weak_factory_.GetWeakPtr()));
 }
@@ -857,7 +858,8 @@
 
 void AppListBubbleAppsPage::SlideViewIntoPosition(views::View* view,
                                                   int vertical_offset,
-                                                  base::TimeDelta duration) {
+                                                  base::TimeDelta duration,
+                                                  gfx::Tween::Type tween_type) {
   // Animation spec:
   //
   // Y Position: Down (offset) → End position
@@ -872,14 +874,72 @@
                                     &AppListBubbleAppsPage::DestroyLayerForView,
                                     weak_factory_.GetWeakPtr(), view)
                               : base::DoNothing();
-  StartSlideInAnimation(view, vertical_offset, duration,
-                        kSlideAnimationTweenType, cleanup);
+  StartSlideInAnimation(view, vertical_offset, duration, tween_type, cleanup);
+}
+
+void AppListBubbleAppsPage::FadeInContinueSectionView(views::View* view) {
+  const bool create_layer = PrepareForLayerAnimation(view);
+
+  // If we created a layer for the view, undo that when the animation ends.
+  // The underlying views don't expose weak pointers directly, so use a weak
+  // pointer to this view, which owns its children.
+  auto cleanup = create_layer ? base::BindRepeating(
+                                    &AppListBubbleAppsPage::DestroyLayerForView,
+                                    weak_factory_.GetWeakPtr(), view)
+                              : base::DoNothing();
+
+  view->layer()->SetOpacity(0.0f);
+
+  // The animation has a delay to give the separator and apps grid time to
+  // partially slide out of the way.
+  views::AnimationBuilder()
+      .OnEnded(cleanup)
+      .OnAborted(cleanup)
+      .Once()
+      .At(base::Milliseconds(100))
+      .SetOpacity(view->layer(), 1.0f)
+      .SetDuration(base::Milliseconds(200));
 }
 
 void AppListBubbleAppsPage::OnToggleContinueSection() {
+  const int separator_initial_y = separator_->y();
+
+  // Toggle the section visibility.
   bool should_hide = !view_delegate_->ShouldHideContinueSection();
   view_delegate_->SetHideContinueSection(should_hide);
   // AppListControllerImpl will trigger UpdateContinueSectionVisibility().
+
+  // Layout() will change the position of the separator and apps grid based on
+  // the visibility of the continue section view and recent apps.
+  if (needs_layout())
+    Layout();
+
+  // The vertical offset for slide animations is the difference in separator
+  // position from before the Layout() versus its position now.
+  const int vertical_offset = separator_initial_y - separator_->y();
+  const base::TimeDelta duration = base::Milliseconds(300);
+  const gfx::Tween::Type tween_type = gfx::Tween::ACCEL_LIN_DECEL_100_3;
+
+  if (should_hide) {
+    // Don't try to fade out the continue section and recent apps because the
+    // view is already invisible. UX is OK with these sections not animating.
+
+    // The separator and apps grid slide up.
+    DCHECK_GE(vertical_offset, 0);
+    SlideViewIntoPosition(separator_, vertical_offset, duration, tween_type);
+    SlideViewIntoPosition(scrollable_apps_grid_view_, vertical_offset, duration,
+                          tween_type);
+  } else {
+    // The continue section and recent apps fade in.
+    FadeInContinueSectionView(continue_section_);
+    FadeInContinueSectionView(recent_apps_);
+
+    // The separator and apps grid slide down.
+    DCHECK_LE(vertical_offset, 0);
+    SlideViewIntoPosition(separator_, vertical_offset, duration, tween_type);
+    SlideViewIntoPosition(scrollable_apps_grid_view_, vertical_offset, duration,
+                          tween_type);
+  }
 }
 
 BEGIN_METADATA(AppListBubbleAppsPage, views::View)
diff --git a/ash/app_list/views/app_list_bubble_apps_page.h b/ash/app_list/views/app_list_bubble_apps_page.h
index aaf2e85..77c2ea9 100644
--- a/ash/app_list/views/app_list_bubble_apps_page.h
+++ b/ash/app_list/views/app_list_bubble_apps_page.h
@@ -16,6 +16,7 @@
 #include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/gfx/animation/tween.h"
 #include "ui/views/view.h"
 #include "ui/views/view_observer.h"
 
@@ -214,7 +215,13 @@
   // animates back to its original position with `duration`.
   void SlideViewIntoPosition(views::View* view,
                              int vertical_offset,
-                             base::TimeDelta duration);
+                             base::TimeDelta duration,
+                             gfx::Tween::Type tween_type);
+
+  // Animates `view` using a layer fade-in animation as part of the show
+  // continue section animation. Takes `view` because the same animation is used
+  // for continue tasks and for recent apps.
+  void FadeInContinueSectionView(views::View* view);
 
   // Pressed callback for `toggle_continue_section_button_`.
   void OnToggleContinueSection();
diff --git a/ash/app_list/views/app_list_bubble_apps_page_unittest.cc b/ash/app_list/views/app_list_bubble_apps_page_unittest.cc
index 39728a1..27af8ce 100644
--- a/ash/app_list/views/app_list_bubble_apps_page_unittest.cc
+++ b/ash/app_list/views/app_list_bubble_apps_page_unittest.cc
@@ -99,14 +99,15 @@
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
   constexpr int kVerticalOffset = 20;
   constexpr base::TimeDelta kSlideDuration = base::Milliseconds(100);
+  constexpr gfx::Tween::Type kTweenType = gfx::Tween::LINEAR;
   helper->StartSlideAnimationOnBubbleAppsPage(recent_apps, kVerticalOffset,
-                                              kSlideDuration);
+                                              kSlideDuration, kTweenType);
   ASSERT_TRUE(recent_apps->layer());
   EXPECT_TRUE(recent_apps->layer()->GetAnimator()->is_animating());
 
   // While that animation is running, run another animation.
   helper->StartSlideAnimationOnBubbleAppsPage(recent_apps, kVerticalOffset,
-                                              kSlideDuration);
+                                              kSlideDuration, kTweenType);
   auto* compositor = recent_apps->layer()->GetCompositor();
   while (recent_apps->layer() &&
          recent_apps->layer()->GetAnimator()->is_animating()) {
@@ -302,6 +303,36 @@
   EXPECT_TRUE(apps_page->separator_for_test()->GetVisible());
 }
 
+TEST_F(AppListBubbleAppsPageTest, HideContinueSectionPlaysAnimation) {
+  base::test::ScopedFeatureList feature_list(
+      features::kLauncherHideContinueSection);
+
+  // Open the app list without animation.
+  ASSERT_EQ(ui::ScopedAnimationDurationScaleMode::duration_multiplier(),
+            ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+  auto* helper = GetAppListTestHelper();
+  helper->AddRecentApps(5);
+  helper->AddAppItems(5);
+  helper->ShowAppList();
+
+  // Enable animations.
+  ui::ScopedAnimationDurationScaleMode duration(
+      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
+
+  // Hide the continue section.
+  auto* apps_page = helper->GetBubbleAppsPage();
+  LeftClickOn(apps_page->toggle_continue_section_button_for_test());
+
+  // Separator and apps grid are animating.
+  auto* separator = apps_page->separator_for_test();
+  ASSERT_TRUE(separator->layer());
+  EXPECT_TRUE(separator->layer()->GetAnimator()->is_animating());
+
+  auto* apps_grid = apps_page->scrollable_apps_grid_view();
+  ASSERT_TRUE(apps_grid->layer());
+  EXPECT_TRUE(apps_grid->layer()->GetAnimator()->is_animating());
+}
+
 TEST_F(AppListBubbleAppsPageTest, CanShowContinueSectionByClickingButton) {
   base::test::ScopedFeatureList feature_list(
       features::kLauncherHideContinueSection);
@@ -339,6 +370,51 @@
   EXPECT_TRUE(apps_page->separator_for_test()->GetVisible());
 }
 
+TEST_F(AppListBubbleAppsPageTest, ShowContinueSectionPlaysAnimation) {
+  base::test::ScopedFeatureList feature_list(
+      features::kLauncherHideContinueSection);
+
+  // Simulate a user with the continue section hidden on startup.
+  Shell::Get()->app_list_controller()->SetHideContinueSection(true);
+
+  // Show the app list with enough items to make the continue section and
+  // recent apps visible.
+  auto* helper = GetAppListTestHelper();
+  helper->AddContinueSuggestionResults(4);
+  helper->AddRecentApps(5);
+  helper->AddAppItems(5);
+  helper->ShowAppList();
+
+  // Enable animations.
+  ui::ScopedAnimationDurationScaleMode duration(
+      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
+
+  // Click the show continue section button.
+  auto* apps_page = helper->GetBubbleAppsPage();
+  LeftClickOn(apps_page->toggle_continue_section_button_for_test());
+
+  // Animations play for continue section, recent apps, separator and apps grid.
+  auto* continue_section = helper->GetBubbleContinueSectionView();
+  ASSERT_TRUE(continue_section->layer());
+  EXPECT_TRUE(continue_section->layer()->GetAnimator()->is_animating());
+  EXPECT_EQ(continue_section->layer()->opacity(), 0.0f);
+  EXPECT_EQ(continue_section->layer()->GetTargetOpacity(), 1.0f);
+
+  auto* recent_apps = helper->GetBubbleRecentAppsView();
+  ASSERT_TRUE(recent_apps->layer());
+  EXPECT_TRUE(recent_apps->layer()->GetAnimator()->is_animating());
+  EXPECT_EQ(recent_apps->layer()->opacity(), 0.0f);
+  EXPECT_EQ(recent_apps->layer()->GetTargetOpacity(), 1.0f);
+
+  auto* separator = apps_page->separator_for_test();
+  ASSERT_TRUE(separator->layer());
+  EXPECT_TRUE(separator->layer()->GetAnimator()->is_animating());
+
+  auto* apps_grid = apps_page->scrollable_apps_grid_view();
+  ASSERT_TRUE(apps_grid->layer());
+  EXPECT_TRUE(apps_grid->layer()->GetAnimator()->is_animating());
+}
+
 // Regression test for https://crbug.com/1329227
 TEST_F(AppListBubbleAppsPageTest, HiddenContinueSectionDoesNotAnimateOnShow) {
   base::test::ScopedFeatureList feature_list(
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 05194d20..8acbbbc 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -5037,6 +5037,15 @@
       <message name="IDS_ASH_STATUS_TRAY_KEYBOARD_BACKLIGHT_ACCESSIBLE_NAME" desc="The accessible text for the brightness slider keyboard backlight icon.">
         Keyboard backlight color
       </message>
+
+      <!-- Eche feature -->
+      <message name="IDS_ASH_ECHE_TOAST_COPY_PASTE_NOT_IMPLEMENTED" desc="A toast message that we show when user tries to use ctrl+c or ctrl+v in the Eche window.">
+        Can't copy or paste content at this time
+      </message>
+      <message name="IDS_ASH_ECHE_TOAST_TABLET_MODE_NOT_SUPPORTED" desc="A toast message that we show when user tries to switch to tablet mode.">
+        Can't stream apps in tablet mode. Try again in laptop mode.
+      </message>
+
     </messages>
   </release>
 </grit>
diff --git a/ash/ash_strings_grd/IDS_ASH_ECHE_TOAST_COPY_PASTE_NOT_IMPLEMENTED.png.sha1 b/ash/ash_strings_grd/IDS_ASH_ECHE_TOAST_COPY_PASTE_NOT_IMPLEMENTED.png.sha1
new file mode 100644
index 0000000..0d255e0
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_ECHE_TOAST_COPY_PASTE_NOT_IMPLEMENTED.png.sha1
@@ -0,0 +1 @@
+12f71e794adad361f0ba66821795eb99d885ea23
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_ECHE_TOAST_TABLET_MODE_NOT_SUPPORTED.png.sha1 b/ash/ash_strings_grd/IDS_ASH_ECHE_TOAST_TABLET_MODE_NOT_SUPPORTED.png.sha1
new file mode 100644
index 0000000..3735922
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_ECHE_TOAST_TABLET_MODE_NOT_SUPPORTED.png.sha1
@@ -0,0 +1 @@
+e39f35d769f36adaf23fcc7bf77743ddf4cac106
\ No newline at end of file
diff --git a/ash/assistant/ui/colors/BUILD.gn b/ash/assistant/ui/colors/BUILD.gn
index 3fd7e95..c85472a 100644
--- a/ash/assistant/ui/colors/BUILD.gn
+++ b/ash/assistant/ui/colors/BUILD.gn
@@ -12,6 +12,8 @@
     "//ui/chromeos/styles/cros_palette.json5",
     "assistant_colors.json5",
   ]
+
+  cpp_namespace = "assistant_colors"
 }
 
 source_set("assistant_colors_util") {
diff --git a/ash/capture_mode/camera_video_frame_handler.cc b/ash/capture_mode/camera_video_frame_handler.cc
index 460205cc..8f6d833 100644
--- a/ash/capture_mode/camera_video_frame_handler.cc
+++ b/ash/capture_mode/camera_video_frame_handler.cc
@@ -579,6 +579,8 @@
               << static_cast<int>(reason);
 }
 
+void CameraVideoFrameHandler::OnNewCropVersion(uint32_t crop_version) {}
+
 void CameraVideoFrameHandler::OnFrameWithEmptyRegionCapture() {}
 
 void CameraVideoFrameHandler::OnLog(const std::string& message) {
diff --git a/ash/capture_mode/camera_video_frame_handler.h b/ash/capture_mode/camera_video_frame_handler.h
index 820474e..9cec9dec 100644
--- a/ash/capture_mode/camera_video_frame_handler.h
+++ b/ash/capture_mode/camera_video_frame_handler.h
@@ -94,6 +94,7 @@
   void OnBufferRetired(int buffer_id) override;
   void OnError(media::VideoCaptureError error) override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnLog(const std::string& message) override;
   void OnStarted() override;
diff --git a/ash/capture_mode/capture_mode_toast_controller.cc b/ash/capture_mode/capture_mode_toast_controller.cc
index d5e2b3a..b0aac2f 100644
--- a/ash/capture_mode/capture_mode_toast_controller.cc
+++ b/ash/capture_mode/capture_mode_toast_controller.cc
@@ -14,6 +14,7 @@
 #include "ash/style/ash_color_provider.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/compositor/layer.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/views/animation/animation_builder.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/label.h"
@@ -28,8 +29,6 @@
 constexpr int kToastVerticalPadding = 8;
 constexpr int kToastHorizontalPadding = 16;
 constexpr int kToastBorderThickness = 1;
-constexpr int kToastCornerRadius = 16;
-constexpr gfx::RoundedCornersF kToastRoundedCorners{kToastCornerRadius};
 
 // Animation duration for updating the visibility of `capture_toast_widget_`.
 constexpr base::TimeDelta kCaptureToastVisibilityChangeDuration =
@@ -169,10 +168,12 @@
   // Create the widget before init it to ensure when the window gets added to
   // the parent container, `capture_toast_widget_` is already available.
   capture_toast_widget_ = std::make_unique<views::Widget>();
+  const gfx::Rect toast_widget_screen_bounds =
+      CalculateToastWidgetScreenBounds();
   capture_toast_widget_->Init(
       CreateWidgetParams(capture_session_->current_root()->GetChildById(
                              kShellWindowId_MenuContainer),
-                         CalculateToastWidgetScreenBounds()));
+                         toast_widget_screen_bounds));
 
   // We animate the toast widget explicitly in `ShowCaptureToast()` and
   // `MaybeDismissCaptureToast()`. Any default visibility animations added by
@@ -188,8 +189,9 @@
       AshColorProvider::BaseLayerType::kTransparent80);
   toast_label_view_->SetBackground(
       views::CreateSolidBackground(background_color));
+  const float toast_corner_radius = toast_widget_screen_bounds.height() / 2.f;
   toast_label_view_->SetBorder(views::CreateRoundedRectBorder(
-      kToastBorderThickness, kToastCornerRadius,
+      kToastBorderThickness, toast_corner_radius,
       color_provider->GetControlsLayerColor(
           AshColorProvider::ControlsLayerType::kHighlightColor1)));
   toast_label_view_->SetAutoColorReadabilityEnabled(false);
@@ -202,7 +204,8 @@
   toast_label_view_->SetPaintToLayer();
   auto* label_layer = toast_label_view_->layer();
   label_layer->SetFillsBoundsOpaquely(false);
-  label_layer->SetRoundedCornerRadius(kToastRoundedCorners);
+  label_layer->SetRoundedCornerRadius(
+      gfx::RoundedCornersF(toast_corner_radius));
   label_layer->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma);
   label_layer->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality);
 
diff --git a/ash/components/arc/BUILD.gn b/ash/components/arc/BUILD.gn
index 6420ec3..5eb5133 100644
--- a/ash/components/arc/BUILD.gn
+++ b/ash/components/arc/BUILD.gn
@@ -131,6 +131,8 @@
     "//chromeos/ash/components/dbus/patchpanel:patchpanel_proto",
     "//chromeos/ash/components/dbus/session_manager",
     "//chromeos/ash/components/dbus/spaced:spaced",
+    "//chromeos/ash/components/dbus/userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/components/disks:prefs",
     "//chromeos/components/sensors:sensors",
     "//chromeos/dbus",
@@ -139,8 +141,6 @@
     "//chromeos/dbus/power",
     "//chromeos/dbus/power:power_manager_proto",
     "//chromeos/dbus/resourced",
-    "//chromeos/dbus/userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//chromeos/login/login_state",
     "//chromeos/network",
     "//chromeos/ui/frame",
@@ -455,6 +455,7 @@
     "//chromeos/ash/components/dbus/session_manager",
     "//chromeos/ash/components/dbus/session_manager:login_manager_proto",
     "//chromeos/ash/components/dbus/upstart",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/dlcservice",
     "//chromeos/dbus/permission_broker",
@@ -462,7 +463,6 @@
     "//chromeos/dbus/power:power_manager_proto",
     "//chromeos/dbus/resourced:resourced",
     "//chromeos/dbus/tpm_manager:tpm_manager",
-    "//chromeos/network:test_support",
     "//chromeos/ui/frame",
     "//components/account_id",
     "//components/exo",
diff --git a/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc b/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
index 59e755f..820cbd4 100644
--- a/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
+++ b/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
@@ -12,7 +12,7 @@
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "chromeos/ash/components/dbus/spaced/spaced_client.h"
-#include "chromeos/dbus/userdataauth/arc_quota_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/arc_quota_client.h"
 
 namespace arc {
 
diff --git a/ash/components/arc/input_overlay/resources/com.androbaby.game2048.json b/ash/components/arc/input_overlay/resources/com.androbaby.game2048.json
index e8b0d074..be8ac79d 100644
--- a/ash/components/arc/input_overlay/resources/com.androbaby.game2048.json
+++ b/ash/components/arc/input_overlay/resources/com.androbaby.game2048.json
@@ -25,7 +25,7 @@
           ],
           "anchor_to_target": [
             0.4957102,
-            0.6135164
+            0.7470961
           ]
         }
       ],
diff --git a/ash/components/arc/input_overlay/resources/com.androbaby.original2048.json b/ash/components/arc/input_overlay/resources/com.androbaby.original2048.json
index e8b0d074..be8ac79d 100644
--- a/ash/components/arc/input_overlay/resources/com.androbaby.original2048.json
+++ b/ash/components/arc/input_overlay/resources/com.androbaby.original2048.json
@@ -25,7 +25,7 @@
           ],
           "anchor_to_target": [
             0.4957102,
-            0.6135164
+            0.7470961
           ]
         }
       ],
diff --git a/ash/components/arc/input_overlay/resources/com.estoty.game2048.json b/ash/components/arc/input_overlay/resources/com.estoty.game2048.json
index e8b0d074..be8ac79d 100644
--- a/ash/components/arc/input_overlay/resources/com.estoty.game2048.json
+++ b/ash/components/arc/input_overlay/resources/com.estoty.game2048.json
@@ -25,7 +25,7 @@
           ],
           "anchor_to_target": [
             0.4957102,
-            0.6135164
+            0.7470961
           ]
         }
       ],
diff --git a/ash/components/arc/input_overlay/resources/com.gabrielecirulli.app2048.json b/ash/components/arc/input_overlay/resources/com.gabrielecirulli.app2048.json
index e8b0d074..be8ac79d 100644
--- a/ash/components/arc/input_overlay/resources/com.gabrielecirulli.app2048.json
+++ b/ash/components/arc/input_overlay/resources/com.gabrielecirulli.app2048.json
@@ -25,7 +25,7 @@
           ],
           "anchor_to_target": [
             0.4957102,
-            0.6135164
+            0.7470961
           ]
         }
       ],
diff --git a/ash/components/arc/input_overlay/resources/com.s2apps.game2048.json b/ash/components/arc/input_overlay/resources/com.s2apps.game2048.json
index e8b0d074..be8ac79d 100644
--- a/ash/components/arc/input_overlay/resources/com.s2apps.game2048.json
+++ b/ash/components/arc/input_overlay/resources/com.s2apps.game2048.json
@@ -25,7 +25,7 @@
           ],
           "anchor_to_target": [
             0.4957102,
-            0.6135164
+            0.7470961
           ]
         }
       ],
diff --git a/ash/components/arc/memory_pressure/arc_memory_pressure_bridge_unittest.cc b/ash/components/arc/memory_pressure/arc_memory_pressure_bridge_unittest.cc
index 54e7567..9d871041 100644
--- a/ash/components/arc/memory_pressure/arc_memory_pressure_bridge_unittest.cc
+++ b/ash/components/arc/memory_pressure/arc_memory_pressure_bridge_unittest.cc
@@ -61,7 +61,7 @@
       delete;
 
   ~ArcMemoryPressureBridgeTest() override {
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
     StabilityMetricsManager::Shutdown();
   }
 
@@ -80,8 +80,8 @@
       AppKillObserver& kill_observer) {
     prefs::RegisterLocalStatePrefs(local_state.registry());
     StabilityMetricsManager::Initialize(&local_state);
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
-    chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
+    ash::SessionManagerClient::InitializeFakeInMemory();
+    ash::FakeSessionManagerClient::Get()->set_arc_available(true);
     prefs::RegisterProfilePrefs(context.pref_registry());
     ArcMetricsService* const arc_metrics_service =
         ArcMetricsService::GetForBrowserContextForTesting(&context);
diff --git a/ash/components/arc/metrics/arc_metrics_service.cc b/ash/components/arc/metrics/arc_metrics_service.cc
index 6a590e6b..7fd46a281 100644
--- a/ash/components/arc/metrics/arc_metrics_service.cc
+++ b/ash/components/arc/metrics/arc_metrics_service.cc
@@ -456,7 +456,7 @@
   }
 
   // Retrieve ARC full container's start time from session manager.
-  chromeos::SessionManagerClient::Get()->GetArcStartTime(base::BindOnce(
+  ash::SessionManagerClient::Get()->GetArcStartTime(base::BindOnce(
       &ArcMetricsService::OnArcStartTimeRetrieved,
       weak_ptr_factory_.GetWeakPtr(), std::move(events), boot_type));
 
@@ -588,7 +588,7 @@
   // time, which is fetched from session manager.
   const base::TimeTicks durationTicks = duration + base::TimeTicks();
   // Retrieve ARC full container's start time from session manager.
-  chromeos::SessionManagerClient::Get()->GetArcStartTime(
+  ash::SessionManagerClient::Get()->GetArcStartTime(
       base::BindOnce(&ArcMetricsService::OnArcStartTimeForPriAbiMigration,
                      weak_ptr_factory_.GetWeakPtr(), durationTicks));
 }
diff --git a/ash/components/arc/metrics/arc_metrics_service_unittest.cc b/ash/components/arc/metrics/arc_metrics_service_unittest.cc
index aa659a6..182ca89 100644
--- a/ash/components/arc/metrics/arc_metrics_service_unittest.cc
+++ b/ash/components/arc/metrics/arc_metrics_service_unittest.cc
@@ -64,8 +64,8 @@
     prefs::RegisterLocalStatePrefs(local_state_.registry());
     StabilityMetricsManager::Initialize(&local_state_);
     chromeos::PowerManagerClient::InitializeFake();
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
-    chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
+    ash::SessionManagerClient::InitializeFakeInMemory();
+    ash::FakeSessionManagerClient::Get()->set_arc_available(true);
     chromeos::ConciergeClient::InitializeFake();
 
     // Changing the command line needs to be done here and not in
@@ -98,7 +98,7 @@
     arc_service_manager_.reset();
 
     chromeos::ConciergeClient::Shutdown();
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
     StabilityMetricsManager::Shutdown();
   }
@@ -108,8 +108,7 @@
   void SetArcStartTimeInMs(uint64_t arc_start_time_in_ms) {
     const base::TimeTicks arc_start_time =
         base::Milliseconds(arc_start_time_in_ms) + base::TimeTicks();
-    chromeos::FakeSessionManagerClient::Get()->set_arc_start_time(
-        arc_start_time);
+    ash::FakeSessionManagerClient::Get()->set_arc_start_time(arc_start_time);
   }
 
   std::vector<mojom::BootProgressEventPtr> GetBootProgressEvents(
diff --git a/ash/components/arc/net/always_on_vpn_manager_unittest.cc b/ash/components/arc/net/always_on_vpn_manager_unittest.cc
index 7432b897..6564f8be 100644
--- a/ash/components/arc/net/always_on_vpn_manager_unittest.cc
+++ b/ash/components/arc/net/always_on_vpn_manager_unittest.cc
@@ -8,8 +8,8 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/prefs/testing_pref_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/components/arc/session/arc_container_client_adapter.cc b/ash/components/arc/session/arc_container_client_adapter.cc
index bf52fe9..d92ebf38 100644
--- a/ash/components/arc/session/arc_container_client_adapter.cc
+++ b/ash/components/arc/session/arc_container_client_adapter.cc
@@ -93,13 +93,12 @@
 
 }  // namespace
 
-class ArcContainerClientAdapter
-    : public ArcClientAdapter,
-      public chromeos::SessionManagerClient::Observer {
+class ArcContainerClientAdapter : public ArcClientAdapter,
+                                  public ash::SessionManagerClient::Observer {
  public:
   ArcContainerClientAdapter() {
-    if (chromeos::SessionManagerClient::Get())
-      chromeos::SessionManagerClient::Get()->AddObserver(this);
+    if (ash::SessionManagerClient::Get())
+      ash::SessionManagerClient::Get()->AddObserver(this);
   }
 
   ArcContainerClientAdapter(const ArcContainerClientAdapter&) = delete;
@@ -107,8 +106,8 @@
       delete;
 
   ~ArcContainerClientAdapter() override {
-    if (chromeos::SessionManagerClient::Get())
-      chromeos::SessionManagerClient::Get()->RemoveObserver(this);
+    if (ash::SessionManagerClient::Get())
+      ash::SessionManagerClient::Get()->RemoveObserver(this);
   }
 
   login_manager::StartArcMiniContainerRequest
@@ -151,7 +150,7 @@
 
     auto request =
         ConvertStartParamsToStartArcMiniContainerRequest(std::move(params));
-    chromeos::SessionManagerClient::Get()->StartArcMiniContainer(
+    ash::SessionManagerClient::Get()->StartArcMiniContainer(
         request, std::move(callback));
   }
 
@@ -182,14 +181,14 @@
   void UpgradeArc(UpgradeParams params,
                   chromeos::VoidDBusMethodCallback callback) override {
     auto request = ConvertUpgradeParamsToUpgradeArcContainerRequest(params);
-    chromeos::SessionManagerClient::Get()->UpgradeArcContainer(
-        request, std::move(callback));
+    ash::SessionManagerClient::Get()->UpgradeArcContainer(request,
+                                                          std::move(callback));
   }
 
   void StopArcInstance(bool on_shutdown, bool should_backup_log) override {
     // Since we have the ArcInstanceStopped() callback, we don't need to do
     // anything when StopArcInstance completes.
-    chromeos::SessionManagerClient::Get()->StopArcInstance(
+    ash::SessionManagerClient::Get()->StopArcInstance(
         cryptohome_id_.id(), should_backup_log, base::DoNothing());
   }
 
@@ -215,7 +214,7 @@
                        /*failure_reason=*/"ARC container is not supported."));
   }
 
-  // chromeos::SessionManagerClient::Observer overrides:
+  // ash::SessionManagerClient::Observer overrides:
   void ArcInstanceStopped(
       login_manager::ArcContainerStopReason reason) override {
     const bool is_system_shutdown =
diff --git a/ash/components/arc/session/arc_container_client_adapter_unittest.cc b/ash/components/arc/session/arc_container_client_adapter_unittest.cc
index 8dbd1d3..e401a191e 100644
--- a/ash/components/arc/session/arc_container_client_adapter_unittest.cc
+++ b/ash/components/arc/session/arc_container_client_adapter_unittest.cc
@@ -24,15 +24,15 @@
       const ArcContainerClientAdapterTest&) = delete;
 
   void SetUp() override {
-    chromeos::SessionManagerClient::InitializeFake();
+    ash::SessionManagerClient::InitializeFake();
     client_adapter_ = CreateArcContainerClientAdapter();
     client_adapter_->AddObserver(this);
-    chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
+    ash::FakeSessionManagerClient::Get()->set_arc_available(true);
   }
 
   void TearDown() override {
     client_adapter_ = nullptr;
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
   }
 
   // ArcClientAdapter::Observer:
@@ -58,14 +58,14 @@
 }
 
 TEST_F(ArcContainerClientAdapterTest, ArcInstanceStopped) {
-  chromeos::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
+  ash::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
       login_manager::ArcContainerStopReason::USER_REQUEST);
   ASSERT_TRUE(is_system_shutdown().has_value());
   EXPECT_FALSE(is_system_shutdown().value());
 }
 
 TEST_F(ArcContainerClientAdapterTest, ArcInstanceStoppedSystemShutdown) {
-  chromeos::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
+  ash::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
       login_manager::ArcContainerStopReason::SESSION_MANAGER_SHUTDOWN);
   ASSERT_TRUE(is_system_shutdown().has_value());
   EXPECT_TRUE(is_system_shutdown().value());
@@ -115,7 +115,7 @@
       },
       client_adapter(), &parent_observer));
 
-  chromeos::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
+  ash::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
       login_manager::ArcContainerStopReason::USER_REQUEST);
 
   EXPECT_TRUE(parent_observer.stopped_called());
@@ -127,7 +127,7 @@
   start_params.disable_media_store_maintenance = true;
   client_adapter()->StartMiniArc(std::move(start_params),
                                  base::BindOnce(&OnMiniInstanceStarted));
-  const auto& request = chromeos::FakeSessionManagerClient::Get()
+  const auto& request = ash::FakeSessionManagerClient::Get()
                             ->last_start_arc_mini_container_request();
   EXPECT_TRUE(request.has_disable_media_store_maintenance());
   EXPECT_TRUE(request.disable_media_store_maintenance());
@@ -137,7 +137,7 @@
   StartParams start_params;
   client_adapter()->StartMiniArc(std::move(start_params),
                                  base::BindOnce(&OnMiniInstanceStarted));
-  const auto& request = chromeos::FakeSessionManagerClient::Get()
+  const auto& request = ash::FakeSessionManagerClient::Get()
                             ->last_start_arc_mini_container_request();
   EXPECT_TRUE(request.has_disable_download_provider());
   EXPECT_FALSE(request.disable_download_provider());
@@ -148,7 +148,7 @@
   start_params.disable_download_provider = true;
   client_adapter()->StartMiniArc(std::move(start_params),
                                  base::BindOnce(&OnMiniInstanceStarted));
-  const auto& request = chromeos::FakeSessionManagerClient::Get()
+  const auto& request = ash::FakeSessionManagerClient::Get()
                             ->last_start_arc_mini_container_request();
   EXPECT_TRUE(request.has_disable_download_provider());
   EXPECT_TRUE(request.disable_download_provider());
@@ -158,7 +158,7 @@
   StartParams start_params;
   client_adapter()->StartMiniArc(std::move(start_params),
                                  base::BindOnce(&OnMiniInstanceStarted));
-  const auto& request = chromeos::FakeSessionManagerClient::Get()
+  const auto& request = ash::FakeSessionManagerClient::Get()
                             ->last_start_arc_mini_container_request();
   EXPECT_TRUE(request.has_disable_ureadahead());
   EXPECT_FALSE(request.disable_ureadahead());
@@ -169,7 +169,7 @@
   start_params.disable_ureadahead = true;
   client_adapter()->StartMiniArc(std::move(start_params),
                                  base::BindOnce(&OnMiniInstanceStarted));
-  const auto& request = chromeos::FakeSessionManagerClient::Get()
+  const auto& request = ash::FakeSessionManagerClient::Get()
                             ->last_start_arc_mini_container_request();
   EXPECT_TRUE(request.has_disable_ureadahead());
   EXPECT_TRUE(request.disable_ureadahead());
@@ -179,7 +179,7 @@
   StartParams start_params;
   client_adapter()->StartMiniArc(std::move(start_params),
                                  base::BindOnce(&OnMiniInstanceStarted));
-  const auto& request = chromeos::FakeSessionManagerClient::Get()
+  const auto& request = ash::FakeSessionManagerClient::Get()
                             ->last_start_arc_mini_container_request();
   EXPECT_TRUE(request.has_enable_tts_caching());
   EXPECT_FALSE(request.enable_tts_caching());
@@ -190,7 +190,7 @@
   start_params.enable_tts_caching = true;
   client_adapter()->StartMiniArc(std::move(start_params),
                                  base::BindOnce(&OnMiniInstanceStarted));
-  const auto& request = chromeos::FakeSessionManagerClient::Get()
+  const auto& request = ash::FakeSessionManagerClient::Get()
                             ->last_start_arc_mini_container_request();
   EXPECT_TRUE(request.has_enable_tts_caching());
   EXPECT_TRUE(request.enable_tts_caching());
@@ -202,7 +202,7 @@
   client_adapter()->UpgradeArc(std::move(upgrade_params),
                                base::BindOnce(&OnMiniInstanceStarted));
   const auto& upgrade_request =
-      chromeos::FakeSessionManagerClient::Get()->last_upgrade_arc_request();
+      ash::FakeSessionManagerClient::Get()->last_upgrade_arc_request();
   EXPECT_TRUE(upgrade_request.skip_tts_cache());
 }
 
@@ -212,7 +212,7 @@
   client_adapter()->UpgradeArc(std::move(upgrade_params),
                                base::BindOnce(&OnMiniInstanceStarted));
   const auto& upgrade_request =
-      chromeos::FakeSessionManagerClient::Get()->last_upgrade_arc_request();
+      ash::FakeSessionManagerClient::Get()->last_upgrade_arc_request();
   EXPECT_FALSE(upgrade_request.skip_tts_cache());
 }
 
@@ -251,7 +251,7 @@
   start_params.dalvik_memory_profile = test_param.profile;
   client_adapter()->StartMiniArc(std::move(start_params),
                                  base::BindOnce(&OnMiniInstanceStarted));
-  const auto& request = chromeos::FakeSessionManagerClient::Get()
+  const auto& request = ash::FakeSessionManagerClient::Get()
                             ->last_start_arc_mini_container_request();
   EXPECT_TRUE(request.has_dalvik_memory_profile());
   EXPECT_EQ(test_param.expectation, request.dalvik_memory_profile());
diff --git a/ash/components/arc/session/arc_session_runner_unittest.cc b/ash/components/arc/session/arc_session_runner_unittest.cc
index 7bd3f532..c1668cb 100644
--- a/ash/components/arc/session/arc_session_runner_unittest.cc
+++ b/ash/components/arc/session/arc_session_runner_unittest.cc
@@ -61,7 +61,7 @@
   ArcSessionRunnerTest& operator=(const ArcSessionRunnerTest&) = delete;
 
   void SetUp() override {
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
 
     stop_reason_ = ArcStopReason::SHUTDOWN;
     restarting_ = false;
@@ -78,7 +78,7 @@
     arc_session_runner_->RemoveObserver(this);
     arc_session_runner_.reset();
 
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
   }
 
   ArcSessionRunner* arc_session_runner() { return arc_session_runner_.get(); }
diff --git a/ash/components/arc/session/arc_vm_client_adapter.cc b/ash/components/arc/session/arc_vm_client_adapter.cc
index fc4f565..bd4c537 100644
--- a/ash/components/arc/session/arc_vm_client_adapter.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter.cc
@@ -65,6 +65,8 @@
 #include "chromeos/system/statistics_provider.h"
 #include "components/version_info/version_info.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
 
 namespace arc {
 namespace {
@@ -504,6 +506,25 @@
   request.set_enable_consumer_auto_update_toggle(base::FeatureList::IsEnabled(
       ash::features::kConsumerAutoUpdateToggleAllowed));
 
+  auto orientation = display::Display::ROTATE_0;
+  if (auto* screen = display::Screen::GetScreen())
+    orientation = screen->GetPrimaryDisplay().panel_rotation();
+  switch (orientation) {
+    using StartArcVmRequest = vm_tools::concierge::StartArcVmRequest;
+    case display::Display::ROTATE_0:
+      request.set_panel_orientation(StartArcVmRequest::ORIENTATION_0);
+      break;
+    case display::Display::ROTATE_90:
+      request.set_panel_orientation(StartArcVmRequest::ORIENTATION_90);
+      break;
+    case display::Display::ROTATE_180:
+      request.set_panel_orientation(StartArcVmRequest::ORIENTATION_180);
+      break;
+    case display::Display::ROTATE_270:
+      request.set_panel_orientation(StartArcVmRequest::ORIENTATION_270);
+      break;
+  }
+
   return request;
 }
 
@@ -712,7 +733,7 @@
     }
 
     VLOG(1) << "Checking adb sideload status";
-    chromeos::SessionManagerClient::Get()->QueryAdbSideload(base::BindOnce(
+    ash::SessionManagerClient::Get()->QueryAdbSideload(base::BindOnce(
         &ArcVmClientAdapter::OnQueryAdbSideload, weak_factory_.GetWeakPtr(),
         std::move(params), std::move(callback)));
   }
@@ -1058,22 +1079,21 @@
   void OnQueryAdbSideload(
       UpgradeParams params,
       chromeos::VoidDBusMethodCallback callback,
-      chromeos::SessionManagerClient::AdbSideloadResponseCode response_code,
+      ash::SessionManagerClient::AdbSideloadResponseCode response_code,
       bool enabled) {
     VLOG(1) << "IsAdbSideloadAllowed, response_code="
             << static_cast<int>(response_code) << ", enabled=" << enabled;
 
     switch (response_code) {
-      case chromeos::SessionManagerClient::AdbSideloadResponseCode::FAILED:
+      case ash::SessionManagerClient::AdbSideloadResponseCode::FAILED:
         LOG(ERROR) << "Failed response from QueryAdbSideload";
         StopArcInstanceInternal();
         std::move(callback).Run(false);
         return;
-      case chromeos::SessionManagerClient::AdbSideloadResponseCode::
-          NEED_POWERWASH:
+      case ash::SessionManagerClient::AdbSideloadResponseCode::NEED_POWERWASH:
         params.is_adb_sideloading_enabled = false;
         break;
-      case chromeos::SessionManagerClient::AdbSideloadResponseCode::SUCCESS:
+      case ash::SessionManagerClient::AdbSideloadResponseCode::SUCCESS:
         params.is_adb_sideloading_enabled = enabled;
         break;
     }
diff --git a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
index 3a78146b..fc59755 100644
--- a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -397,7 +397,7 @@
         // connect_sleep_duration_initial
         base::Milliseconds(20));
 
-    chromeos::SessionManagerClient::InitializeFake();
+    ash::SessionManagerClient::InitializeFake();
 
     adapter_->SetDemoModeDelegate(&demo_mode_delegate_);
     app_host_ = std::make_unique<FakeAppHost>(arc_bridge_service()->app());
@@ -407,7 +407,7 @@
 
   void TearDown() override {
     arc_dlc_installer_.reset();
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
     adapter_->RemoveObserver(this);
     adapter_.reset();
     run_loop_.reset();
@@ -1102,8 +1102,8 @@
   StartMiniArc();
 
   // Ask the Fake Session Manager to return a failed Adb Sideload response.
-  chromeos::FakeSessionManagerClient::Get()->set_adb_sideload_response(
-      chromeos::FakeSessionManagerClient::AdbSideloadResponseCode::FAILED);
+  ash::FakeSessionManagerClient::Get()->set_adb_sideload_response(
+      ash::FakeSessionManagerClient::AdbSideloadResponseCode::FAILED);
 
   UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/2);
   ExpectArcStopped();
@@ -1115,9 +1115,8 @@
 
   // Ask the Fake Session Manager to return a Need_Powerwash Adb Sideload
   // response.
-  chromeos::FakeSessionManagerClient::Get()->set_adb_sideload_response(
-      chromeos::FakeSessionManagerClient::AdbSideloadResponseCode::
-          NEED_POWERWASH);
+  ash::FakeSessionManagerClient::Get()->set_adb_sideload_response(
+      ash::FakeSessionManagerClient::AdbSideloadResponseCode::NEED_POWERWASH);
   UpgradeArc(true);
   EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
   EXPECT_FALSE(is_system_shutdown().has_value());
@@ -1140,7 +1139,7 @@
 TEST_F(ArcVmClientAdapterTest, UpgradeArc_AdbSideloadingPropertyEnabled) {
   StartMiniArc();
 
-  chromeos::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(true);
+  ash::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(true);
   UpgradeArc(true);
   EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
   EXPECT_FALSE(is_system_shutdown().has_value());
@@ -1151,7 +1150,7 @@
 TEST_F(ArcVmClientAdapterTest, UpgradeArc_AdbSideloadingPropertyDisabled) {
   StartMiniArc();
 
-  chromeos::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(false);
+  ash::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(false);
   UpgradeArc(true);
   EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
   EXPECT_FALSE(is_system_shutdown().has_value());
diff --git a/ash/components/cryptohome/BUILD.gn b/ash/components/cryptohome/BUILD.gn
index 1230fcb..e97a6683 100644
--- a/ash/components/cryptohome/BUILD.gn
+++ b/ash/components/cryptohome/BUILD.gn
@@ -12,11 +12,11 @@
   deps = [
     "//ash/components/login/auth:challenge_response_key",
     "//base",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus/common",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
-    "//chromeos/dbus/userdataauth:userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//components/account_id",
     "//components/device_event_log",
     "//components/user_manager",
@@ -40,10 +40,10 @@
     "//ash/components/login/auth:challenge_response_key",
     "//base",
     "//base/test:test_support",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
-    "//chromeos/dbus/userdataauth:userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//testing/gtest:gtest",
   ]
   sources = [
diff --git a/ash/components/cryptohome/DEPS b/ash/components/cryptohome/DEPS
index ca6fa87..581eddf 100644
--- a/ash/components/cryptohome/DEPS
+++ b/ash/components/cryptohome/DEPS
@@ -3,6 +3,7 @@
 include_rules = [
   "+ash/components/login/auth",
   "+base",
+  "+chromeos/ash/components/dbus",
   "+chromeos/dbus",
   "+components/account_id",
   "+components/device_event_log",
diff --git a/ash/components/cryptohome/system_salt_getter.cc b/ash/components/cryptohome/system_salt_getter.cc
index 7080667..41c34c8 100644
--- a/ash/components/cryptohome/system_salt_getter.cc
+++ b/ash/components/cryptohome/system_salt_getter.cc
@@ -15,7 +15,7 @@
 #include "base/strings/string_util.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 
 namespace ash {
 
diff --git a/ash/components/cryptohome/system_salt_getter_unittest.cc b/ash/components/cryptohome/system_salt_getter_unittest.cc
index 94972d9..06831fa 100644
--- a/ash/components/cryptohome/system_salt_getter_unittest.cc
+++ b/ash/components/cryptohome/system_salt_getter_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
diff --git a/ash/components/device_activity/BUILD.gn b/ash/components/device_activity/BUILD.gn
index 65c9fe24..2e6ad36 100644
--- a/ash/components/device_activity/BUILD.gn
+++ b/ash/components/device_activity/BUILD.gn
@@ -68,8 +68,8 @@
     "//base/test:test_support",
     "//chromeos/ash/components/dbus/session_manager:session_manager",
     "//chromeos/ash/components/dbus/system_clock:system_clock",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/network",
-    "//chromeos/network:test_support",
     "//chromeos/system:system",
     "//components/policy/core/common:test_support",
     "//components/prefs:test_support",
diff --git a/ash/components/device_activity/device_activity_client_unittest.cc b/ash/components/device_activity/device_activity_client_unittest.cc
index 5eb992f..bf4371f9 100644
--- a/ash/components/device_activity/device_activity_client_unittest.cc
+++ b/ash/components/device_activity/device_activity_client_unittest.cc
@@ -20,8 +20,8 @@
 #include "base/time/time.h"
 #include "base/timer/mock_timer.h"
 #include "chromeos/ash/components/dbus/system_clock/system_clock_client.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state_handler_observer.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/version_info/channel.h"
diff --git a/ash/components/device_activity/device_activity_controller.cc b/ash/components/device_activity/device_activity_controller.cc
index c6004bc..5cc413b 100644
--- a/ash/components/device_activity/device_activity_controller.cc
+++ b/ash/components/device_activity/device_activity_controller.cc
@@ -194,11 +194,10 @@
 
   // Wrap with callback from |psm_device_active_secret_| retrieval using
   // |SessionManagerClient| DBus.
-  chromeos::SessionManagerClient::Get()->GetPsmDeviceActiveSecret(
-      base::BindOnce(&device_activity::DeviceActivityController::
-                         OnPsmDeviceActiveSecretFetched,
-                     weak_factory_.GetWeakPtr(), local_state,
-                     url_loader_factory));
+  SessionManagerClient::Get()->GetPsmDeviceActiveSecret(base::BindOnce(
+      &device_activity::DeviceActivityController::
+          OnPsmDeviceActiveSecretFetched,
+      weak_factory_.GetWeakPtr(), local_state, url_loader_factory));
 }
 
 void DeviceActivityController::OnPsmDeviceActiveSecretFetched(
diff --git a/ash/components/device_activity/device_activity_controller_unittest.cc b/ash/components/device_activity/device_activity_controller_unittest.cc
index 3db349b..ad08c12a 100644
--- a/ash/components/device_activity/device_activity_controller_unittest.cc
+++ b/ash/components/device_activity/device_activity_controller_unittest.cc
@@ -45,7 +45,7 @@
  protected:
   // testing::Test:
   void SetUp() override {
-    chromeos::SessionManagerClient::InitializeFake();
+    SessionManagerClient::InitializeFake();
     chromeos::system::StatisticsProvider::SetTestProvider(
         &statistics_provider_);
 
diff --git a/ash/components/drivefs/drivefs_host.cc b/ash/components/drivefs/drivefs_host.cc
index aee66b6..605301e 100644
--- a/ash/components/drivefs/drivefs_host.cc
+++ b/ash/components/drivefs/drivefs_host.cc
@@ -199,6 +199,21 @@
     http_client_->ExecuteHttpRequest(std::move(request), std::move(delegate));
   }
 
+  void GetMachineRootID(GetMachineRootIDCallback callback) override {
+    if (!chromeos::features::IsDriveFsMirroringEnabled()) {
+      std::move(callback).Run({});
+      return;
+    }
+    std::move(callback).Run(host_->delegate_->GetMachineRootID());
+  }
+
+  void PersistMachineRootID(const std::string& id) override {
+    if (!chromeos::features::IsDriveFsMirroringEnabled()) {
+      return;
+    }
+    host_->delegate_->PersistMachineRootID(std::move(id));
+  }
+
   // DriveNotificationObserver overrides:
   void OnNotificationReceived(
       const std::map<std::string, int64_t>& invalidations) override {
diff --git a/ash/components/drivefs/drivefs_host.h b/ash/components/drivefs/drivefs_host.h
index d7f1bcc..eb6479d 100644
--- a/ash/components/drivefs/drivefs_host.h
+++ b/ash/components/drivefs/drivefs_host.h
@@ -71,6 +71,8 @@
         mojom::ExtensionConnectionParamsPtr params,
         mojo::PendingReceiver<mojom::NativeMessagingPort> port,
         mojo::PendingRemote<mojom::NativeMessagingHost> host) = 0;
+    virtual const std::string GetMachineRootID() = 0;
+    virtual void PersistMachineRootID(const std::string& id) = 0;
   };
 
   DriveFsHost(const base::FilePath& profile_path,
diff --git a/ash/components/drivefs/drivefs_host_unittest.cc b/ash/components/drivefs/drivefs_host_unittest.cc
index fd310da16..d28fafa 100644
--- a/ash/components/drivefs/drivefs_host_unittest.cc
+++ b/ash/components/drivefs/drivefs_host_unittest.cc
@@ -179,6 +179,10 @@
         kExtensionNotFound;
   }
 
+  const std::string GetMachineRootID() override { return ""; }
+
+  void PersistMachineRootID(const std::string& id) override {}
+
   signin::IdentityManager* const identity_manager_;
   const AccountId account_id_;
   mojo::PendingRemote<mojom::DriveFsBootstrap> pending_bootstrap_;
diff --git a/ash/components/drivefs/drivefs_session_unittest.cc b/ash/components/drivefs/drivefs_session_unittest.cc
index 72bf3365..af96201 100644
--- a/ash/components/drivefs/drivefs_session_unittest.cc
+++ b/ash/components/drivefs/drivefs_session_unittest.cc
@@ -248,6 +248,9 @@
   void ExecuteHttpRequest(
       mojom::HttpRequestPtr request,
       mojo::PendingRemote<mojom::HttpDelegate> delegate) override {}
+  void GetMachineRootID(
+      mojom::DriveFsDelegate::GetMachineRootIDCallback callback) override {}
+  void PersistMachineRootID(const std::string& id) override {}
 };
 
 class DriveFsSessionTest : public ::testing::Test,
diff --git a/ash/components/drivefs/mojom/drivefs.mojom b/ash/components/drivefs/mojom/drivefs.mojom
index 8d6f44e3..6aca7cd 100644
--- a/ash/components/drivefs/mojom/drivefs.mojom
+++ b/ash/components/drivefs/mojom/drivefs.mojom
@@ -184,6 +184,14 @@
   // calls the necessary callbacks on the |delegate|.
   ExecuteHttpRequest(
     HttpRequest request, pending_remote<HttpDelegate> delegate);
+
+  // On startup, retrieve the machine ID to ensure Chromebook is reassociated
+  // with an existing Computers root based on `doc_id`. If no ID is available it
+  // will return an empty string.
+  GetMachineRootID() => (string doc_id);
+
+  // Invoked when the machine ID is calculated to store in Chrome device prefs.
+  PersistMachineRootID(string doc_id);
 };
 
 // Next MinVersion: 7
diff --git a/ash/components/geolocation/BUILD.gn b/ash/components/geolocation/BUILD.gn
index b418228..82424210 100644
--- a/ash/components/geolocation/BUILD.gn
+++ b/ash/components/geolocation/BUILD.gn
@@ -34,8 +34,8 @@
     ":geolocation",
     "//base",
     "//base/test:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus/shill",
-    "//chromeos/network:test_support",
     "//net",
     "//services/network:test_support",
     "//services/network/public/cpp",
diff --git a/ash/components/geolocation/DEPS b/ash/components/geolocation/DEPS
index 4fd7074..1486f32 100644
--- a/ash/components/geolocation/DEPS
+++ b/ash/components/geolocation/DEPS
@@ -2,6 +2,7 @@
 
 include_rules = [
   "+base",
+  "+chromeos/ash/components/network",
   "+chromeos/network",
   "+google_apis",
   "+services/network/public/cpp",
diff --git a/ash/components/geolocation/simple_geolocation_unittest.cc b/ash/components/geolocation/simple_geolocation_unittest.cc
index 05c8b18f..739b7d74 100644
--- a/ash/components/geolocation/simple_geolocation_unittest.cc
+++ b/ash/components/geolocation/simple_geolocation_unittest.cc
@@ -14,9 +14,9 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/geolocation_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
diff --git a/ash/components/hid_detection/hid_detection_manager_impl.cc b/ash/components/hid_detection/hid_detection_manager_impl.cc
index df16d0c..9e75da3 100644
--- a/ash/components/hid_detection/hid_detection_manager_impl.cc
+++ b/ash/components/hid_detection/hid_detection_manager_impl.cc
@@ -4,6 +4,7 @@
 
 #include "ash/components/hid_detection/hid_detection_manager_impl.h"
 
+#include "ash/components/hid_detection/bluetooth_hid_detector_impl.h"
 #include "ash/components/hid_detection/hid_detection_utils.h"
 #include "base/no_destructor.h"
 #include "components/device_event_log/device_event_log.h"
@@ -25,10 +26,9 @@
 }
 
 HidDetectionManagerImpl::HidDetectionManagerImpl(
-    device::mojom::DeviceService* device_service,
-    BluetoothHidDetector* bluetooth_hid_detector)
+    device::mojom::DeviceService* device_service)
     : device_service_{device_service},
-      bluetooth_hid_detector_{bluetooth_hid_detector} {}
+      bluetooth_hid_detector_{std::make_unique<BluetoothHidDetectorImpl>()} {}
 
 HidDetectionManagerImpl::~HidDetectionManagerImpl() = default;
 
@@ -252,4 +252,9 @@
        .keyboard_is_missing = !connected_keyboard_id_.has_value()});
 }
 
+void HidDetectionManagerImpl::SetBluetoothHidDetectorForTest(
+    std::unique_ptr<BluetoothHidDetector> bluetooth_hid_detector) {
+  bluetooth_hid_detector_ = std::move(bluetooth_hid_detector);
+}
+
 }  // namespace ash::hid_detection
diff --git a/ash/components/hid_detection/hid_detection_manager_impl.h b/ash/components/hid_detection/hid_detection_manager_impl.h
index 131a584..151db2e 100644
--- a/ash/components/hid_detection/hid_detection_manager_impl.h
+++ b/ash/components/hid_detection/hid_detection_manager_impl.h
@@ -31,11 +31,13 @@
   static void SetInputDeviceManagerBinderForTest(
       InputDeviceManagerBinder binder);
 
-  HidDetectionManagerImpl(device::mojom::DeviceService* device_service,
-                          BluetoothHidDetector* bluetooth_hid_detector);
+  explicit HidDetectionManagerImpl(
+      device::mojom::DeviceService* device_service);
   ~HidDetectionManagerImpl() override;
 
  private:
+  friend class HidDetectionManagerImplTest;
+
   // HidDetectionManager:
   void GetIsHidDetectionRequired(
       base::OnceCallback<void(bool)> callback) override;
@@ -91,6 +93,10 @@
   // Informs |bluetooth_hid_detector_| what devices are missing.
   void SetInputDevicesStatus();
 
+  // Allows tests to override the BluetoothHidDetector implementation used.
+  void SetBluetoothHidDetectorForTest(
+      std::unique_ptr<BluetoothHidDetector> bluetooth_hid_detector);
+
   std::map<std::string, device::mojom::InputDeviceInfoPtr>
       device_id_to_device_map_;
   absl::optional<std::string> connected_touchscreen_id_;
@@ -98,7 +104,7 @@
   absl::optional<std::string> connected_keyboard_id_;
 
   device::mojom::DeviceService* device_service_ = nullptr;
-  BluetoothHidDetector* bluetooth_hid_detector_ = nullptr;
+  std::unique_ptr<BluetoothHidDetector> bluetooth_hid_detector_;
   mojo::Remote<device::mojom::InputDeviceManager> input_device_manager_;
   mojo::AssociatedReceiver<device::mojom::InputDeviceManagerClient>
       input_device_manager_receiver_{this};
diff --git a/ash/components/hid_detection/hid_detection_manager_impl_unittest.cc b/ash/components/hid_detection/hid_detection_manager_impl_unittest.cc
index cffc90d..5533faf9 100644
--- a/ash/components/hid_detection/hid_detection_manager_impl_unittest.cc
+++ b/ash/components/hid_detection/hid_detection_manager_impl_unittest.cc
@@ -73,9 +73,13 @@
   void SetUp() override {
     scoped_feature_list_.InitAndEnableFeature(
         ash::features::kOobeHidDetectionRevamp);
-    fake_bluetooth_hid_detector_ = std::make_unique<FakeBluetoothHidDetector>();
+    auto fake_bluetooth_hid_detector =
+        std::make_unique<FakeBluetoothHidDetector>();
+    fake_bluetooth_hid_detector_ = fake_bluetooth_hid_detector.get();
     hid_detection_manager_ = std::make_unique<HidDetectionManagerImpl>(
-        /*device_service=*/nullptr, fake_bluetooth_hid_detector_.get());
+        /*device_service=*/nullptr);
+    hid_detection_manager_->SetBluetoothHidDetectorForTest(
+        std::move(fake_bluetooth_hid_detector));
 
     HidDetectionManagerImpl::SetInputDeviceManagerBinderForTest(
         base::BindRepeating(&device::FakeInputServiceLinux::Bind,
@@ -223,9 +227,10 @@
   size_t num_devices_created_ = 0;
 
   FakeHidDetectionManagerDelegate delegate_;
-  std::unique_ptr<FakeBluetoothHidDetector> fake_bluetooth_hid_detector_;
+  FakeBluetoothHidDetector* fake_bluetooth_hid_detector_ = nullptr;
 
-  std::unique_ptr<hid_detection::HidDetectionManager> hid_detection_manager_;
+  std::unique_ptr<hid_detection::HidDetectionManagerImpl>
+      hid_detection_manager_;
 };
 
 TEST_F(HidDetectionManagerImplTest,
diff --git a/ash/components/login/auth/BUILD.gn b/ash/components/login/auth/BUILD.gn
index 650037d..73b5f17c 100644
--- a/ash/components/login/auth/BUILD.gn
+++ b/ash/components/login/auth/BUILD.gn
@@ -19,11 +19,11 @@
     "//chromeos/ash/components/dbus/authpolicy",
     "//chromeos/ash/components/dbus/authpolicy:authpolicy_proto",
     "//chromeos/ash/components/dbus/session_manager",
+    "//chromeos/ash/components/dbus/userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus/constants",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
-    "//chromeos/dbus/userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//chromeos/login/login_state",
     "//chromeos/metrics",
     "//components/account_id",
@@ -106,7 +106,7 @@
   deps = [
     ":auth",
     "//base",
-    "//chromeos/dbus/userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth",
     "//chromeos/login/login_state",
     "//components/account_id",
     "//google_apis",
@@ -147,10 +147,10 @@
     "//base:i18n",
     "//chromeos/ash/components/dbus/authpolicy",
     "//chromeos/ash/components/dbus/authpolicy:authpolicy_proto",
+    "//chromeos/ash/components/dbus/userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:test_support",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus/cryptohome",
-    "//chromeos/dbus/userdataauth",
-    "//chromeos/dbus/userdataauth:test_support",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//components/prefs",
     "//components/prefs:test_support",
     "//net",
diff --git a/ash/components/login/auth/auth_factor_editor.cc b/ash/components/login/auth/auth_factor_editor.cc
index 775a268..d1899f0 100644
--- a/ash/components/login/auth/auth_factor_editor.cc
+++ b/ash/components/login/auth/auth_factor_editor.cc
@@ -13,7 +13,7 @@
 #include "ash/constants/ash_features.h"
 #include "base/bind.h"
 #include "base/callback.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "components/device_event_log/device_event_log.h"
 
 namespace ash {
diff --git a/ash/components/login/auth/auth_performer.cc b/ash/components/login/auth/auth_performer.cc
index 9b56c2c..5415fc88 100644
--- a/ash/components/login/auth/auth_performer.cc
+++ b/ash/components/login/auth/auth_performer.cc
@@ -12,8 +12,8 @@
 #include "ash/components/login/auth/user_context.h"
 #include "base/bind.h"
 #include "base/callback.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/key.pb.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/device_event_log/device_event_log.h"
 
 namespace ash {
diff --git a/ash/components/login/auth/auth_performer.h b/ash/components/login/auth/auth_performer.h
index 201a455..0e91818 100644
--- a/ash/components/login/auth/auth_performer.h
+++ b/ash/components/login/auth/auth_performer.h
@@ -13,8 +13,8 @@
 #include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
diff --git a/ash/components/login/auth/auth_performer_unittest.cc b/ash/components/login/auth/auth_performer_unittest.cc
index 99c8f2f4..a2915642 100644
--- a/ash/components/login/auth/auth_performer_unittest.cc
+++ b/ash/components/login/auth/auth_performer_unittest.cc
@@ -15,10 +15,10 @@
 #include "base/memory/raw_ptr.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/mock_userdataauth_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/ash/components/login/auth/auth_session_authenticator.cc b/ash/components/login/auth/auth_session_authenticator.cc
index a82417e..95d5fec9 100644
--- a/ash/components/login/auth/auth_session_authenticator.cc
+++ b/ash/components/login/auth/auth_session_authenticator.cc
@@ -18,8 +18,8 @@
 #include "base/debug/crash_logging.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/notreached.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/device_event_log/device_event_log.h"
 #include "components/user_manager/known_user.h"
 #include "components/user_manager/user_names.h"
diff --git a/ash/components/login/auth/cryptohome_authenticator.cc b/ash/components/login/auth/cryptohome_authenticator.cc
index bf0cf6d..68caaeef 100644
--- a/ash/components/login/auth/cryptohome_authenticator.cc
+++ b/ash/components/login/auth/cryptohome_authenticator.cc
@@ -26,8 +26,8 @@
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_macros.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/metrics/login_event_recorder.h"
 #include "components/account_id/account_id.h"
diff --git a/ash/components/login/auth/extended_authenticator_impl.cc b/ash/components/login/auth/extended_authenticator_impl.cc
index c1b996ca..3b0848f 100644
--- a/ash/components/login/auth/extended_authenticator_impl.cc
+++ b/ash/components/login/auth/extended_authenticator_impl.cc
@@ -17,7 +17,7 @@
 #include "base/bind.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/metrics/login_event_recorder.h"
 #include "components/account_id/account_id.h"
 #include "crypto/sha2.h"
diff --git a/ash/components/login/auth/mock_auth_performer.h b/ash/components/login/auth/mock_auth_performer.h
index 76ca0e8..04afc15 100644
--- a/ash/components/login/auth/mock_auth_performer.h
+++ b/ash/components/login/auth/mock_auth_performer.h
@@ -7,7 +7,7 @@
 
 #include "ash/components/login/auth/auth_performer.h"
 #include "ash/components/login/auth/user_context.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace ash {
diff --git a/ash/components/login/auth/mount_performer.cc b/ash/components/login/auth/mount_performer.cc
index d7f6d3f6..6c16b522 100644
--- a/ash/components/login/auth/mount_performer.cc
+++ b/ash/components/login/auth/mount_performer.cc
@@ -10,7 +10,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/command_line.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "components/device_event_log/device_event_log.h"
 
 namespace ash {
diff --git a/ash/components/login/session/BUILD.gn b/ash/components/login/session/BUILD.gn
index b4a3dc56..8ed3f25 100644
--- a/ash/components/login/session/BUILD.gn
+++ b/ash/components/login/session/BUILD.gn
@@ -12,11 +12,11 @@
   deps = [
     "//base",
     "//chromeos/ash/components/dbus/session_manager",
+    "//chromeos/ash/components/dbus/userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus/cryptohome:cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
     "//chromeos/dbus/power:power",
-    "//chromeos/dbus/userdataauth:userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//third_party/protobuf:protobuf_lite",
   ]
   sources = [
@@ -31,9 +31,9 @@
     "//ash/components/login/session:session",
     "//base",
     "//chromeos/ash/components/dbus/session_manager",
+    "//chromeos/ash/components/dbus/userdataauth",
     "//chromeos/dbus/cryptohome:cryptohome",
     "//chromeos/dbus/power:power",
-    "//chromeos/dbus/userdataauth:userdataauth",
     "//testing/gtest",
   ]
   sources = [ "session_termination_manager_unittest.cc" ]
diff --git a/ash/components/login/session/session_termination_manager.cc b/ash/components/login/session/session_termination_manager.cc
index e597795..72fe796 100644
--- a/ash/components/login/session/session_termination_manager.cc
+++ b/ash/components/login/session/session_termination_manager.cc
@@ -7,8 +7,8 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace ash {
diff --git a/ash/components/login/session/session_termination_manager_unittest.cc b/ash/components/login/session/session_termination_manager_unittest.cc
index 1188ae70..ae9c1fd7 100644
--- a/ash/components/login/session/session_termination_manager_unittest.cc
+++ b/ash/components/login/session/session_termination_manager_unittest.cc
@@ -5,8 +5,8 @@
 #include "ash/components/login/session/session_termination_manager.h"
 
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
diff --git a/ash/components/phonehub/BUILD.gn b/ash/components/phonehub/BUILD.gn
index 5b5e56b..ce56ddf1 100644
--- a/ash/components/phonehub/BUILD.gn
+++ b/ash/components/phonehub/BUILD.gn
@@ -138,6 +138,7 @@
     "//chromeos/dbus/power",
     "//chromeos/services/network_config",
     "//chromeos/services/network_config:in_process_instance",
+    "//chromeos/services/network_config/public/cpp",
     "//components/keyed_service/core",
     "//components/prefs",
     "//components/session_manager/core",
@@ -277,9 +278,9 @@
     "//ash/webui/eche_app_ui:eche_app_ui_pref",
     "//base",
     "//base/test:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus/power",
     "//chromeos/network:network",
-    "//chromeos/network:test_support",
     "//chromeos/services/network_config:in_process_instance",
     "//chromeos/services/network_config/public/cpp:test_support",
     "//components/prefs:test_support",
diff --git a/ash/components/phonehub/tether_controller_impl.h b/ash/components/phonehub/tether_controller_impl.h
index 78d1076..2e2a31e 100644
--- a/ash/components/phonehub/tether_controller_impl.h
+++ b/ash/components/phonehub/tether_controller_impl.h
@@ -9,7 +9,7 @@
 #include "ash/components/phonehub/tether_controller.h"
 #include "ash/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
 #include "base/memory/weak_ptr.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 namespace ash {
@@ -33,7 +33,7 @@
     : public TetherController,
       public PhoneModel::Observer,
       public multidevice_setup::MultiDeviceSetupClient::Observer,
-      public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+      public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   TetherControllerImpl(
       PhoneModel* phone_model,
@@ -132,14 +132,8 @@
   void OnActiveNetworksChanged(
       std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
           networks) override;
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
-      override {}
   void OnNetworkStateListChanged() override;
   void OnDeviceStateListChanged() override;
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
   void AttemptTurningOnTethering();
   void OnSetFeatureEnabled(bool success);
diff --git a/ash/components/phonehub/tether_controller_impl_unittest.cc b/ash/components/phonehub/tether_controller_impl_unittest.cc
index fcf919d..7e4a601 100644
--- a/ash/components/phonehub/tether_controller_impl_unittest.cc
+++ b/ash/components/phonehub/tether_controller_impl_unittest.cc
@@ -15,8 +15,8 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/services/network_config/in_process_instance.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/components/proximity_auth/screenlock_bridge.cc b/ash/components/proximity_auth/screenlock_bridge.cc
index 199f3a1..edbe3e7 100644
--- a/ash/components/proximity_auth/screenlock_bridge.cc
+++ b/ash/components/proximity_auth/screenlock_bridge.cc
@@ -148,7 +148,7 @@
 }
 
 void ScreenlockBridge::Lock() {
-  chromeos::SessionManagerClient::Get()->RequestLockScreen();
+  ash::SessionManagerClient::Get()->RequestLockScreen();
 }
 
 void ScreenlockBridge::Unlock(const AccountId& account_id) {
diff --git a/ash/components/tether/BUILD.gn b/ash/components/tether/BUILD.gn
index 25616c9b..d67fd53 100644
--- a/ash/components/tether/BUILD.gn
+++ b/ash/components/tether/BUILD.gn
@@ -208,7 +208,7 @@
     "//ash/services/secure_channel/public/cpp/shared",
     "//base",
     "//base/test:test_support",
-    "//chromeos/network:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//device/bluetooth",
     "//testing/gmock",
     "//testing/gtest",
@@ -275,9 +275,9 @@
     "//ash/services/secure_channel/public/cpp/client:test_support",
     "//ash/services/secure_channel/public/cpp/shared",
     "//base/test:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus/power",
     "//chromeos/login/login_state",
-    "//chromeos/network:test_support",
     "//components/prefs:test_support",
     "//components/session_manager/core",
     "//components/sync_preferences:test_support",
diff --git a/ash/components/tether/active_host_network_state_updater_unittest.cc b/ash/components/tether/active_host_network_state_updater_unittest.cc
index 2340217a..894d5ed 100644
--- a/ash/components/tether/active_host_network_state_updater_unittest.cc
+++ b/ash/components/tether/active_host_network_state_updater_unittest.cc
@@ -10,9 +10,9 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/ash/components/tether/connection_preserver_impl_unittest.cc b/ash/components/tether/connection_preserver_impl_unittest.cc
index e0f8f20..936c79b 100644
--- a/ash/components/tether/connection_preserver_impl_unittest.cc
+++ b/ash/components/tether/connection_preserver_impl_unittest.cc
@@ -19,9 +19,9 @@
 #include "base/memory/ptr_util.h"
 #include "base/test/task_environment.h"
 #include "base/timer/mock_timer.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/ash/components/tether/crash_recovery_manager_impl_unittest.cc b/ash/components/tether/crash_recovery_manager_impl_unittest.cc
index 795d8c8..e247a58 100644
--- a/ash/components/tether/crash_recovery_manager_impl_unittest.cc
+++ b/ash/components/tether/crash_recovery_manager_impl_unittest.cc
@@ -14,8 +14,8 @@
 #include "ash/components/tether/host_scan_cache_entry.h"
 #include "base/bind.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
 
diff --git a/ash/components/tether/host_scan_scheduler_impl_unittest.cc b/ash/components/tether/host_scan_scheduler_impl_unittest.cc
index c1c7b0af..81e6e83 100644
--- a/ash/components/tether/host_scan_scheduler_impl_unittest.cc
+++ b/ash/components/tether/host_scan_scheduler_impl_unittest.cc
@@ -15,11 +15,11 @@
 #include "base/test/task_environment.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/timer/mock_timer.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/network_type_pattern.h"
 #include "components/session_manager/core/session_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/ash/components/tether/host_scanner_impl_unittest.cc b/ash/components/tether/host_scanner_impl_unittest.cc
index 78ae6b6..d22d2ac5 100644
--- a/ash/components/tether/host_scanner_impl_unittest.cc
+++ b/ash/components/tether/host_scanner_impl_unittest.cc
@@ -28,7 +28,7 @@
 #include "base/test/simple_test_clock.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chromeos/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "components/session_manager/core/session_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/ash/components/tether/network_configuration_remover_unittest.cc b/ash/components/tether/network_configuration_remover_unittest.cc
index ea0a3e9b..557375ce 100644
--- a/ash/components/tether/network_configuration_remover_unittest.cc
+++ b/ash/components/tether/network_configuration_remover_unittest.cc
@@ -7,7 +7,7 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
-#include "chromeos/network/mock_managed_network_configuration_handler.h"
+#include "chromeos/ash/components/network/mock_managed_network_configuration_handler.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/tether/network_host_scan_cache_unittest.cc b/ash/components/tether/network_host_scan_cache_unittest.cc
index 0b21fcdc..16b9f0e 100644
--- a/ash/components/tether/network_host_scan_cache_unittest.cc
+++ b/ash/components/tether/network_host_scan_cache_unittest.cc
@@ -13,9 +13,9 @@
 #include "ash/components/tether/mock_tether_host_response_recorder.h"
 #include "base/containers/contains.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/tether/notification_remover_unittest.cc b/ash/components/tether/notification_remover_unittest.cc
index 54016bf..af55549 100644
--- a/ash/components/tether/notification_remover_unittest.cc
+++ b/ash/components/tether/notification_remover_unittest.cc
@@ -13,7 +13,7 @@
 #include "ash/components/tether/fake_notification_presenter.h"
 #include "ash/components/tether/host_scan_test_util.h"
 #include "base/test/task_environment.h"
-#include "chromeos/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
 
diff --git a/ash/components/tether/tether_connector_impl_unittest.cc b/ash/components/tether/tether_connector_impl_unittest.cc
index d162f4b..28f1833 100644
--- a/ash/components/tether/tether_connector_impl_unittest.cc
+++ b/ash/components/tether/tether_connector_impl_unittest.cc
@@ -26,10 +26,10 @@
 #include "base/memory/ptr_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/ash/components/tether/tether_network_disconnection_handler_unittest.cc b/ash/components/tether/tether_network_disconnection_handler_unittest.cc
index fc0b29f..840d2e3 100644
--- a/ash/components/tether/tether_network_disconnection_handler_unittest.cc
+++ b/ash/components/tether/tether_network_disconnection_handler_unittest.cc
@@ -16,9 +16,9 @@
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_simple_task_runner.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
 
diff --git a/ash/components/tether/wifi_hotspot_connector_unittest.cc b/ash/components/tether/wifi_hotspot_connector_unittest.cc
index a57a26d..7e633bde 100644
--- a/ash/components/tether/wifi_hotspot_connector_unittest.cc
+++ b/ash/components/tether/wifi_hotspot_connector_unittest.cc
@@ -17,10 +17,10 @@
 #include "base/test/test_simple_task_runner.h"
 #include "base/timer/mock_timer.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/shill_property_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/components/tether/wifi_hotspot_disconnector_impl_unittest.cc b/ash/components/tether/wifi_hotspot_disconnector_impl_unittest.cc
index bdfc59f..c2b3a438 100644
--- a/ash/components/tether/wifi_hotspot_disconnector_impl_unittest.cc
+++ b/ash/components/tether/wifi_hotspot_disconnector_impl_unittest.cc
@@ -11,10 +11,10 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/components/tpm/BUILD.gn b/ash/components/tpm/BUILD.gn
index 4a20489..0a3f46b 100644
--- a/ash/components/tpm/BUILD.gn
+++ b/ash/components/tpm/BUILD.gn
@@ -20,13 +20,13 @@
     ":buildflags",
     "//ash/components/cryptohome",
     "//base",
+    "//chromeos/ash/components/dbus/userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus/constants",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
     "//chromeos/dbus/tpm_manager",
     "//chromeos/dbus/tpm_manager:tpm_manager_proto",
-    "//chromeos/dbus/userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//chromeos/login/login_state",
     "//components/account_id",
     "//components/policy/core/common:common_constants",
@@ -66,14 +66,14 @@
     ":tpm",
     "//ash/components/cryptohome",
     "//base/test:test_support",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/constants",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
     "//chromeos/dbus/tpm_manager",
     "//chromeos/dbus/tpm_manager:tpm_manager_proto",
-    "//chromeos/dbus/userdataauth:userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//components/policy/proto",
     "//google_apis",
     "//testing/gtest",
diff --git a/ash/components/tpm/DEPS b/ash/components/tpm/DEPS
index 66bbcb8f..79f0fe5 100644
--- a/ash/components/tpm/DEPS
+++ b/ash/components/tpm/DEPS
@@ -5,6 +5,7 @@
   "+base",
   "+crypto",
   "+chromeos/login/login_state",
+  "+chromeos/ash/components/dbus",
   "+chromeos/dbus",
   "+components/account_id",
   "+components/policy/core/common/cloud/cloud_policy_constants.h",
diff --git a/ash/components/tpm/install_attributes.cc b/ash/components/tpm/install_attributes.cc
index bf37919a..7ad9996a 100644
--- a/ash/components/tpm/install_attributes.cc
+++ b/ash/components/tpm/install_attributes.cc
@@ -20,11 +20,11 @@
 #include "base/task/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_util.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/install_attributes_util.h"
 #include "components/policy/proto/install_attributes.pb.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/ash/components/tpm/install_attributes.h b/ash/components/tpm/install_attributes.h
index 4a2eff67..5390c675 100644
--- a/ash/components/tpm/install_attributes.h
+++ b/ash/components/tpm/install_attributes.h
@@ -14,8 +14,8 @@
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_client.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
-#include "chromeos/dbus/userdataauth/install_attributes_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/ash/components/tpm/install_attributes_unittest.cc b/ash/components/tpm/install_attributes_unittest.cc
index c5456e5..1fa5a1e 100644
--- a/ash/components/tpm/install_attributes_unittest.cc
+++ b/ash/components/tpm/install_attributes_unittest.cc
@@ -14,10 +14,10 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_util.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/install_attributes_util.h"
 #include "components/policy/proto/install_attributes.pb.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/components/tpm/tpm_token_info_getter.cc b/ash/components/tpm/tpm_token_info_getter.cc
index ee932efd..5e24780 100644
--- a/ash/components/tpm/tpm_token_info_getter.cc
+++ b/ash/components/tpm/tpm_token_info_getter.cc
@@ -15,9 +15,9 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/task/task_runner.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 
 namespace ash {
 
diff --git a/ash/components/tpm/tpm_token_info_getter.h b/ash/components/tpm/tpm_token_info_getter.h
index 16b5e5b..62a6364 100644
--- a/ash/components/tpm/tpm_token_info_getter.h
+++ b/ash/components/tpm/tpm_token_info_getter.h
@@ -13,9 +13,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
-#include "chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h"
 #include "components/account_id/account_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/ash/components/tpm/tpm_token_info_getter_unittest.cc b/ash/components/tpm/tpm_token_info_getter_unittest.cc
index 7834eda..41cee555 100644
--- a/ash/components/tpm/tpm_token_info_getter_unittest.cc
+++ b/ash/components/tpm/tpm_token_info_getter_unittest.cc
@@ -19,9 +19,9 @@
 #include "base/task/task_runner.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_pkcs11_client.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_pkcs11_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/ash/components/tpm/tpm_token_loader.h b/ash/components/tpm/tpm_token_loader.h
index 9ac8a06d..06af3d2 100644
--- a/ash/components/tpm/tpm_token_loader.h
+++ b/ash/components/tpm/tpm_token_loader.h
@@ -15,7 +15,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 415389b..df209658 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -204,6 +204,10 @@
 const base::Feature kAutoScreenBrightness{"AutoScreenBrightness",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables or disables extended autocomplete results.
+const base::Feature kAutocompleteExtendedSuggestions{
+    "AutocompleteExtendedSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
+
 // Enables params tuning experiment for autocorrect on ChromeOS.
 const base::Feature kAutocorrectParamsTuning{"AutocorrectParamsTuning",
                                              base::FEATURE_DISABLED_BY_DEFAULT};
@@ -940,10 +944,6 @@
 const base::Feature kLacrosMoveProfileMigration{
     "LacrosMoveProfileMigration", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Enables or disables the second language settings update.
-const base::Feature kLanguageSettingsUpdate2{"LanguageSettingsUpdate2",
-                                             base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Enables or disables sorting app icons shown on the launcher.
 const base::Feature kLauncherAppSort{"LauncherAppSort",
                                      base::FEATURE_ENABLED_BY_DEFAULT};
@@ -1123,8 +1123,8 @@
 
 // Removes "Shut down" button from OOBE, except first login screen and
 // successful enrollment step.
-const base::Feature kOobeRemoveShutdownButton{
-    "OobeRemoveShutdownButton", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kOobeRemoveShutdownButton{"OobeRemoveShutdownButton",
+                                              base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables StartDemoModeSetupForTesting call.
 const base::Feature kOobeStartDemoModeForTesting{
@@ -1356,15 +1356,10 @@
                                 base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enables Shelf Palm Rejection in tablet mode by defining a pixel offset for
-// the swipe gesture to show the extended hotseat.
+// the swipe gesture to show the extended hotseat. Limited to certain apps.
 const base::Feature kShelfPalmRejectionSwipeOffset{
     "ShelfPalmRejectionSwipeOffset", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Enables Shelf Palm Rejection in tablet mode by defining a touch area for the
-// swipe gesture to show the extended hotseat.
-const base::Feature kShelfPalmRejectionTouchArea{
-    "ShelfPalmRejectionTouchArea", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Enables or disables the new shimless rma flow.
 const base::Feature kShimlessRMAFlow{"ShimlessRMAFlow",
                                      base::FEATURE_ENABLED_BY_DEFAULT};
@@ -1653,6 +1648,10 @@
   return base::FeatureList::IsEnabled(kEnableDesksTrackpadSwipeImprovements);
 }
 
+bool IsAutocompleteExtendedSuggestionsEnabled() {
+  return base::FeatureList::IsEnabled(kAutocompleteExtendedSuggestions);
+}
+
 bool DoWindowsFollowCursor() {
   return base::FeatureList::IsEnabled(kWindowsFollowCursor);
 }
@@ -2291,10 +2290,6 @@
   return base::FeatureList::IsEnabled(kShelfPalmRejectionSwipeOffset);
 }
 
-bool IsShelfPalmRejectionTouchAreaEnabled() {
-  return base::FeatureList::IsEnabled(kShelfPalmRejectionTouchArea);
-}
-
 bool IsShimlessRMAFlowEnabled() {
   return base::FeatureList::IsEnabled(kShimlessRMAFlow);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 685ba00..c6ea13f45 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -93,6 +93,8 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kAutoScreenBrightness;
 COMPONENT_EXPORT(ASH_CONSTANTS)
+extern const base::Feature kAutocompleteExtendedSuggestions;
+COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kAutocorrectParamsTuning;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kAzureADIntegration;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kBentoBar;
@@ -374,8 +376,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kLacrosMoveProfileMigration;
 COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const base::Feature kLanguageSettingsUpdate2;
-COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kLauncherAppSort;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kLauncherFolderRenameKeepsSortOrder;
@@ -539,8 +539,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kShelfParty;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kShelfPalmRejectionSwipeOffset;
-COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const base::Feature kShelfPalmRejectionTouchArea;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kShimlessRMAFlow;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kShimlessRMAEnableStandalone;
@@ -640,6 +638,7 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) bool AreContextualNudgesEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool AreDesksTemplatesEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool AreDesksTrackpadSwipeImprovementsEnabled();
+COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAutocompleteExtendedSuggestionsEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool AreImprovedScreenCaptureSettingsEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool DoWindowsFollowCursor();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAdaptiveChargingEnabled();
@@ -814,7 +813,6 @@
 bool IsSettingsAppThemeChangeAnimationEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShelfLauncherNudgeEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShelfPalmRejectionSwipeOffsetEnabled();
-COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShelfPalmRejectionTouchAreaEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsSimLockPolicyEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShimlessRMAFlowEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShimlessRMAStandaloneAppEnabled();
diff --git a/ash/constants/notifier_catalogs.h b/ash/constants/notifier_catalogs.h
index a7d4aaf0..d4b81167 100644
--- a/ash/constants/notifier_catalogs.h
+++ b/ash/constants/notifier_catalogs.h
@@ -197,7 +197,9 @@
   kUndoCloseAll = 34,
   kEcheAppToast = 35,
   kDeprecateAssistantStylus = 36,
-  kMaxValue = kDeprecateAssistantStylus,
+  kEcheTrayCopyPasteNotImplemented = 37,
+  kEcheTrayTabletModeNotSupported = 38,
+  kMaxValue = kEcheTrayTabletModeNotSupported,
 };
 
 }  // namespace ash
diff --git a/ash/in_session_auth/BUILD.gn b/ash/in_session_auth/BUILD.gn
index 47532d6..11ec877 100644
--- a/ash/in_session_auth/BUILD.gn
+++ b/ash/in_session_auth/BUILD.gn
@@ -29,8 +29,8 @@
     "//ash/resources/vector_icons",
     "//ash/strings",
     "//base",
+    "//chromeos/ash/components/dbus/userdataauth",
     "//chromeos/components/webauthn",
-    "//chromeos/dbus/userdataauth",
     "//ui/views",
   ]
 }
diff --git a/ash/in_session_auth/authentication_dialog_unittest.cc b/ash/in_session_auth/authentication_dialog_unittest.cc
index 2ca5d250..2a7b04f 100644
--- a/ash/in_session_auth/authentication_dialog_unittest.cc
+++ b/ash/in_session_auth/authentication_dialog_unittest.cc
@@ -17,7 +17,7 @@
 #include "base/logging.h"
 #include "base/test/bind.h"
 #include "base/unguessable_token.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/keycodes/keyboard_codes_posix.h"
diff --git a/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc b/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc
index 1f6c496..a34b75b99 100644
--- a/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc
+++ b/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc
@@ -8,7 +8,7 @@
 #include "ash/in_session_auth/authentication_dialog.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 
 namespace ash {
 
diff --git a/ash/quick_pair/scanning/BUILD.gn b/ash/quick_pair/scanning/BUILD.gn
index e105295..758c12b 100644
--- a/ash/quick_pair/scanning/BUILD.gn
+++ b/ash/quick_pair/scanning/BUILD.gn
@@ -82,7 +82,7 @@
     "//ash/services/quick_pair",
     "//ash/services/quick_pair:test_support",
     "//base/test:test_support",
-    "//chromeos/network:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//dbus:test_support",
     "//device/bluetooth",
     "//device/bluetooth:mocks",
diff --git a/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl_unittest.cc b/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl_unittest.cc
index 0f1cb22..ef62f6d 100644
--- a/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl_unittest.cc
+++ b/ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl_unittest.cc
@@ -30,9 +30,9 @@
 #include "base/test/bind.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_device.h"
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
diff --git a/ash/quick_pair/scanning/scanner_broker_impl_unittest.cc b/ash/quick_pair/scanning/scanner_broker_impl_unittest.cc
index 3d1a830..d7362a5 100644
--- a/ash/quick_pair/scanning/scanner_broker_impl_unittest.cc
+++ b/ash/quick_pair/scanning/scanner_broker_impl_unittest.cc
@@ -21,7 +21,7 @@
 #include "ash/services/quick_pair/quick_pair_process_manager.h"
 #include "ash/services/quick_pair/quick_pair_process_manager_impl.h"
 #include "ash/test/ash_test_base.h"
-#include "chromeos/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_device.h"
diff --git a/ash/rgb_keyboard/rgb_keyboard_manager.cc b/ash/rgb_keyboard/rgb_keyboard_manager.cc
index a51076f..d34a7db1 100644
--- a/ash/rgb_keyboard/rgb_keyboard_manager.cc
+++ b/ash/rgb_keyboard/rgb_keyboard_manager.cc
@@ -29,6 +29,7 @@
   g_instance = this;
 
   ime_controller_ptr_->AddObserver(this);
+  RgbkbdClient::Get()->AddObserver(this);
 
   VLOG(1) << "Initializing RGB Keyboard support";
   FetchRgbKeyboardSupport();
@@ -102,6 +103,15 @@
   return g_instance;
 }
 
+void RgbKeyboardManager::OnCapabilityUpdatedForTesting(
+    rgbkbd::RgbKeyboardCapabilities capability) {
+  capabilities_ = capability;
+}
+
+void RgbKeyboardManager::OnShutdown() {
+  RgbkbdClient::Get()->RemoveObserver(this);
+}
+
 void RgbKeyboardManager::OnGetRgbKeyboardCapabilities(
     absl::optional<rgbkbd::RgbKeyboardCapabilities> reply) {
   if (!reply.has_value()) {
diff --git a/ash/rgb_keyboard/rgb_keyboard_manager.h b/ash/rgb_keyboard/rgb_keyboard_manager.h
index c833f54..b26f7f48 100644
--- a/ash/rgb_keyboard/rgb_keyboard_manager.h
+++ b/ash/rgb_keyboard/rgb_keyboard_manager.h
@@ -20,12 +20,13 @@
 // of the rgbkbd DBus client.
 // This class is owned by ash/shell and should NOT be created by any other
 // means.
-class ASH_EXPORT RgbKeyboardManager : public ImeControllerImpl::Observer {
+class ASH_EXPORT RgbKeyboardManager : public ImeControllerImpl::Observer,
+                                      public RgbkbdClient::Observer {
  public:
   explicit RgbKeyboardManager(ImeControllerImpl* ime_controller);
   RgbKeyboardManager(const RgbKeyboardManager&) = delete;
   RgbKeyboardManager& operator=(const RgbKeyboardManager&) = delete;
-  virtual ~RgbKeyboardManager();
+  ~RgbKeyboardManager() override;
 
   rgbkbd::RgbKeyboardCapabilities GetRgbKeyboardCapabilities() const;
   void SetStaticBackgroundColor(uint8_t r, uint8_t g, uint8_t b);
@@ -44,6 +45,11 @@
   void OnCapsLockChanged(bool enabled) override;
   void OnKeyboardLayoutNameChanged(const std::string&) override {}
 
+  // RgbkbdClient::Observer:
+  void OnCapabilityUpdatedForTesting(
+      rgbkbd::RgbKeyboardCapabilities capability) override;
+  void OnShutdown() override;
+
   void FetchRgbKeyboardSupport();
 
   void OnGetRgbKeyboardCapabilities(
diff --git a/ash/rgb_keyboard/rgb_keyboard_util.cc b/ash/rgb_keyboard/rgb_keyboard_util.cc
index b5280e8..4ef06ff 100644
--- a/ash/rgb_keyboard/rgb_keyboard_util.cc
+++ b/ash/rgb_keyboard/rgb_keyboard_util.cc
@@ -51,7 +51,7 @@
     case personalization_app::mojom::BacklightColor::kPurple:
       return SkColorSetRGB(/*r=*/132, /*g=*/32, /*b=*/180);
     default:
-      return kInvalidColor;
+      return kDefaultColor;
   }
 }
 
@@ -83,7 +83,7 @@
       return ConvertBacklightColorToSkColor(
           personalization_app::mojom::BacklightColor::kWallpaper);
     default:
-      return kInvalidColor;
+      return kDefaultColor;
   }
 }
 
diff --git a/ash/rgb_keyboard/rgb_keyboard_util.h b/ash/rgb_keyboard/rgb_keyboard_util.h
index 14d04c2e..3e0561d 100644
--- a/ash/rgb_keyboard/rgb_keyboard_util.h
+++ b/ash/rgb_keyboard/rgb_keyboard_util.h
@@ -10,7 +10,7 @@
 
 namespace ash {
 
-inline constexpr SkColor kInvalidColor = SK_ColorWHITE;
+inline constexpr SkColor kDefaultColor = SK_ColorWHITE;
 
 // Util method to convert the |BacklightColor| enum to a predefined SkColor
 // which will be set by rgb keyboard manager to change the color of the keyboard
diff --git a/ash/services/cellular_setup/BUILD.gn b/ash/services/cellular_setup/BUILD.gn
index e20201f..c8162c4 100644
--- a/ash/services/cellular_setup/BUILD.gn
+++ b/ash/services/cellular_setup/BUILD.gn
@@ -115,9 +115,9 @@
     "//ash/services/cellular_setup/public/cpp:test_support",
     "//base",
     "//base/test:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus/hermes",
     "//chromeos/dbus/shill",
-    "//chromeos/network:test_support",
     "//components/user_manager:test_support",
     "//dbus",
     "//testing/gmock",
diff --git a/ash/services/cellular_setup/cellular_setup_impl_unittest.cc b/ash/services/cellular_setup/cellular_setup_impl_unittest.cc
index 9f486b7..429234a 100644
--- a/ash/services/cellular_setup/cellular_setup_impl_unittest.cc
+++ b/ash/services/cellular_setup/cellular_setup_impl_unittest.cc
@@ -15,7 +15,7 @@
 #include "ash/services/cellular_setup/public/cpp/fake_activation_delegate.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "chromeos/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/services/cellular_setup/esim_profile_unittest.cc b/ash/services/cellular_setup/esim_profile_unittest.cc
index 1617564..865e5ce 100644
--- a/ash/services/cellular_setup/esim_profile_unittest.cc
+++ b/ash/services/cellular_setup/esim_profile_unittest.cc
@@ -10,9 +10,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
 #include "chromeos/dbus/hermes/hermes_euicc_client.h"
 #include "chromeos/dbus/hermes/hermes_profile_client.h"
-#include "chromeos/network/fake_network_connection_handler.h"
 #include "components/user_manager/fake_user_manager.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
diff --git a/ash/services/cellular_setup/esim_test_base.cc b/ash/services/cellular_setup/esim_test_base.cc
index c57348a..25c1f61 100644
--- a/ash/services/cellular_setup/esim_test_base.cc
+++ b/ash/services/cellular_setup/esim_test_base.cc
@@ -13,17 +13,17 @@
 #include "chromeos/ash/components/network/cellular_esim_installer.h"
 #include "chromeos/ash/components/network/cellular_esim_uninstall_handler.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/dbus/hermes/hermes_clients.h"
 #include "chromeos/dbus/hermes/hermes_euicc_client.h"
 #include "chromeos/dbus/hermes/hermes_manager_client.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
-#include "chromeos/network/fake_network_connection_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_device_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 
 namespace ash::cellular_setup {
 
diff --git a/ash/services/cellular_setup/esim_test_base.h b/ash/services/cellular_setup/esim_test_base.h
index c78ed346..9a11dcf 100644
--- a/ash/services/cellular_setup/esim_test_base.h
+++ b/ash/services/cellular_setup/esim_test_base.h
@@ -17,9 +17,9 @@
 // TODO(https://crbug.com/1164001): move to forward declaration.
 #include "chromeos/ash/components/network/cellular_esim_uninstall_handler.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
-#include "chromeos/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
 #include "chromeos/network/network_configuration_handler.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
diff --git a/ash/services/cellular_setup/euicc_unittest.cc b/ash/services/cellular_setup/euicc_unittest.cc
index 50d61405..82ce99b 100644
--- a/ash/services/cellular_setup/euicc_unittest.cc
+++ b/ash/services/cellular_setup/euicc_unittest.cc
@@ -11,11 +11,11 @@
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/dbus/hermes/hermes_euicc_client.h"
 #include "chromeos/dbus/hermes/hermes_profile_client.h"
-#include "chromeos/network/fake_network_connection_handler.h"
 #include "chromeos/network/network_type_pattern.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
 
diff --git a/ash/services/cellular_setup/ota_activator_impl_unittest.cc b/ash/services/cellular_setup/ota_activator_impl_unittest.cc
index 9aee5505..2de61528 100644
--- a/ash/services/cellular_setup/ota_activator_impl_unittest.cc
+++ b/ash/services/cellular_setup/ota_activator_impl_unittest.cc
@@ -12,11 +12,11 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_simple_task_runner.h"
-#include "chromeos/network/fake_network_activation_handler.h"
-#include "chromeos/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/fake_network_activation_handler.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/ash/services/chromebox_for_meetings/DEPS b/ash/services/chromebox_for_meetings/DEPS
index b847090..2e2e8d99 100644
--- a/ash/services/chromebox_for_meetings/DEPS
+++ b/ash/services/chromebox_for_meetings/DEPS
@@ -1,6 +1,5 @@
 include_rules = [
   "+chromeos/dbus",
-  "+chromeos/services/cros_healthd/public/mojom",
   "+mojo/core/embedder",
   "+mojo/public",
 ]
diff --git a/ash/services/chromebox_for_meetings/public/mojom/BUILD.gn b/ash/services/chromebox_for_meetings/public/mojom/BUILD.gn
index 72d99565..46bb89b 100644
--- a/ash/services/chromebox_for_meetings/public/mojom/BUILD.gn
+++ b/ash/services/chromebox_for_meetings/public/mojom/BUILD.gn
@@ -22,6 +22,6 @@
       "meet_devices_info.mojom",
       "meet_devices_logger.mojom",
     ]
-    public_deps += [ "//chromeos/services/cros_healthd/public/mojom" ]
+    public_deps += [ "//chromeos/ash/services/cros_healthd/public/mojom" ]
   }
 }
diff --git a/ash/services/chromebox_for_meetings/public/mojom/meet_devices_diagnostics.mojom b/ash/services/chromebox_for_meetings/public/mojom/meet_devices_diagnostics.mojom
index 93cd797..9996f70 100644
--- a/ash/services/chromebox_for_meetings/public/mojom/meet_devices_diagnostics.mojom
+++ b/ash/services/chromebox_for_meetings/public/mojom/meet_devices_diagnostics.mojom
@@ -4,7 +4,7 @@
 
 module chromeos.cfm.mojom;
 
-import "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom";
+import "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom";
 
 // Interface defined by chromium specifically for the ChromeboxForMeetings
 // platform to query system diagnostics of devices in the fleet.
diff --git a/ash/services/device_sync/BUILD.gn b/ash/services/device_sync/BUILD.gn
index 59f5c82..53895a3 100644
--- a/ash/services/device_sync/BUILD.gn
+++ b/ash/services/device_sync/BUILD.gn
@@ -324,9 +324,9 @@
     "//ash/services/device_sync/public/mojom:unit_tests",
     "//base",
     "//base/test:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus:test_support",
     "//chromeos/network",
-    "//chromeos/network:test_support",
     "//components/gcm_driver:test_support",
     "//components/prefs:test_support",
     "//components/signin/public/identity_manager:test_support",
diff --git a/ash/services/device_sync/cryptauth_scheduler_impl_unittest.cc b/ash/services/device_sync/cryptauth_scheduler_impl_unittest.cc
index db926e41..63d9f47 100644
--- a/ash/services/device_sync/cryptauth_scheduler_impl_unittest.cc
+++ b/ash/services/device_sync/cryptauth_scheduler_impl_unittest.cc
@@ -18,7 +18,7 @@
 #include "base/test/simple_test_clock.h"
 #include "base/test/task_environment.h"
 #include "base/timer/mock_timer.h"
-#include "chromeos/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/ash/services/device_sync/device_sync_service_unittest.cc b/ash/services/device_sync/device_sync_service_unittest.cc
index 37a9e42d..e1d9009 100644
--- a/ash/services/device_sync/device_sync_service_unittest.cc
+++ b/ash/services/device_sync/device_sync_service_unittest.cc
@@ -54,8 +54,8 @@
 #include "base/test/simple_test_clock.h"
 #include "base/test/task_environment.h"
 #include "base/timer/mock_timer.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/gcm_driver/fake_gcm_driver.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/ash/services/recording/recording_service.cc b/ash/services/recording/recording_service.cc
index 5785141e..1eb8ca58 100644
--- a/ash/services/recording/recording_service.cc
+++ b/ash/services/recording/recording_service.cc
@@ -366,6 +366,8 @@
   encoder_muxer_.AsyncCall(&RecordingEncoderMuxer::EncodeVideo).WithArgs(frame);
 }
 
+void RecordingService::OnNewCropVersion(uint32_t crop_version) {}
+
 void RecordingService::OnFrameWithEmptyRegionCapture() {}
 
 void RecordingService::OnStopped() {
diff --git a/ash/services/recording/recording_service.h b/ash/services/recording/recording_service.h
index be1325b..36bba76 100644
--- a/ash/services/recording/recording_service.h
+++ b/ash/services/recording/recording_service.h
@@ -99,6 +99,7 @@
       const gfx::Rect& content_rect,
       mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
           callbacks) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnStopped() override;
   void OnLog(const std::string& message) override;
diff --git a/ash/shelf/hotseat_widget.cc b/ash/shelf/hotseat_widget.cc
index 3b77350..a26e259 100644
--- a/ash/shelf/hotseat_widget.cc
+++ b/ash/shelf/hotseat_widget.cc
@@ -1268,26 +1268,4 @@
   SetBounds(target_bounds);
 }
 
-bool HotseatWidget::IsPointWithinGestureTouchArea(
-    const gfx::Point& screen_location) {
-  if (!features::IsShelfPalmRejectionTouchAreaEnabled())
-    return true;
-
-  const int touch_area_width = base::GetFieldTrialParamByFeatureAsInt(
-      features::kShelfPalmRejectionTouchArea, "shelf_touch_area", 100);
-
-  gfx::Rect hotseat_bounds = GetWindowBoundsInScreen();
-
-  if (hotseat_bounds.width() < touch_area_width)
-    return true;
-
-  hotseat_bounds.ClampToCenteredSize(
-      gfx::Size(touch_area_width, hotseat_bounds.height()));
-
-  const int min_x =
-      (hotseat_bounds.width() - touch_area_width) / 2 + hotseat_bounds.x();
-  const int max_x = min_x + touch_area_width;
-  return screen_location.x() >= min_x && screen_location.x() <= max_x;
-}
-
 }  // namespace ash
diff --git a/ash/shelf/hotseat_widget.h b/ash/shelf/hotseat_widget.h
index 72039ac..121b158 100644
--- a/ash/shelf/hotseat_widget.h
+++ b/ash/shelf/hotseat_widget.h
@@ -158,11 +158,6 @@
 
   metrics_util::ReportCallback GetTranslucentBackgroundReportCallback();
 
-  // Verifies if `screen_location` falls within the hotseat widget bounds' touch
-  // area. `screen_location` is expected to be in screen bounds. The hotseat
-  // touch area is the area of the widget that allows to trigger gesture events.
-  bool IsPointWithinGestureTouchArea(const gfx::Point& screen_location);
-
   void SetState(HotseatState state);
   HotseatState state() const { return state_; }
 
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index d43f2d7..7f00bd2 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -112,6 +112,9 @@
 // the auto-hidden shelf when the shelf is on the boundary between displays.
 constexpr int kMaxAutoHideShowShelfRegionSize = 10;
 
+// Delay before showing the shelf. This is after the mouse stops moving.
+constexpr int kShelfPalmRejectionSwipeOffset = 80;
+
 // Returns the `aura::client::DragDropClient` for the given `shelf_widget`. Note
 // that this may return `nullptr` if the browser is performing its shutdown
 // sequence.
@@ -291,11 +294,9 @@
 }
 
 int GetShelfSwipeOffset() {
-  if (!features::IsShelfPalmRejectionSwipeOffsetEnabled())
-    return 0;
-
-  return base::GetFieldTrialParamByFeatureAsInt(
-      ash::features::kShelfPalmRejectionSwipeOffset, "shelf_swipe_offset", 0);
+  return features::IsShelfPalmRejectionSwipeOffsetEnabled()
+             ? kShelfPalmRejectionSwipeOffset
+             : 0;
 }
 
 // Forwards gesture events to ShelfLayoutManager to hide the hotseat
@@ -2481,12 +2482,6 @@
     return false;
   }
 
-  if (is_tablet_mode &&
-      !shelf_->hotseat_widget()->IsPointWithinGestureTouchArea(
-          event_in_screen.location())) {
-    return false;
-  }
-
   drag_status_ = kDragInProgress;
   drag_auto_hide_state_ =
       (!Shell::Get()->overview_controller()->InOverviewSession() &&
diff --git a/ash/shell.cc b/ash/shell.cc
index 733f067c..22be1719 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -1107,7 +1107,8 @@
     env->set_context_factory(context_factory);
 
   ash_color_provider_ = std::make_unique<AshColorProvider>();
-
+  ui::ColorProviderManager::Get().AppendColorProviderInitializer(
+      base::BindRepeating(AddCrosStylesColorMixer));
   ui::ColorProviderManager::Get().AppendColorProviderInitializer(
       base::BindRepeating(AddAshColorMixer));
 
diff --git a/ash/strings/ash_strings_fa.xtb b/ash/strings/ash_strings_fa.xtb
index e1f117d8..6428c67 100644
--- a/ash/strings/ash_strings_fa.xtb
+++ b/ash/strings/ash_strings_fa.xtb
@@ -376,7 +376,7 @@
 <translation id="3217205077783620295">دکمه میزان صدا فعال است، با تغییر وضعیت صامت می‌شود.</translation>
 <translation id="3226991577105957773">+<ph name="COUNT" /> مورد دیگر</translation>
 <translation id="3227137524299004712">میکروفن</translation>
-<translation id="324366796737464147">کاهش صدای محیط</translation>
+<translation id="324366796737464147">حذف نوفه زمینه</translation>
 <translation id="3249513730522716925">پنجره <ph name="WINDOW_TITLE" /> از میز <ph name="ACTIVE_DESK" /> به میز <ph name="TARGET_DESK" /> منتقل شد</translation>
 <translation id="3252573918265662711">راه‌اندازی</translation>
 <translation id="3255483164551725916">‏What can you do?‎ (چه کاری می‌توانی انجام دهی؟)</translation>
diff --git a/ash/strings/ash_strings_uk.xtb b/ash/strings/ash_strings_uk.xtb
index f66ca63..593cae4f 100644
--- a/ash/strings/ash_strings_uk.xtb
+++ b/ash/strings/ash_strings_uk.xtb
@@ -181,7 +181,7 @@
 <translation id="1982717156487272186">Показати попередній тиждень</translation>
 <translation id="1989113344093894667">Не вдається записати контент</translation>
 <translation id="1990046457226896323">Файли живих субтитрів завантажено</translation>
-<translation id="1993072747612765854">Докладніше про останнє оновлення додатка <ph name="SYSTEM_APP_NAME" /></translation>
+<translation id="1993072747612765854">Докладніше про останнє оновлення <ph name="SYSTEM_APP_NAME" /></translation>
 <translation id="1998100899771863792">Поточний робочий стіл</translation>
 <translation id="2001444736072756133">Шукайте <ph name="CATEGORY" />, файли, додатки тощо.</translation>
 <translation id="2016340657076538683">Введіть повідомлення</translation>
diff --git a/ash/style/ash_color_mixer.cc b/ash/style/ash_color_mixer.cc
index e9531e9..1b751bf 100644
--- a/ash/style/ash_color_mixer.cc
+++ b/ash/style/ash_color_mixer.cc
@@ -10,6 +10,7 @@
 #include "ash/style/ash_color_provider.h"
 #include "ash/system/tray/tray_constants.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_mixer.h"
 #include "ui/color/color_provider.h"
@@ -17,6 +18,17 @@
 
 namespace ash {
 
+void AddCrosStylesColorMixer(ui::ColorProvider* provider,
+                             const ui::ColorProviderManager::Key& key) {
+  ui::ColorMixer& mixer = provider->AddMixer();
+  bool dark_mode = key.color_mode == ui::ColorProviderManager::ColorMode::kDark;
+  cros_tokens::AddCrosRefColorsToMixer(mixer, dark_mode);
+  cros_tokens::AddCrosSysColorsToMixer(mixer, dark_mode);
+  cros_tokens::AddLegacySemanticColorsToMixer(mixer, dark_mode);
+
+  // TODO(b/235913438): Remap legacy colors to tokens here.
+}
+
 void AddAshColorMixer(ui::ColorProvider* provider,
                       const ui::ColorProviderManager::Key& key) {
   auto* ash_color_provider = AshColorProvider::Get();
diff --git a/ash/style/ash_color_mixer.h b/ash/style/ash_color_mixer.h
index e028c00d..6566acec 100644
--- a/ash/style/ash_color_mixer.h
+++ b/ash/style/ash_color_mixer.h
@@ -13,6 +13,10 @@
 
 namespace ash {
 
+// Adds a color mixer with colors generated from ui/chromeos/styles/*.json5.
+void AddCrosStylesColorMixer(ui::ColorProvider* provider,
+                             const ui::ColorProviderManager::Key& key);
+
 // Adds a color mixer to `provider` that supplies default values for various
 // ash/ colors before taking into account any custom themes.
 void AddAshColorMixer(ui::ColorProvider* provider,
diff --git a/ash/system/eche/eche_tray.cc b/ash/system/eche/eche_tray.cc
index 718a7325..de4c292 100644
--- a/ash/system/eche/eche_tray.cc
+++ b/ash/system/eche/eche_tray.cc
@@ -8,12 +8,16 @@
 
 #include "ash/accessibility/accessibility_controller_impl.h"
 #include "ash/components/multidevice/logging/logging.h"
+#include "ash/constants/notifier_catalogs.h"
 #include "ash/keyboard/ui/keyboard_ui_controller.h"
 #include "ash/public/cpp/accelerators.h"
 #include "ash/public/cpp/ash_web_view.h"
 #include "ash/public/cpp/ash_web_view_factory.h"
 #include "ash/public/cpp/keyboard/keyboard_controller.h"
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/public/cpp/system/toast_data.h"
+#include "ash/public/cpp/system/toast_manager.h"
+#include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/root_window_controller.h"
 #include "ash/session/session_controller_impl.h"
@@ -39,10 +43,13 @@
 #include "base/time/time.h"
 #include "components/account_id/account_id.h"
 #include "components/vector_icons/vector_icons.h"
+#include "ui/base/accelerators/accelerator.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
 #include "ui/events/event.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/types/event_type.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
@@ -94,6 +101,13 @@
 // Unload timeout to close Eche Bubble in case error from Ech web during closing
 constexpr base::TimeDelta kUnloadTimeoutDuration = base::Milliseconds(500);
 
+// The ID for the "Copy/paste not yet implemented" toast.
+constexpr char kEcheTrayCopyPasteNotImplementedToastId[] =
+    "eche_tray_toast_ids.copy_paste_not_implemented";
+// The ID for the "Tablet mode not supported" toast.
+constexpr char kEcheTrayTabletModeNotSupportedId[] =
+    "eche_tray_toast_ids.tablet_mode_not_supported";
+
 // Creates a button with the given callback, icon, and tooltip text.
 // `message_id` is the resource id of the tooltip text of the icon.
 std::unique_ptr<views::Button> CreateButton(
@@ -121,12 +135,7 @@
 EcheTray::EventInterceptor::~EventInterceptor() = default;
 
 void EcheTray::EventInterceptor::OnKeyEvent(ui::KeyEvent* event) {
-  // To provide consistent behavior with a menu, process accelerator as a menu
-  // is open if the event is not handled by the widget.
-  ui::Accelerator accelerator(*event);
-  if (AcceleratorController::Get()->DoesAcceleratorMatchAction(
-          accelerator, AcceleratorAction::WINDOW_MINIMIZE)) {
-    eche_tray_->CloseBubble();
+  if (eche_tray_->ProcessAcceleratorKeys(event)) {
     event->StopPropagation();
     return;
   }
@@ -146,6 +155,10 @@
   // Note: `ScreenLayoutObserver` starts observing at its constructor.
   observed_session_.Observe(Shell::Get()->session_controller());
   icon_->SetTooltipText(GetAccessibleNameForTray());
+  icon_->SetImage(CreateVectorIcon(
+      kPhoneHubPhoneIcon,
+      AshColorProvider::Get()->GetContentLayerColor(
+          AshColorProvider::ContentLayerType::kIconColorPrimary)));
   shelf_observation_.Observe(shelf);
   tablet_mode_observation_.Observe(Shell::Get()->tablet_mode_controller());
   shell_observer_.Observe(Shell::Get());
@@ -227,7 +240,7 @@
 
 bool EcheTray::PerformAction(const ui::Event& event) {
   // Simply toggle between visible/invisibvle
-  if (bubble_ && bubble_->bubble_view()->GetVisible()) {
+  if (IsBubbleVisible()) {
     HideBubble();
   } else {
 #ifdef FAKE_BUBBLE_FOR_DEBUG
@@ -259,7 +272,7 @@
     return;
 
   // Another bubble has become visible, so minimize this one.
-  if (visible && bubble_->bubble_view()->GetVisible())
+  if (visible && IsBubbleVisible())
     HideBubble();
 }
 
@@ -300,13 +313,13 @@
 }
 
 void EcheTray::OnKeyboardUIDestroyed() {
-  if (!bubble_ || !bubble_->bubble_view()->GetVisible())
+  if (!IsBubbleVisible())
     return;
   UpdateBubbleBounds();
 }
 
 void EcheTray::OnKeyboardVisibilityChanged(bool visible) {
-  if (visible || !bubble_ || !bubble_->bubble_view()->GetVisible())
+  if (visible || !IsBubbleVisible())
     return;
   UpdateBubbleBounds();
 }
@@ -331,16 +344,26 @@
   }
 }
 
-void EcheTray::LoadBubble(const GURL& url,
+bool EcheTray::LoadBubble(const GURL& url,
                           const gfx::Image& icon,
                           const std::u16string& visible_name) {
+  if (Shell::Get()->IsInTabletMode()) {
+    ash::ToastManager::Get()->Show(ash::ToastData(
+        kEcheTrayTabletModeNotSupportedId,
+        ash::ToastCatalogName::kEcheTrayTabletModeNotSupported,
+        l10n_util::GetStringUTF16(IDS_ASH_ECHE_TOAST_TABLET_MODE_NOT_SUPPORTED),
+        ash::ToastData::kDefaultToastDuration,
+        /*visible_on_lock_screen=*/false));
+    PA_LOG(WARNING) << "Eche load failed due to tablet mode.";
+    return false;
+  }
   SetUrl(url);
   SetIcon(icon, /*tooltip_text=*/visible_name);
   // If the bubble is already initialized, setting the icon and url was enough
   // to navigate the bubble to the new address.
   if (IsInitialized()) {
     ShowBubble();
-    return;
+    return true;
   }
   InitBubble();
   StartLoadingAnimation();
@@ -351,6 +374,7 @@
   }
   // Hide bubble first until the streaming is ready.
   HideBubble();
+  return true;
 }
 
 void EcheTray::PurgeAndClose() {
@@ -615,7 +639,7 @@
 }
 
 void EcheTray::UpdateBubbleBounds() {
-  if (!bubble_)
+  if (!bubble_ || !bubble_->GetBubbleView())
     return;
   bubble_->GetBubbleView()->ChangeAnchorRect(GetAnchor());
 }
@@ -633,7 +657,15 @@
 }
 
 void EcheTray::OnTabletModeStarted() {
-  UpdateBubbleBounds();
+  if (!IsBubbleVisible())
+    return;
+  ash::ToastManager::Get()->Show(ash::ToastData(
+      kEcheTrayTabletModeNotSupportedId,
+      ash::ToastCatalogName::kEcheTrayTabletModeNotSupported,
+      l10n_util::GetStringUTF16(IDS_ASH_ECHE_TOAST_TABLET_MODE_NOT_SUPPORTED),
+      ash::ToastData::kDefaultToastDuration,
+      /*visible_on_lock_screen=*/false));
+  PurgeAndClose();
 }
 
 void EcheTray::OnTabletModeEnded() {
@@ -648,6 +680,74 @@
   return shelf()->GetSystemTrayAnchorRect();
 }
 
+// TODO(b/234848974): Try to use View::AddAccelerator for the bubble view
+// and then add the handler in View::AcceleratorPressed.
+bool EcheTray::ProcessAcceleratorKeys(ui::KeyEvent* event) {
+  ui::Accelerator accelerator(*event);
+
+  auto* accelerator_controller = AcceleratorController::Get();
+
+  // Process minimize action
+  // Please note that the bubble is not a normal window and it has a special
+  // minimize behavior that is closer to hide than real minimize.
+  //
+  // TODO(https://crbug/1338650): See if we can just leave this to be handled
+  // upper in the chain and perform the minimize by reacting to
+  // ToggleMinimized().
+  if (accelerator_controller->DoesAcceleratorMatchAction(
+          accelerator, AcceleratorAction::WINDOW_MINIMIZE)) {
+    CloseBubble();
+    return true;
+  }
+
+  if (accelerator_controller->DoesAcceleratorMatchAction(
+          accelerator, AcceleratorAction::OPEN_FEEDBACK_PAGE) ||
+      accelerator_controller->DoesAcceleratorMatchAction(
+          accelerator, AcceleratorAction::EXIT)) {
+    views::ViewsDelegate::GetInstance()->ProcessAcceleratorWhileMenuShowing(
+        accelerator);
+    event->StopPropagation();
+    return true;
+  }
+
+  const ui::KeyboardCode key_code = event->key_code();
+  const bool is_only_control_down = ui::Accelerator::MaskOutKeyEventFlags(
+                                        event->flags()) == ui::EF_CONTROL_DOWN;
+
+  if (event->type() == ui::ET_KEY_PRESSED && is_only_control_down) {
+    switch (key_code) {
+      case ui::VKEY_C:
+      case ui::VKEY_V:
+      case ui::VKEY_X:
+        ash::ToastManager::Get()->Show(ash::ToastData(
+            kEcheTrayCopyPasteNotImplementedToastId,
+            ash::ToastCatalogName::kEcheTrayCopyPasteNotImplemented,
+            l10n_util::GetStringUTF16(
+                IDS_ASH_ECHE_TOAST_COPY_PASTE_NOT_IMPLEMENTED),
+            ash::ToastData::kDefaultToastDuration,
+            /*visible_on_lock_screen=*/false));
+        return true;
+      case ui::VKEY_W:
+        // Please note that ctrl+w does not have a global accelerator action
+        // similar to AcceleratorAction::WINDOW_MINIMIZE that was used above.
+        //
+        // TODO(https://crbug/1338650): See if we can just leave this to be
+        // handled upper in the chain.
+        StartGracefulClose();
+        return true;
+      default:
+        // Do nothing
+        break;
+    }
+  }
+  return false;
+}
+
+bool EcheTray::IsBubbleVisible() {
+  return bubble_ && bubble_->GetBubbleView() &&
+         bubble_->GetBubbleView()->GetVisible();
+}
+
 BEGIN_METADATA(EcheTray, TrayBackgroundView)
 END_METADATA
 
diff --git a/ash/system/eche/eche_tray.h b/ash/system/eche/eche_tray.h
index d3dbf5a..11516e7 100644
--- a/ash/system/eche/eche_tray.h
+++ b/ash/system/eche/eche_tray.h
@@ -146,7 +146,9 @@
   // The `url` parameter is used to load the `WebView` inside the bubble.
   // The `icon` is used to update the tray icon for `EcheTray`.
   // The `visible_name` is shown as a tooltip for the Eche icon.
-  void LoadBubble(const GURL& url,
+  //
+  // Returns true if the bubble is loaded or initialized successfully.
+  bool LoadBubble(const GURL& url,
                   const gfx::Image& icon,
                   const std::u16string& visible_name);
 
@@ -236,6 +238,13 @@
   // returns the position of the anchor that bubble needs to be anchored to.
   gfx::Rect GetAnchor();
 
+  // Processes the accelerator keys and returns true if the accelerator was
+  // processed completely in this method and no further processing is needed.
+  bool ProcessAcceleratorKeys(ui::KeyEvent* event);
+
+  // Returns true only if the bubble is initialized and visible.
+  bool IsBubbleVisible();
+
   // The url that is transferred to the web view.
   // In the current implementation, this is supposed to be
   // Eche window URL. However, the bubble does not interpret,
diff --git a/ash/system/eche/eche_tray_unittest.cc b/ash/system/eche/eche_tray_unittest.cc
index e4517c5..f612cf7 100644
--- a/ash/system/eche/eche_tray_unittest.cc
+++ b/ash/system/eche/eche_tray_unittest.cc
@@ -7,13 +7,17 @@
 #include <memory>
 #include <string>
 
+#include "ash/public/cpp/system/toast_manager.h"
 #include "ash/shell.h"
+#include "ash/strings/grit/ash_strings.h"
 #include "ash/system/phonehub/phone_hub_tray.h"
 #include "ash/system/status_area_widget_test_helper.h"
+#include "ash/system/toast/toast_manager_impl.h"
 #include "ash/system/tray/tray_bubble_wrapper.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/test/test_ash_web_view_factory.h"
 #include "base/test/scoped_feature_list.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/display/test/display_manager_test_api.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/keyboard_codes_posix.h"
@@ -81,6 +85,8 @@
 
     display::test::DisplayManagerTestApi(display_manager())
         .SetFirstDisplayAsInternalDisplay();
+
+    toast_manager_ = Shell::Get()->toast_manager();
   }
 
   // Performs a tap on the eche tray button.
@@ -96,11 +102,13 @@
 
   EcheTray* eche_tray() { return eche_tray_; }
   PhoneHubTray* phone_hub_tray() { return phone_hub_tray_; }
+  ToastManagerImpl* toast_manager() { return toast_manager_; }
 
  private:
   EcheTray* eche_tray_ = nullptr;  // Not owned
   PhoneHubTray* phone_hub_tray_ = nullptr;  // Not owned
   base::test::ScopedFeatureList feature_list_;
+  ToastManagerImpl* toast_manager_ = nullptr;
 
   // Calling the factory constructor is enough to set it up.
   std::unique_ptr<TestAshWebViewFactory> test_web_view_factory_ =
@@ -362,4 +370,75 @@
   EXPECT_FALSE(is_web_content_unloaded_);
 }
 
+TEST_F(EcheTrayTest, AcceleratorKeyHandled_Ctrl_W) {
+  ResetUnloadWebContent();
+  eche_tray()->SetGracefulCloseCallback(base::BindOnce(&UnloadWebContent));
+  eche_tray()->LoadBubble(GURL("http://google.com"), CreateTestImage(),
+                          u"app 1");
+  eche_tray()->ShowBubble();
+
+  EXPECT_TRUE(
+      eche_tray()->get_bubble_wrapper_for_test()->bubble_view()->GetVisible());
+
+  // Now press the ctrl+w that closes the bubble.
+  GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_W, ui::EF_CONTROL_DOWN);
+
+  // Check to see if the bubble is closed and purged.
+  EXPECT_TRUE(is_web_content_unloaded_);
+}
+
+TEST_F(EcheTrayTest, AcceleratorKeyHandled_Ctrl_C) {
+  eche_tray()->LoadBubble(GURL("http://google.com"), CreateTestImage(),
+                          u"app 1");
+  eche_tray()->ShowBubble();
+
+  EXPECT_TRUE(
+      eche_tray()->get_bubble_wrapper_for_test()->bubble_view()->GetVisible());
+  EXPECT_FALSE(toast_manager()->IsRunning(
+      "eche_tray_toast_ids.copy_paste_not_implemented"));
+
+  // Now press the ctrl+w that closes the bubble.
+  GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_C, ui::EF_CONTROL_DOWN);
+
+  // Check to see if a toast is shown
+  EXPECT_TRUE(toast_manager()->IsRunning(
+      "eche_tray_toast_ids.copy_paste_not_implemented"));
+}
+
+TEST_F(EcheTrayTest, AcceleratorKeyHandled_Ctrl_V) {
+  eche_tray()->LoadBubble(GURL("http://google.com"), CreateTestImage(),
+                          u"app 1");
+  eche_tray()->ShowBubble();
+
+  EXPECT_TRUE(
+      eche_tray()->get_bubble_wrapper_for_test()->bubble_view()->GetVisible());
+  EXPECT_FALSE(toast_manager()->IsRunning(
+      "eche_tray_toast_ids.copy_paste_not_implemented"));
+
+  // Now press the ctrl+w that closes the bubble.
+  GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_V, ui::EF_CONTROL_DOWN);
+
+  // Check to see if a toast is shown
+  EXPECT_TRUE(toast_manager()->IsRunning(
+      "eche_tray_toast_ids.copy_paste_not_implemented"));
+}
+
+TEST_F(EcheTrayTest, AcceleratorKeyHandled_Ctrl_X) {
+  eche_tray()->LoadBubble(GURL("http://google.com"), CreateTestImage(),
+                          u"app 1");
+  eche_tray()->ShowBubble();
+
+  EXPECT_TRUE(
+      eche_tray()->get_bubble_wrapper_for_test()->bubble_view()->GetVisible());
+  EXPECT_FALSE(toast_manager()->IsRunning(
+      "eche_tray_toast_ids.copy_paste_not_implemented"));
+
+  // Now press the ctrl+w that closes the bubble.
+  GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_X, ui::EF_CONTROL_DOWN);
+
+  // Check to see if a toast is shown
+  EXPECT_TRUE(toast_manager()->IsRunning(
+      "eche_tray_toast_ids.copy_paste_not_implemented"));
+}
+
 }  // namespace ash
diff --git a/ash/system/holding_space/holding_space_progress_indicator_util.cc b/ash/system/holding_space/holding_space_progress_indicator_util.cc
index ae81054..ffc7eb6 100644
--- a/ash/system/holding_space/holding_space_progress_indicator_util.cc
+++ b/ash/system/holding_space/holding_space_progress_indicator_util.cc
@@ -98,7 +98,7 @@
 
   void OnHoldingSpaceItemUpdated(const HoldingSpaceItem* item,
                                  uint32_t updated_fields) override {
-    if (item->IsInitialized())
+    if (item->IsInitialized() && (updated_fields & UpdatedField::kProgress))
       InvalidateLayer();
   }
 
@@ -148,7 +148,7 @@
   // HoldingSpaceModelObserver:
   void OnHoldingSpaceItemUpdated(const HoldingSpaceItem* item,
                                  uint32_t updated_fields) override {
-    if (item_ == item)
+    if (item_ == item && (updated_fields & UpdatedField::kProgress))
       InvalidateLayer();
   }
 
diff --git a/ash/system/human_presence/human_presence_orientation_controller.cc b/ash/system/human_presence/human_presence_orientation_controller.cc
index ea29a301..b003ca4f 100644
--- a/ash/system/human_presence/human_presence_orientation_controller.cc
+++ b/ash/system/human_presence/human_presence_orientation_controller.cc
@@ -7,7 +7,9 @@
 #include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/shell.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "base/bind.h"
 #include "base/scoped_observation.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/display/display.h"
 #include "ui/display/display_observer.h"
 #include "ui/display/manager/display_manager.h"
@@ -23,6 +25,14 @@
       tablet_mode_controller->is_in_tablet_physical_state();
   tablet_mode_observation_.Observe(tablet_mode_controller);
 
+  chromeos::PowerManagerClient* power_manager_client =
+      chromeos::PowerManagerClient::Get();
+  DCHECK(power_manager_client);
+  power_manager_client_observation_.Observe(power_manager_client);
+  power_manager_client->GetSwitchStates(
+      base::BindOnce(&HumanPresenceOrientationController::OnReceiveSwitchStates,
+                     weak_factory_.GetWeakPtr()));
+
   // Only care about rotation of the actual device.
   if (!display::HasInternalDisplay())
     return;
@@ -46,13 +56,16 @@
 }
 
 bool HumanPresenceOrientationController::IsOrientationSuitable() const {
-  return !physical_tablet_state_ && !display_rotated_;
+  return !physical_tablet_state_ && !display_rotated_ && !lid_closed_;
 }
 
 void HumanPresenceOrientationController::OnTabletPhysicalStateChanged() {
+  TabletModeController* tablet_mode_controller =
+      Shell::Get()->tablet_mode_controller();
+  DCHECK(tablet_mode_controller);
   const bool physical_tablet_state =
-      Shell::Get()->tablet_mode_controller()->is_in_tablet_physical_state();
-  UpdateOrientation(physical_tablet_state, display_rotated_);
+      tablet_mode_controller->is_in_tablet_physical_state();
+  UpdateOrientation(physical_tablet_state, display_rotated_, lid_closed_);
 }
 
 void HumanPresenceOrientationController::OnDisplayMetricsChanged(
@@ -65,16 +78,34 @@
   }
 
   const bool display_rotated = display.rotation() != display::Display::ROTATE_0;
-  UpdateOrientation(physical_tablet_state_, display_rotated);
+  UpdateOrientation(physical_tablet_state_, display_rotated, lid_closed_);
+}
+
+void HumanPresenceOrientationController::LidEventReceived(
+    chromeos::PowerManagerClient::LidState state,
+    base::TimeTicks /* timestamp */) {
+  const bool lid_closed = state != chromeos::PowerManagerClient::LidState::OPEN;
+  UpdateOrientation(physical_tablet_state_, display_rotated_, lid_closed);
+}
+
+void HumanPresenceOrientationController::OnReceiveSwitchStates(
+    absl::optional<chromeos::PowerManagerClient::SwitchStates> switch_states) {
+  if (switch_states.has_value()) {
+    const bool lid_closed = switch_states->lid_state !=
+                            chromeos::PowerManagerClient::LidState::OPEN;
+    UpdateOrientation(physical_tablet_state_, display_rotated_, lid_closed);
+  }
 }
 
 void HumanPresenceOrientationController::UpdateOrientation(
     bool physical_tablet_state,
-    bool display_rotated) {
+    bool display_rotated,
+    bool lid_closed) {
   const bool was_suitable = IsOrientationSuitable();
 
   physical_tablet_state_ = physical_tablet_state;
   display_rotated_ = display_rotated;
+  lid_closed_ = lid_closed;
 
   const bool is_suitable = IsOrientationSuitable();
 
diff --git a/ash/system/human_presence/human_presence_orientation_controller.h b/ash/system/human_presence/human_presence_orientation_controller.h
index 0f64369..c1658f61 100644
--- a/ash/system/human_presence/human_presence_orientation_controller.h
+++ b/ash/system/human_presence/human_presence_orientation_controller.h
@@ -8,7 +8,9 @@
 #include "ash/ash_export.h"
 #include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
+#include "chromeos/dbus/power/power_manager_client.h"
 #include "ui/display/display.h"
 #include "ui/display/display_observer.h"
 
@@ -21,7 +23,8 @@
 // when it enters or leaves non-standard orientations.
 class ASH_EXPORT HumanPresenceOrientationController
     : public TabletModeObserver,
-      public display::DisplayObserver {
+      public display::DisplayObserver,
+      public PowerManagerClient::Observer {
  public:
   class Observer : public base::CheckedObserver {
    public:
@@ -54,9 +57,17 @@
   void OnDisplayMetricsChanged(const display::Display& display,
                                uint32_t changed_metrics) override;
 
-  // Updates the internal state of the controller, and notifies observers if the
-  // state has changed.
-  void UpdateOrientation(bool physical_tablet_state, bool display_rotated);
+  // chromeos::PowerManagerClient::Observer:
+  void LidEventReceived(chromeos::PowerManagerClient::LidState state,
+                        base::TimeTicks timestamp) override;
+  void OnReceiveSwitchStates(
+      absl::optional<chromeos::PowerManagerClient::SwitchStates> switch_states);
+
+  // Updates the internal state of the controller, and notifies observers if
+  // the state has changed.
+  void UpdateOrientation(bool physical_tablet_state,
+                         bool display_rotated,
+                         bool lid_closed);
 
   // If the device is physically configured like a tablet, we will sense frames
   // from atypical angles. Note this is different from tablet mode in general,
@@ -70,12 +81,20 @@
   // frames.
   bool display_rotated_ = false;
 
+  // Device with close lid captures unusable frames.
+  bool lid_closed_ = false;
+
   // Clients listening for orientation status changes.
   base::ObserverList<Observer> observers_;
 
   base::ScopedObservation<TabletModeController, TabletModeObserver>
       tablet_mode_observation_{this};
   display::ScopedDisplayObserver display_observation_{this};
+  base::ScopedObservation<chromeos::PowerManagerClient,
+                          chromeos::PowerManagerClient::Observer>
+      power_manager_client_observation_{this};
+
+  base::WeakPtrFactory<HumanPresenceOrientationController> weak_factory_{this};
 };
 
 }  // namespace ash
diff --git a/ash/system/human_presence/human_presence_orientation_controller_unittest.cc b/ash/system/human_presence/human_presence_orientation_controller_unittest.cc
index f673890..381cd30 100644
--- a/ash/system/human_presence/human_presence_orientation_controller_unittest.cc
+++ b/ash/system/human_presence/human_presence_orientation_controller_unittest.cc
@@ -10,6 +10,8 @@
 #include "base/command_line.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/time/time.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "ui/display/display.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/test/display_manager_test_api.h"
@@ -54,12 +56,14 @@
                                           {ash::features::kQuickDim});
     base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kHasHps);
 
+    PowerManagerClient::InitializeFake();
     AshTestBase::SetUp();
 
     orientation_controller_ =
         Shell::Get()->human_presence_orientation_controller();
     tablet_mode_controller_ = Shell::Get()->tablet_mode_controller();
     display_manager_ = Shell::Get()->display_manager();
+    power_manager_client_ = AshTestBase::power_manager_client();
 
     // Two displays: the first internal and the second external.
     UpdateDisplay("800x600,1024x768");
@@ -78,6 +82,7 @@
   HumanPresenceOrientationController* orientation_controller_ = nullptr;
   TabletModeController* tablet_mode_controller_ = nullptr;
   display::DisplayManager* display_manager_ = nullptr;
+  chromeos::FakePowerManagerClient* power_manager_client_ = nullptr;
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -111,6 +116,16 @@
   EXPECT_TRUE(orientation_controller_->IsOrientationSuitable());
 }
 
+TEST_F(HumanPresenceOrientationControllerTest, LidState) {
+  ASSERT_TRUE(orientation_controller_->IsOrientationSuitable());
+  power_manager_client_->SetLidState(
+      chromeos::PowerManagerClient::LidState::CLOSED, base::TimeTicks());
+  ASSERT_FALSE(orientation_controller_->IsOrientationSuitable());
+  power_manager_client_->SetLidState(
+      chromeos::PowerManagerClient::LidState::OPEN, base::TimeTicks());
+  ASSERT_TRUE(orientation_controller_->IsOrientationSuitable());
+}
+
 TEST_F(HumanPresenceOrientationControllerTest, Observer) {
   TestObserver observer;
   orientation_controller_->AddObserver(&observer);
@@ -139,6 +154,17 @@
   EXPECT_EQ(observer.observation_count(), 2);
   EXPECT_EQ(observer.last_observation(), /*suitable_for_hps=*/true);
 
+  // Closing the device lid makes the device unsuitable.
+  power_manager_client_->SetLidState(
+      chromeos::PowerManagerClient::LidState::CLOSED, base::TimeTicks());
+  EXPECT_EQ(observer.observation_count(), 3);
+  ASSERT_FALSE(observer.last_observation());
+  // Opening the device lid makes the device suitable.
+  power_manager_client_->SetLidState(
+      chromeos::PowerManagerClient::LidState::OPEN, base::TimeTicks());
+  EXPECT_EQ(observer.observation_count(), 4);
+  EXPECT_TRUE(observer.last_observation());
+
   orientation_controller_->RemoveObserver(&observer);
 }
 
diff --git a/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc b/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc
index 2d144e9..f84570f 100644
--- a/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc
+++ b/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc
@@ -15,6 +15,7 @@
 #include "ash/system/keyboard_brightness/keyboard_backlight_color_nudge_controller.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
 #include "ash/webui/personalization_app/mojom/personalization_app.mojom.h"
+#include "base/metrics/histogram_functions.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -51,7 +52,19 @@
   DCHECK(rgb_keyboard_manager);
   DVLOG(3) << __func__ << " backlight_color=" << backlight_color;
   switch (backlight_color) {
-    case personalization_app::mojom::BacklightColor::kWallpaper:
+    case personalization_app::mojom::BacklightColor::kWallpaper: {
+      SkColor color = ConvertBacklightColorToSkColor(backlight_color);
+      bool valid_color = color != kInvalidWallpaperColor;
+      base::UmaHistogramBoolean(
+          "Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid",
+          valid_color);
+      // Default to |kDefaultColor| if |color| is invalid.
+      if (!valid_color)
+        color = kDefaultColor;
+      rgb_keyboard_manager->SetStaticBackgroundColor(
+          SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
+      break;
+    }
     case personalization_app::mojom::BacklightColor::kWhite:
     case personalization_app::mojom::BacklightColor::kRed:
     case personalization_app::mojom::BacklightColor::kYellow:
diff --git a/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc b/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc
index 05cddae0..209385a 100644
--- a/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc
+++ b/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc
@@ -8,6 +8,7 @@
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -41,10 +42,15 @@
   }
 
  protected:
+  const base::HistogramTester& histogram_tester() const {
+    return histogram_tester_;
+  }
+
   KeyboardBacklightColorController* controller_ = nullptr;
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
+  base::HistogramTester histogram_tester_;
 };
 
 TEST_F(KeyboardBacklightColorControllerTest, SetBacklightColorUpdatesPref) {
@@ -64,6 +70,12 @@
   SimulateUserLogin(account_id_1);
   EXPECT_EQ(personalization_app::mojom::BacklightColor::kWallpaper,
             controller_->GetBacklightColor());
+  // Expect the Wallpaper color to be set twice. Once on login screen and once
+  // after the user logs in.
+  histogram_tester().ExpectBucketCount(
+      "Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid", false, 2);
+  histogram_tester().ExpectTotalCount(
+      "Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid", 2);
   controller_->SetBacklightColor(
       personalization_app::mojom::BacklightColor::kRainbow);
   EXPECT_EQ(personalization_app::mojom::BacklightColor::kRainbow,
diff --git a/ash/system/message_center/ash_notification_view.cc b/ash/system/message_center/ash_notification_view.cc
index 3dd6763..5636a25 100644
--- a/ash/system/message_center/ash_notification_view.cc
+++ b/ash/system/message_center/ash_notification_view.cc
@@ -116,7 +116,8 @@
     message_center::kNotificationWidth * message_center::kMaxTitleLines /
     message_center::kMinPixelsPerTitleCharacter;
 constexpr int kTitleLabelSize = 13;
-constexpr int kTitleLabelMaxLines = 2;
+constexpr int kTitleLabelExpandedMaxLines = 2;
+constexpr int kTitleLabelCollapsedMaxLines = 1;
 constexpr int kTimestampInCollapsedViewSize = 12;
 constexpr int kMessageLabelSize = 12;
 // The size for `icon_view_`, which is the icon within right content (between
@@ -264,10 +265,8 @@
 }
 
 AshNotificationView::NotificationTitleRow::NotificationTitleRow(
-    AshNotificationView* parent,
     const std::u16string& title)
-    : parent_(parent),
-      title_view_(AddChildView(GenerateTitleView(title))),
+    : title_view_(AddChildView(GenerateTitleView(title))),
       title_row_divider_(AddChildView(std::make_unique<views::Label>(
           kTitleRowDivider,
           views::style::CONTEXT_DIALOG_BODY_TEXT))),
@@ -284,8 +283,8 @@
                                views::MaximumFlexSizeRule::kPreferred));
   title_view_->SetMultiLine(true);
   title_view_->SetAllowCharacterBreak(true);
-  title_view_->SetMaxLines(kTitleLabelMaxLines);
-  title_view_->SetMaximumWidth(parent->GetExpandedTitleLabelWidth());
+  title_view_->SetMaxLines(kTitleLabelExpandedMaxLines);
+  title_view_->SetMaximumWidth(kNotificationInMessageCenterWidth);
 
   ConfigureLabelStyle(title_row_divider_, kTimestampInCollapsedViewSize,
                       /*is_color_primary=*/false);
@@ -878,6 +877,9 @@
   if (title_row_) {
     title_row_->UpdateVisibility(is_grouped_child_view_ ||
                                  (IsExpandable() && !expanded));
+    title_row_->title_view()->SetMaxLines(
+        expanded ? kTitleLabelExpandedMaxLines : kTitleLabelCollapsedMaxLines);
+    title_row_->title_view()->SetMaximumWidth(GetExpandedTitleLabelWidth());
   }
 
   if (message_label()) {
@@ -1009,8 +1011,8 @@
       notification.title(), kTitleCharacterLimit, gfx::WORD_BREAK);
 
   if (!title_row_) {
-    title_row_ = AddViewToLeftContent(
-        std::make_unique<NotificationTitleRow>(this, title));
+    title_row_ =
+        AddViewToLeftContent(std::make_unique<NotificationTitleRow>(title));
   } else {
     title_row_->UpdateTitle(title);
     ReorderViewInLeftContent(title_row_);
diff --git a/ash/system/message_center/ash_notification_view.h b/ash/system/message_center/ash_notification_view.h
index 45d3a15..8deb79c8 100644
--- a/ash/system/message_center/ash_notification_view.h
+++ b/ash/system/message_center/ash_notification_view.h
@@ -147,8 +147,7 @@
   class NotificationTitleRow : public views::View {
    public:
     METADATA_HEADER(NotificationTitleRow);
-    NotificationTitleRow(AshNotificationView* parent,
-                         const std::u16string& title);
+    explicit NotificationTitleRow(const std::u16string& title);
     NotificationTitleRow(const NotificationTitleRow&) = delete;
     NotificationTitleRow& operator=(const NotificationTitleRow&) = delete;
     ~NotificationTitleRow() override;
@@ -169,11 +168,10 @@
     // views::View:
     void OnThemeChanged() override;
 
+    views::Label* title_view() { return title_view_; }
+
    private:
     friend class AshNotificationViewTest;
-
-    AshNotificationView* const parent_;
-
     // Showing notification title.
     views::Label* const title_view_;
 
diff --git a/ash/system/network/active_network_icon_unittest.cc b/ash/system/network/active_network_icon_unittest.cc
index 9cbd0e1..df4b811 100644
--- a/ash/system/network/active_network_icon_unittest.cc
+++ b/ash/system/network/active_network_icon_unittest.cc
@@ -14,8 +14,8 @@
 #include "ash/test/ash_test_base.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/system/network/auto_connect_notifier_unittest.cc b/ash/system/network/auto_connect_notifier_unittest.cc
index a266f90..ceec050 100644
--- a/ash/system/network/auto_connect_notifier_unittest.cc
+++ b/ash/system/network/auto_connect_notifier_unittest.cc
@@ -16,10 +16,10 @@
 #include "base/run_loop.h"
 #include "base/timer/mock_timer.h"
 #include "chromeos/ash/components/network/auto_connect_handler.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/system_token_cert_db_storage.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "dbus/object_path.h"
diff --git a/ash/system/network/cellular_setup_notifier.h b/ash/system/network/cellular_setup_notifier.h
index 0b2814a..e803c61 100644
--- a/ash/system/network/cellular_setup_notifier.h
+++ b/ash/system/network/cellular_setup_notifier.h
@@ -8,7 +8,7 @@
 #include "ash/ash_export.h"
 #include "ash/public/cpp/session/session_observer.h"
 #include "base/gtest_prod_util.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "components/prefs/pref_service.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
@@ -25,7 +25,7 @@
 // inserted a cold pSIM and need to provision in-session.
 class ASH_EXPORT CellularSetupNotifier
     : public SessionObserver,
-      public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+      public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   CellularSetupNotifier();
   CellularSetupNotifier(const CellularSetupNotifier&) = delete;
@@ -56,16 +56,9 @@
 
   // CrosNetworkConfigObserver:
   void OnNetworkStateListChanged() override;
-  void OnActiveNetworksChanged(
-      std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
-          networks) override {}
   void OnNetworkStateChanged(
       chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
       override;
-  void OnDeviceStateListChanged() override {}
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
   void MaybeShowCellularSetupNotification();
   void OnTimerFired();
diff --git a/ash/system/network/managed_sim_lock_notifier.h b/ash/system/network/managed_sim_lock_notifier.h
index 201b640e..bde31e3 100644
--- a/ash/system/network/managed_sim_lock_notifier.h
+++ b/ash/system/network/managed_sim_lock_notifier.h
@@ -9,7 +9,7 @@
 #include "ash/public/cpp/session/session_observer.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 namespace ash {
@@ -18,7 +18,7 @@
 // restrict cellular SIM lock Global Network Configuration is set to true.
 class ASH_EXPORT ManagedSimLockNotifier
     : public SessionObserver,
-      public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+      public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   ManagedSimLockNotifier();
   ManagedSimLockNotifier(const ManagedSimLockNotifier&) = delete;
@@ -32,16 +32,7 @@
   void OnSessionStateChanged(session_manager::SessionState state) override;
 
   // CrosNetworkConfigObserver:
-  void OnNetworkStateListChanged() override {}
-  void OnActiveNetworksChanged(
-      std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
-          networks) override {}
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
-      override {}
   void OnDeviceStateListChanged() override;
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
   void OnPoliciesApplied(const std::string& userhash) override;
 
   void OnGetDeviceStateList(
diff --git a/ash/system/network/managed_sim_lock_notifier_unittest.cc b/ash/system/network/managed_sim_lock_notifier_unittest.cc
index 33b9227..d14c6fec6 100644
--- a/ash/system/network/managed_sim_lock_notifier_unittest.cc
+++ b/ash/system/network/managed_sim_lock_notifier_unittest.cc
@@ -10,8 +10,8 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
diff --git a/ash/system/network/network_feature_pod_controller_unittest.cc b/ash/system/network/network_feature_pod_controller_unittest.cc
index 3f466e7..7ad83e2 100644
--- a/ash/system/network/network_feature_pod_controller_unittest.cc
+++ b/ash/system/network/network_feature_pod_controller_unittest.cc
@@ -22,9 +22,9 @@
 #include "ash/test/ash_test_base.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_feature_list.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_handler_callbacks.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/network_type_pattern.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/ash/system/network/network_icon_unittest.cc b/ash/system/network/network_icon_unittest.cc
index 582ede1..75323686 100644
--- a/ash/system/network/network_icon_unittest.cc
+++ b/ash/system/network/network_icon_unittest.cc
@@ -14,8 +14,8 @@
 #include "ash/test/ash_test_base.h"
 #include "base/logging.h"
 #include "base/run_loop.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/tether_constants.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/ash/system/network/network_list_view_controller_unittest.cc b/ash/system/network/network_list_view_controller_unittest.cc
index 913da286..a9e2df1 100644
--- a/ash/system/network/network_list_view_controller_unittest.cc
+++ b/ash/system/network/network_list_view_controller_unittest.cc
@@ -22,7 +22,7 @@
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
-#include "chromeos/network/mock_managed_network_configuration_handler.h"
+#include "chromeos/ash/components/network/mock_managed_network_configuration_handler.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/services/bluetooth_config/fake_adapter_state_controller.h"
 #include "chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h"
diff --git a/ash/system/network/tray_network_state_model.cc b/ash/system/network/tray_network_state_model.cc
index fd7944d..53417dd 100644
--- a/ash/system/network/tray_network_state_model.cc
+++ b/ash/system/network/tray_network_state_model.cc
@@ -13,8 +13,8 @@
 #include "base/callback_helpers.h"
 #include "base/containers/contains.h"
 #include "base/location.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -53,7 +53,7 @@
 namespace ash {
 
 class TrayNetworkStateModel::Impl
-    : public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+    : public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   explicit Impl(TrayNetworkStateModel* model) : model_(model) {
     GetNetworkConfigService(
@@ -116,10 +116,6 @@
     model_->SendActiveNetworkStateChanged();
   }
 
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr /* network */)
-      override {}
-
   void OnNetworkStateListChanged() override {
     model_->NotifyNetworkListChanged();
     GetVirtualNetworks();
@@ -129,8 +125,6 @@
 
   void OnVpnProvidersChanged() override { model_->NotifyVpnProvidersChanged(); }
 
-  void OnNetworkCertificatesChanged() override {}
-
   void OnPoliciesApplied(const std::string& userhash) override {
     GetGlobalPolicy();
   }
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc
index 44a880b..779eb402 100644
--- a/ash/system/status_area_widget_unittest.cc
+++ b/ash/system/status_area_widget_unittest.cc
@@ -34,8 +34,8 @@
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "chromeos/ash/components/network/cellular_metrics_logger.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/session_manager/session_manager_types.h"
 #include "ui/events/event.h"
diff --git a/ash/system/time/calendar_month_view_unittest.cc b/ash/system/time/calendar_month_view_unittest.cc
index 6596568..79e37df 100644
--- a/ash/system/time/calendar_month_view_unittest.cc
+++ b/ash/system/time/calendar_month_view_unittest.cc
@@ -77,8 +77,8 @@
     ash::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(timezone);
     controller_ = std::make_unique<CalendarViewController>();
     controller_->UpdateMonth(date);
-    calendar_month_view_ =
-        std::make_unique<CalendarMonthView>(date, controller_.get());
+    calendar_month_view_ = std::make_unique<CalendarMonthView>(
+        controller_->GetOnScreenMonthFirstDayUTC(), controller_.get());
     calendar_month_view_->Layout();
   }
 
@@ -215,6 +215,44 @@
                       ->GetText());
 }
 
+// Tests that the month view should be rendered correctly with any time zone.
+// Using March to test since there's a DST change in several time zones in
+// March. If any calculation is wrong, there could be duplicated dates and the
+// last row will be rendered with one day off.
+TEST_F(CalendarMonthViewTest, AllTimeZone) {
+  // Create a monthview based on Mar,1st 2022.
+  //
+  // 27, 28, 1 , 2 , 3 , 4 , 5
+  // 6,  7,  8 , 9 , 10, 11, 12
+  // 13, 14, 15, 16, 17, 18, 19
+  // 20, 21, 22, 23, 24, 25, 26
+  // 27, 28, 29, 30, 31, 1 , 2
+  base::Time date;
+  ASSERT_TRUE(base::Time::FromString("6 Mar 2022 10:00 GMT", &date));
+
+  for (auto* timezone : kAllTimeZones) {
+    // Creates a month view based on the current timezone.
+    CreateMonthView(date, base::UTF8ToUTF16(timezone));
+
+    // Checks some dates in the first row and last row of this month view.
+    EXPECT_EQ(u"27",
+              static_cast<views::LabelButton*>(month_view()->children()[0])
+                  ->GetText());
+    EXPECT_EQ(u"28",
+              static_cast<views::LabelButton*>(month_view()->children()[1])
+                  ->GetText());
+    EXPECT_EQ(u"1",
+              static_cast<views::LabelButton*>(month_view()->children()[2])
+                  ->GetText());
+    EXPECT_EQ(u"29",
+              static_cast<views::LabelButton*>(month_view()->children()[30])
+                  ->GetText());
+    EXPECT_EQ(u"2",
+              static_cast<views::LabelButton*>(month_view()->children()[34])
+                  ->GetText());
+  }
+}
+
 // Tests that todays row position is not updated when today is not in the month.
 TEST_F(CalendarMonthViewTest, TodayNotInMonth) {
   base::Time date;
diff --git a/ash/system/time/calendar_unittest_utils.h b/ash/system/time/calendar_unittest_utils.h
index da3f8f8..be0e0f3c 100644
--- a/ash/system/time/calendar_unittest_utils.h
+++ b/ash/system/time/calendar_unittest_utils.h
@@ -12,6 +12,166 @@
 
 namespace ash {
 
+namespace {
+// This list is from "ash/components/settings/timezone_settings.cc"
+const char* kAllTimeZones[] = {"Pacific/Midway",
+                               "Pacific/Honolulu",
+                               "America/Anchorage",
+                               "America/Los_Angeles",
+                               "America/Vancouver",
+                               "America/Tijuana",
+                               "America/Phoenix",
+                               "America/Chihuahua",
+                               "America/Denver",
+                               "America/Edmonton",
+                               "America/Mazatlan",
+                               "America/Regina",
+                               "America/Costa_Rica",
+                               "America/Chicago",
+                               "America/Mexico_City",
+                               "America/Tegucigalpa",
+                               "America/Winnipeg",
+                               "Pacific/Easter",
+                               "America/Bogota",
+                               "America/Lima",
+                               "America/New_York",
+                               "America/Toronto",
+                               "America/Caracas",
+                               "America/Barbados",
+                               "America/Halifax",
+                               "America/Manaus",
+                               "America/Santiago",
+                               "America/St_Johns",
+                               "America/Araguaina",
+                               "America/Argentina/Buenos_Aires",
+                               "America/Argentina/San_Luis",
+                               "America/Montevideo",
+                               "America/Santiago",
+                               "America/Sao_Paulo",
+                               "America/Godthab",
+                               "Atlantic/South_Georgia",
+                               "Atlantic/Cape_Verde",
+                               "Etc/GMT",
+                               "Atlantic/Azores",
+                               "Atlantic/Reykjavik",
+                               "Atlantic/St_Helena",
+                               "Africa/Casablanca",
+                               "Atlantic/Faroe",
+                               "Europe/Dublin",
+                               "Europe/Lisbon",
+                               "Europe/London",
+                               "Europe/Amsterdam",
+                               "Europe/Belgrade",
+                               "Europe/Berlin",
+                               "Europe/Bratislava",
+                               "Europe/Brussels",
+                               "Europe/Budapest",
+                               "Europe/Copenhagen",
+                               "Europe/Ljubljana",
+                               "Europe/Madrid",
+                               "Europe/Malta",
+                               "Europe/Oslo",
+                               "Europe/Paris",
+                               "Europe/Prague",
+                               "Europe/Rome",
+                               "Europe/Stockholm",
+                               "Europe/Sarajevo",
+                               "Europe/Tirane",
+                               "Europe/Vaduz",
+                               "Europe/Vienna",
+                               "Europe/Warsaw",
+                               "Europe/Zagreb",
+                               "Europe/Zurich",
+                               "Africa/Windhoek",
+                               "Africa/Lagos",
+                               "Africa/Brazzaville",
+                               "Africa/Cairo",
+                               "Africa/Harare",
+                               "Africa/Maputo",
+                               "Africa/Johannesburg",
+                               "Europe/Kaliningrad",
+                               "Europe/Athens",
+                               "Europe/Bucharest",
+                               "Europe/Chisinau",
+                               "Europe/Helsinki",
+                               "Europe/Istanbul",
+                               "Europe/Kiev",
+                               "Europe/Riga",
+                               "Europe/Sofia",
+                               "Europe/Tallinn",
+                               "Europe/Vilnius",
+                               "Asia/Amman",
+                               "Asia/Beirut",
+                               "Asia/Jerusalem",
+                               "Africa/Nairobi",
+                               "Asia/Baghdad",
+                               "Asia/Riyadh",
+                               "Asia/Kuwait",
+                               "Europe/Minsk",
+                               "Europe/Moscow",
+                               "Asia/Tehran",
+                               "Europe/Samara",
+                               "Asia/Dubai",
+                               "Asia/Tbilisi",
+                               "Indian/Mauritius",
+                               "Asia/Baku",
+                               "Asia/Yerevan",
+                               "Asia/Kabul",
+                               "Asia/Karachi",
+                               "Asia/Aqtobe",
+                               "Asia/Ashgabat",
+                               "Asia/Oral",
+                               "Asia/Yekaterinburg",
+                               "Asia/Calcutta",
+                               "Asia/Colombo",
+                               "Asia/Katmandu",
+                               "Asia/Omsk",
+                               "Asia/Almaty",
+                               "Asia/Dhaka",
+                               "Asia/Novosibirsk",
+                               "Asia/Rangoon",
+                               "Asia/Bangkok",
+                               "Asia/Jakarta",
+                               "Asia/Krasnoyarsk",
+                               "Asia/Novokuznetsk",
+                               "Asia/Ho_Chi_Minh",
+                               "Asia/Phnom_Penh",
+                               "Asia/Vientiane",
+                               "Asia/Shanghai",
+                               "Asia/Hong_Kong",
+                               "Asia/Kuala_Lumpur",
+                               "Asia/Singapore",
+                               "Asia/Manila",
+                               "Asia/Taipei",
+                               "Asia/Ulaanbaatar",
+                               "Asia/Makassar",
+                               "Asia/Irkutsk",
+                               "Asia/Yakutsk",
+                               "Australia/Perth",
+                               "Australia/Eucla",
+                               "Asia/Seoul",
+                               "Asia/Tokyo",
+                               "Asia/Jayapura",
+                               "Asia/Sakhalin",
+                               "Asia/Vladivostok",
+                               "Asia/Magadan",
+                               "Australia/Darwin",
+                               "Australia/Adelaide",
+                               "Pacific/Guam",
+                               "Australia/Brisbane",
+                               "Australia/Hobart",
+                               "Australia/Sydney",
+                               "Asia/Anadyr",
+                               "Pacific/Port_Moresby",
+                               "Asia/Kamchatka",
+                               "Pacific/Fiji",
+                               "Pacific/Majuro",
+                               "Pacific/Auckland",
+                               "Pacific/Tongatapu",
+                               "Pacific/Apia",
+                               "Pacific/Kiritimati"};
+}  // namespace
+
 namespace calendar_test_utils {
 
 // A duration to let the animation finish and pass the cool down duration in
diff --git a/ash/system/time/date_helper.cc b/ash/system/time/date_helper.cc
index 4d25ba5a..8a2fbf9 100644
--- a/ash/system/time/date_helper.cc
+++ b/ash/system/time/date_helper.cc
@@ -177,7 +177,8 @@
   // titles, since there are no daylight saving starts/ends in June worldwide.
   // If the `DCHECK` fails, use `Now()`.
   base::Time start_date = base::Time::Now();
-  DCHECK(base::Time::FromString("15 Jun 2021 10:00 GMT", &start_date));
+  bool result = base::Time::FromString("15 Jun 2021 10:00 GMT", &start_date);
+  DCHECK(result);
   start_date = GetLocalMidnight(start_date);
   std::u16string day_of_week =
       GetFormattedTime(&day_of_week_formatter_, start_date);
@@ -195,11 +196,12 @@
   while (day_int != 1) {
     start_date += base::Hours(25);
     day_of_week = GetFormattedTime(&day_of_week_formatter_, start_date);
-    DCHECK(base::StringToInt(day_of_week, &day_int));
+    bool result = base::StringToInt(day_of_week, &day_int);
+    DCHECK(result);
     ++safe_index;
     // Should already find the first day within 7 times, since there are only 7
     // days in a week.
-    CHECK_NE(safe_index, calendar_utils::kDateInOneWeek);
+    DCHECK_NE(safe_index, calendar_utils::kDateInOneWeek);
   }
 
   int day_index = 0;
diff --git a/ash/system/time/date_helper_unittest.cc b/ash/system/time/date_helper_unittest.cc
index 55879c0..62eb870 100644
--- a/ash/system/time/date_helper_unittest.cc
+++ b/ash/system/time/date_helper_unittest.cc
@@ -127,7 +127,7 @@
 TEST_F(DateHelperUnittest, GetWeekTitleForAllLocales) {
   for (auto* local : kLocales) {
     SetDefaultLocale(local);
-    DateHelper::GetInstance()->week_titles();
+    EXPECT_EQ(7U, DateHelper::GetInstance()->week_titles().size());
   }
 }
 
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller_impl.h
index 22d6ff6..348f6e5 100644
--- a/ash/wallpaper/wallpaper_controller_impl.h
+++ b/ash/wallpaper/wallpaper_controller_impl.h
@@ -371,7 +371,7 @@
   FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest, BasicReparenting);
   FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest,
                            WallpaperMovementDuringUnlock);
-  friend class WallpaperControllerTestBase;
+  friend class WallpaperControllerTest;
   friend class WallpaperControllerTestApi;
 
   enum WallpaperMode { WALLPAPER_NONE, WALLPAPER_IMAGE };
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index f6512f3..6170c109 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -403,14 +403,13 @@
 
 }  // namespace
 
-class WallpaperControllerTestBase : public AshTestBase {
+class WallpaperControllerTest : public AshTestBase {
  public:
-  WallpaperControllerTestBase()
+  WallpaperControllerTest()
       : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
 
-  WallpaperControllerTestBase(const WallpaperControllerTestBase&) = delete;
-  WallpaperControllerTestBase& operator=(const WallpaperControllerTestBase&) =
-      delete;
+  WallpaperControllerTest(const WallpaperControllerTest&) = delete;
+  WallpaperControllerTest& operator=(const WallpaperControllerTest&) = delete;
 
   void SetUp() override {
     AshTestBase::SetUp();
@@ -744,37 +743,7 @@
   data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
 };
 
-class WallpaperControllerTest : public WallpaperControllerTestBase,
-                                public testing::WithParamInterface<bool> {
- public:
-  WallpaperControllerTest() = default;
-
-  WallpaperControllerTest(const WallpaperControllerTest&) = delete;
-  WallpaperControllerTest& operator=(const WallpaperControllerTest&) = delete;
-
-  ~WallpaperControllerTest() override = default;
-
-  void SetUp() override {
-    if (GetParam()) {
-      scoped_feature_list_.InitWithFeatures(
-          {ash::features::kWallpaperWebUI,
-           ash::features::kWallpaperFullScreenPreview},
-          {});
-    } else {
-      scoped_feature_list_.InitWithFeatures(
-          {}, {ash::features::kWallpaperWebUI,
-               ash::features::kWallpaperFullScreenPreview});
-    }
-    WallpaperControllerTestBase::SetUp();
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-INSTANTIATE_TEST_SUITE_P(All, WallpaperControllerTest, testing::Bool());
-
-TEST_P(WallpaperControllerTest, Client) {
+TEST_F(WallpaperControllerTest, Client) {
   base::FilePath empty_path;
   controller_->Init(empty_path, empty_path, empty_path, empty_path);
 
@@ -784,7 +753,7 @@
   EXPECT_EQ(1u, client_.open_count());
 }
 
-TEST_P(WallpaperControllerTest, BasicReparenting) {
+TEST_F(WallpaperControllerTest, BasicReparenting) {
   WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller();
   controller->CreateEmptyWallpaperForTesting();
 
@@ -806,7 +775,7 @@
   EXPECT_EQ(0, ChildCountForContainer(kLockScreenWallpaperId));
 }
 
-TEST_P(WallpaperControllerTest, SwitchWallpapersWhenNewWallpaperAnimationEnds) {
+TEST_F(WallpaperControllerTest, SwitchWallpapersWhenNewWallpaperAnimationEnds) {
   // We cannot short-circuit animations for this test.
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
@@ -829,7 +798,7 @@
 
 // Test for crbug.com/149043 "Unlock screen, no launcher appears". Ensure we
 // move all wallpaper views if there are more than one.
-TEST_P(WallpaperControllerTest, WallpaperMovementDuringUnlock) {
+TEST_F(WallpaperControllerTest, WallpaperMovementDuringUnlock) {
   // We cannot short-circuit animations for this test.
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
@@ -881,7 +850,7 @@
 
 // Test for crbug.com/156542. Animating wallpaper should immediately finish
 // animation and replace current wallpaper before next animation starts.
-TEST_P(WallpaperControllerTest, ChangeWallpaperQuick) {
+TEST_F(WallpaperControllerTest, ChangeWallpaperQuick) {
   // We cannot short-circuit animations for this test.
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
@@ -911,7 +880,7 @@
   EXPECT_FALSE(widget_controller->IsAnimating());
 }
 
-TEST_P(WallpaperControllerTest, ResizeCustomWallpaper) {
+TEST_F(WallpaperControllerTest, ResizeCustomWallpaper) {
   UpdateDisplay("320x200");
 
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
@@ -937,7 +906,7 @@
   EXPECT_TRUE(resized_image.BackedBySameObjectAs(controller_->GetWallpaper()));
 }
 
-TEST_P(WallpaperControllerTest, GetMaxDisplaySize) {
+TEST_F(WallpaperControllerTest, GetMaxDisplaySize) {
   // Device scale factor shouldn't affect the native size.
   UpdateDisplay("1000x300*2");
   EXPECT_EQ("1000x300",
@@ -971,7 +940,7 @@
 
 // Test that the wallpaper is always fitted to the native display resolution
 // when the layout is WALLPAPER_LAYOUT_CENTER to prevent blurry images.
-TEST_P(WallpaperControllerTest, DontScaleWallpaperWithCenterLayout) {
+TEST_F(WallpaperControllerTest, DontScaleWallpaperWithCenterLayout) {
   // We cannot short-circuit animations for this test.
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
@@ -1047,7 +1016,7 @@
   }
 }
 
-TEST_P(WallpaperControllerTest, ShouldCalculateColorsBasedOnImage) {
+TEST_F(WallpaperControllerTest, ShouldCalculateColorsBasedOnImage) {
   EnableShelfColoring();
   EXPECT_TRUE(ShouldCalculateColors());
 
@@ -1055,7 +1024,7 @@
   EXPECT_FALSE(ShouldCalculateColors());
 }
 
-TEST_P(WallpaperControllerTest, ShouldCalculateColorsBasedOnSessionState) {
+TEST_F(WallpaperControllerTest, ShouldCalculateColorsBasedOnSessionState) {
   EnableShelfColoring();
 
   SetSessionState(SessionState::UNKNOWN);
@@ -1080,7 +1049,7 @@
   EXPECT_FALSE(ShouldCalculateColors());
 }
 
-TEST_P(WallpaperControllerTest, EnableShelfColoringNotifiesObservers) {
+TEST_F(WallpaperControllerTest, EnableShelfColoringNotifiesObservers) {
   TestWallpaperControllerObserver observer(controller_);
   EXPECT_EQ(0, observer.colors_changed_count());
 
@@ -1091,73 +1060,7 @@
   EXPECT_EQ(1, observer.colors_changed_count());
 }
 
-TEST_P(WallpaperControllerTest, SetOnlineWallpaperIfExists) {
-  SetBypassDecode();
-  gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
-  WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER_CROPPED;
-  SimulateUserLogin(account_id_1);
-
-  // Verify that calling |SetOnlineWallpaperIfExists| without providing image
-  // data fails.
-  std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
-  ClearWallpaperCount();
-  const OnlineWallpaperParams& params = OnlineWallpaperParams(
-      account_id_1, kAssetId, GURL(kDummyUrl),
-      TestWallpaperControllerClient::kDummyCollectionId, layout,
-      /*preview_mode=*/false, /*from_user=*/true,
-      /*daily_refresh_enabled=*/false, kUnitId,
-      /*variants=*/std::vector<OnlineWallpaperVariant>());
-  controller_->SetOnlineWallpaperIfExists(
-      params, base::BindLambdaForTesting([&run_loop](bool file_exists) {
-        EXPECT_FALSE(file_exists);
-        run_loop->Quit();
-      }));
-  run_loop->Run();
-  EXPECT_EQ(0, GetWallpaperCount());
-
-  // Set an online wallpaper with image data. Verify that the wallpaper is set
-  // successfully.
-  ClearWallpaperCount();
-  controller_->SetOnlineWallpaperFromData(
-      params,
-      /*image_data=*/std::string(),
-      WallpaperController::SetWallpaperCallback());
-  RunAllTasksUntilIdle();
-  EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
-  // Verify that the user wallpaper info is updated.
-  WallpaperInfo wallpaper_info;
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info));
-  WallpaperInfo expected_wallpaper_info(params);
-  EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
-
-  // Change the on-screen wallpaper to a different one. (Otherwise the
-  // subsequent calls will be no-op since we intentionally prevent reloading the
-  // same wallpaper.)
-  ClearWallpaperCount();
-  controller_->SetCustomWallpaper(account_id_1, file_name_1, layout,
-                                  CreateImage(640, 480, kWallpaperColor),
-                                  /*preview_mode=*/false);
-  RunAllTasksUntilIdle();
-  EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kCustomized);
-
-  // Attempt to set an online wallpaper via |SetOnlineWallpaperIfExists| without
-  // providing the image data. Verify it succeeds this time because
-  // |SetOnlineWallpaperFromData| has saved the file.
-  ClearWallpaperCount();
-  run_loop = std::make_unique<base::RunLoop>();
-  controller_->SetOnlineWallpaperIfExists(
-      params, base::BindLambdaForTesting([&run_loop](bool file_exists) {
-        EXPECT_TRUE(file_exists);
-        run_loop->Quit();
-      }));
-  run_loop->Run();
-  EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
-}
-
-TEST_P(WallpaperControllerTest, SetOnlineWallpaperFromDataSavesFile) {
+TEST_F(WallpaperControllerTest, SetOnlineWallpaperFromDataSavesFile) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   SimulateUserLogin(account_id_1);
@@ -1196,7 +1099,7 @@
   run_loop->Run();
 }
 
-TEST_P(WallpaperControllerTest,
+TEST_F(WallpaperControllerTest,
        UpdatePrimaryUserWallpaperWhileSecondUserActive) {
   SetBypassDecode();
   WallpaperInfo wallpaper_info;
@@ -1245,7 +1148,7 @@
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info_2);
 }
 
-TEST_P(WallpaperControllerTest, SetOnlineWallpaper) {
+TEST_F(WallpaperControllerTest, SetOnlineWallpaper) {
   SetBypassDecode();
 
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
@@ -1296,7 +1199,7 @@
   run_loop->Run();
 }
 
-TEST_P(WallpaperControllerTest, SetAndRemovePolicyWallpaper) {
+TEST_F(WallpaperControllerTest, SetAndRemovePolicyWallpaper) {
   SetBypassDecode();
   // Simulate the login screen.
   ClearLogin();
@@ -1371,7 +1274,7 @@
 
 // Simulates the scenario where the wallpaper are not yet resized and only the
 // original size image is available.
-TEST_P(WallpaperControllerTest, ShowUserWallpaper_OriginalFallback) {
+TEST_F(WallpaperControllerTest, ShowUserWallpaper_OriginalFallback) {
   SetBypassDecode();
   CreateDefaultWallpapers();
 
@@ -1417,7 +1320,7 @@
 
 // Simulates a missing wallpaper due (possibly) an outdated preference. In this
 // situation, we fallback to the default.
-TEST_P(WallpaperControllerTest, ShowUserWallpaper_MissingFile) {
+TEST_F(WallpaperControllerTest, ShowUserWallpaper_MissingFile) {
   CreateDefaultWallpapers();
 
   // Simulate the login screen.
@@ -1449,7 +1352,7 @@
               testing::EndsWith(kDefaultSmallWallpaperName));
 }
 
-TEST_P(WallpaperControllerTest, RemovePolicyWallpaperNoOp) {
+TEST_F(WallpaperControllerTest, RemovePolicyWallpaperNoOp) {
   auto verify_custom_wallpaper_info = [&]() {
     EXPECT_EQ(WallpaperType::kCustomized, controller_->GetWallpaperType());
     EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -1483,7 +1386,7 @@
   verify_custom_wallpaper_info();
 }
 
-TEST_P(WallpaperControllerTest, SetThirdPartyWallpaper) {
+TEST_F(WallpaperControllerTest, SetThirdPartyWallpaper) {
   SetBypassDecode();
   SimulateUserLogin(account_id_1);
 
@@ -1552,7 +1455,7 @@
   EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
 }
 
-TEST_P(WallpaperControllerTest, SetDefaultWallpaperForRegularAccount) {
+TEST_F(WallpaperControllerTest, SetDefaultWallpaperForRegularAccount) {
   CreateDefaultWallpapers();
   SimulateUserLogin(account_id_1);
 
@@ -1628,7 +1531,7 @@
   EXPECT_EQ(wallpaper_info, default_wallpaper_info);
 }
 
-TEST_P(WallpaperControllerTest, SetDefaultWallpaperForChildAccount) {
+TEST_F(WallpaperControllerTest, SetDefaultWallpaperForChildAccount) {
   CreateDefaultWallpapers();
 
   fake_user_manager_->AddChildUser(kChildAccountId);
@@ -1667,7 +1570,7 @@
 // Verify that the |ShowWallpaperImage| will be called with the default image
 // for the guest session only even if there's a policy that has been set for
 // another user which invokes |SetPolicyWallpaper|.
-TEST_P(WallpaperControllerTest,
+TEST_F(WallpaperControllerTest,
        SetDefaultWallpaperForGuestSessionUnaffectedByWallpaperPolicy) {
   SetBypassDecode();
   // Simulate the login screen.
@@ -1731,7 +1634,7 @@
             GetDecodeFilePaths()[0]);
 }
 
-TEST_P(WallpaperControllerTest, SetDefaultWallpaperForGuestSession) {
+TEST_F(WallpaperControllerTest, SetDefaultWallpaperForGuestSession) {
   CreateDefaultWallpapers();
 
   // First, simulate setting a custom wallpaper for a regular user.
@@ -1780,7 +1683,7 @@
             GetDecodeFilePaths()[0]);
 }
 
-TEST_P(WallpaperControllerTest, SetDefaultWallpaperCallbackTiming) {
+TEST_F(WallpaperControllerTest, SetDefaultWallpaperCallbackTiming) {
   SetBypassDecode();
   SimulateUserLogin(account_id_1);
 
@@ -1808,7 +1711,7 @@
   EXPECT_EQ(1, observer.wallpaper_changed_count());
 }
 
-TEST_P(WallpaperControllerTest, IgnoreWallpaperRequestInKioskMode) {
+TEST_F(WallpaperControllerTest, IgnoreWallpaperRequestInKioskMode) {
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   SimulateUserLogin("kiosk", user_manager::USER_TYPE_KIOSK_APP);
 
@@ -1857,12 +1760,12 @@
 }
 
 // Disable the wallpaper setting for public session since it is ephemeral.
-TEST_P(WallpaperControllerTest, NotShowWallpaperSettingInPublicSession) {
+TEST_F(WallpaperControllerTest, NotShowWallpaperSettingInPublicSession) {
   SimulateUserLogin("public_session", user_manager::USER_TYPE_PUBLIC_ACCOUNT);
   EXPECT_FALSE(controller_->ShouldShowWallpaperSetting());
 }
 
-TEST_P(WallpaperControllerTest, IgnoreWallpaperRequestWhenPolicyIsEnforced) {
+TEST_F(WallpaperControllerTest, IgnoreWallpaperRequestWhenPolicyIsEnforced) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   SimulateUserLogin(account_id_1);
@@ -1974,7 +1877,7 @@
   }
 }
 
-TEST_P(WallpaperControllerTest, VerifyWallpaperCache) {
+TEST_F(WallpaperControllerTest, VerifyWallpaperCache) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   SimulateUserLogin(account_id_1);
@@ -2034,7 +1937,7 @@
 
 // Tests that the appropriate wallpaper (large vs. small) is shown depending
 // on the desktop resolution.
-TEST_P(WallpaperControllerTest, ShowCustomWallpaperWithCorrectResolution) {
+TEST_F(WallpaperControllerTest, ShowCustomWallpaperWithCorrectResolution) {
   CreateDefaultWallpapers();
   const base::FilePath small_custom_wallpaper_path =
       GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir,
@@ -2099,7 +2002,7 @@
 
 // After the display is rotated, the sign in wallpaper should be kept. Test for
 // crbug.com/794725.
-TEST_P(WallpaperControllerTest, SigninWallpaperIsKeptAfterRotation) {
+TEST_F(WallpaperControllerTest, SigninWallpaperIsKeptAfterRotation) {
   CreateDefaultWallpapers();
 
   UpdateDisplay("800x600");
@@ -2128,7 +2031,7 @@
 }
 
 // Display size change should trigger wallpaper reload.
-TEST_P(WallpaperControllerTest, ReloadWallpaper) {
+TEST_F(WallpaperControllerTest, ReloadWallpaper) {
   CreateAndSaveWallpapers(account_id_1);
 
   // Show a user wallpaper.
@@ -2188,7 +2091,7 @@
   EXPECT_EQ(1, GetWallpaperCount());
 }
 
-TEST_P(WallpaperControllerTest, UpdateCurrentWallpaperLayout) {
+TEST_F(WallpaperControllerTest, UpdateCurrentWallpaperLayout) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kSmallCustomWallpaperColor);
   WallpaperLayout layout = WALLPAPER_LAYOUT_STRETCH;
@@ -2224,9 +2127,7 @@
   {
     base::test::ScopedFeatureList scoped_feature_list;
     scoped_feature_list.InitWithFeatures(
-        {ash::features::kWallpaperWebUI,
-         ash::features::kWallpaperGooglePhotosIntegration},
-        {});
+        {ash::features::kWallpaperGooglePhotosIntegration}, {});
 
     // Now set a Google Photos wallpaper. Verify that it's set successfully and
     // the wallpaper info is updated.
@@ -2301,7 +2202,7 @@
 // Tests that if a user who has a custom wallpaper is removed from the device,
 // only the directory that contains the user's custom wallpapers gets removed.
 // The other user's custom wallpaper is not affected.
-TEST_P(WallpaperControllerTest, RemoveUserWithCustomWallpaper) {
+TEST_F(WallpaperControllerTest, RemoveUserWithCustomWallpaper) {
   SimulateUserLogin(account_id_1);
   base::FilePath small_wallpaper_path_1 =
       GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir,
@@ -2332,7 +2233,7 @@
 
 // Tests that if a user who has a default wallpaper is removed from the device,
 // the other user's custom wallpaper is not affected.
-TEST_P(WallpaperControllerTest, RemoveUserWithDefaultWallpaper) {
+TEST_F(WallpaperControllerTest, RemoveUserWithDefaultWallpaper) {
   SimulateUserLogin(account_id_1);
   base::FilePath small_wallpaper_path_1 =
       GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir,
@@ -2353,7 +2254,7 @@
   EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
 }
 
-TEST_P(WallpaperControllerTest, IsActiveUserWallpaperControlledByPolicy) {
+TEST_F(WallpaperControllerTest, IsActiveUserWallpaperControlledByPolicy) {
   SetBypassDecode();
   // Simulate the login screen. Verify that it returns false since there's no
   // active user.
@@ -2377,7 +2278,7 @@
   EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy());
 }
 
-TEST_P(WallpaperControllerTest, WallpaperBlur) {
+TEST_F(WallpaperControllerTest, WallpaperBlur) {
   TestWallpaperControllerObserver observer(controller_);
 
   ASSERT_TRUE(controller_->IsBlurAllowedForLockState());
@@ -2413,7 +2314,7 @@
   EXPECT_EQ(3, observer.blur_changed_count());
 }
 
-TEST_P(WallpaperControllerTest, WallpaperBlurDuringLockScreenTransition) {
+TEST_F(WallpaperControllerTest, WallpaperBlurDuringLockScreenTransition) {
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
 
@@ -2460,7 +2361,7 @@
             wallpaper_view()->layer()->parent()->children()[1]->type());
 }
 
-TEST_P(WallpaperControllerTest, LockDuringOverview) {
+TEST_F(WallpaperControllerTest, LockDuringOverview) {
   gfx::ImageSkia image = CreateImage(600, 400, kWallpaperColor);
   controller_->ShowWallpaperImage(
       image, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
@@ -2487,7 +2388,7 @@
   ASSERT_EQ(30, wallpaper_view->blur_sigma());
 }
 
-TEST_P(WallpaperControllerTest, DontLeakShieldView) {
+TEST_F(WallpaperControllerTest, DontLeakShieldView) {
   SetSessionState(SessionState::LOCKED);
   views::View* shield_view = wallpaper_view()->shield_view_for_testing();
   ASSERT_TRUE(shield_view);
@@ -2497,7 +2398,7 @@
   EXPECT_EQ(nullptr, view_tracker.view());
 }
 
-TEST_P(WallpaperControllerTest, OnlyShowDevicePolicyWallpaperOnLoginScreen) {
+TEST_F(WallpaperControllerTest, OnlyShowDevicePolicyWallpaperOnLoginScreen) {
   SetBypassDecode();
 
   // Verify the device policy wallpaper is shown on login screen.
@@ -2536,7 +2437,7 @@
   EXPECT_FALSE(IsDevicePolicyWallpaper());
 }
 
-TEST_P(WallpaperControllerTest, ShouldShowInitialAnimationAfterBoot) {
+TEST_F(WallpaperControllerTest, ShouldShowInitialAnimationAfterBoot) {
   CreateDefaultWallpapers();
 
   // Simulate the login screen after system boot.
@@ -2571,7 +2472,7 @@
   EXPECT_EQ(1, GetWallpaperCount());
 }
 
-TEST_P(WallpaperControllerTest, ShouldNotShowInitialAnimationAfterSignOut) {
+TEST_F(WallpaperControllerTest, ShouldNotShowInitialAnimationAfterSignOut) {
   CreateDefaultWallpapers();
 
   // Simulate the login screen after user sign-out. Verify that the slower
@@ -2603,7 +2504,7 @@
   EXPECT_EQ(1, GetWallpaperCount());
 }
 
-TEST_P(WallpaperControllerTest, ClosePreviewWallpaperOnOverviewStart) {
+TEST_F(WallpaperControllerTest, ClosePreviewWallpaperOnOverviewStart) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -2654,7 +2555,7 @@
   EXPECT_EQ(1u, client_.close_preview_count());
 }
 
-TEST_P(WallpaperControllerTest, ClosePreviewWallpaperOnWindowCycleStart) {
+TEST_F(WallpaperControllerTest, ClosePreviewWallpaperOnWindowCycleStart) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -2705,7 +2606,7 @@
   EXPECT_EQ(1u, client_.close_preview_count());
 }
 
-TEST_P(WallpaperControllerTest,
+TEST_F(WallpaperControllerTest,
        ClosePreviewWallpaperOnActiveUserSessionChanged) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
@@ -2758,7 +2659,7 @@
   EXPECT_EQ(1u, client_.close_preview_count());
 }
 
-TEST_P(WallpaperControllerTest, ConfirmPreviewWallpaper) {
+TEST_F(WallpaperControllerTest, ConfirmPreviewWallpaper) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -2875,7 +2776,7 @@
   EXPECT_EQ(user_wallpaper_info, online_wallpaper_info);
 }
 
-TEST_P(WallpaperControllerTest, CancelPreviewWallpaper) {
+TEST_F(WallpaperControllerTest, CancelPreviewWallpaper) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -2954,7 +2855,7 @@
   EXPECT_EQ(user_wallpaper_info, default_wallpaper_info);
 }
 
-TEST_P(WallpaperControllerTest, WallpaperSyncedDuringPreview) {
+TEST_F(WallpaperControllerTest, WallpaperSyncedDuringPreview) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -3089,7 +2990,7 @@
   EXPECT_EQ(user_wallpaper_info, synced_online_wallpaper_info);
 }
 
-TEST_P(WallpaperControllerTest, AddFirstWallpaperAnimationEndCallback) {
+TEST_F(WallpaperControllerTest, AddFirstWallpaperAnimationEndCallback) {
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
   std::unique_ptr<aura::Window> test_window(
@@ -3125,7 +3026,7 @@
   EXPECT_TRUE(is_third_callback_run);
 }
 
-TEST_P(WallpaperControllerTest, ShowOneShotWallpaper) {
+TEST_F(WallpaperControllerTest, ShowOneShotWallpaper) {
   gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
   WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
 
@@ -3181,7 +3082,7 @@
   EXPECT_EQ(WallpaperType::kCustomized, controller_->GetWallpaperType());
 }
 
-TEST_P(WallpaperControllerTest, OnFirstWallpaperShown) {
+TEST_F(WallpaperControllerTest, OnFirstWallpaperShown) {
   TestWallpaperControllerObserver observer(controller_);
   EXPECT_EQ(0, GetWallpaperCount());
   EXPECT_EQ(0, observer.first_shown_count());
@@ -3207,7 +3108,7 @@
 
 // Although ephemeral users' custom wallpapers are not saved to disk, they
 // should be kept within the user session. Test for https://crbug.com/825237.
-TEST_P(WallpaperControllerTest, ShowWallpaperForEphemeralUser) {
+TEST_F(WallpaperControllerTest, ShowWallpaperForEphemeralUser) {
   // Add an ephemeral user session and simulate login, like SimulateUserLogin.
   UserSession session;
   session.session_id = 0;
@@ -3253,7 +3154,7 @@
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
 }
 
-TEST_P(WallpaperControllerTest, AlwaysOnTopWallpaper) {
+TEST_F(WallpaperControllerTest, AlwaysOnTopWallpaper) {
   CreateDefaultWallpapers();
   SetBypassDecode();
 
@@ -3307,8 +3208,7 @@
 
 namespace {
 
-class WallpaperControllerPrefTest : public AshTestBase,
-                                    public testing::WithParamInterface<bool> {
+class WallpaperControllerPrefTest : public AshTestBase {
  public:
   WallpaperControllerPrefTest() {
     base::Value property(base::Value::Type::DICTIONARY);
@@ -3323,19 +3223,7 @@
 
   ~WallpaperControllerPrefTest() override = default;
 
-  void SetUp() override {
-    if (GetParam()) {
-      scoped_feature_list_.InitWithFeatures(
-          {ash::features::kWallpaperWebUI,
-           ash::features::kWallpaperFullScreenPreview},
-          {});
-    } else {
-      scoped_feature_list_.InitWithFeatures(
-          {}, {ash::features::kWallpaperWebUI,
-               ash::features::kWallpaperFullScreenPreview});
-    }
-    AshTestBase::SetUp();
-  }
+  void SetUp() override { AshTestBase::SetUp(); }
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -3343,11 +3231,9 @@
 
 }  // namespace
 
-INSTANTIATE_TEST_SUITE_P(All, WallpaperControllerPrefTest, testing::Bool());
-
 // Make sure that the display and the wallpaper view are rotated correctly at
 // startup.
-TEST_P(WallpaperControllerPrefTest, InitWithPrefs) {
+TEST_F(WallpaperControllerPrefTest, InitWithPrefs) {
   auto* wallpaper_view = Shell::GetPrimaryRootWindowController()
                              ->wallpaper_widget_controller()
                              ->wallpaper_view();
@@ -3360,7 +3246,7 @@
   EXPECT_EQ(root_window->bounds().size(), wallpaper_view->bounds().size());
 }
 
-TEST_P(WallpaperControllerTest, NoAnimationForNewRootWindowWhenLocked) {
+TEST_F(WallpaperControllerTest, NoAnimationForNewRootWindowWhenLocked) {
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
   SetSessionState(SessionState::LOCKED);
@@ -3376,7 +3262,7 @@
                    ->is_animating());
 }
 
-TEST_P(WallpaperControllerTest, GetWallpaperInfo) {
+TEST_F(WallpaperControllerTest, GetWallpaperInfo) {
   WallpaperInfo expected_info = InfoWithType(WallpaperType::kDaily);
   controller_->SetUserWallpaperInfo(account_id_1, expected_info);
 
@@ -3385,12 +3271,12 @@
   EXPECT_EQ(expected_info, actual_info);
 }
 
-TEST_P(WallpaperControllerTest, GetWallpaperInfoNothingToGet) {
+TEST_F(WallpaperControllerTest, GetWallpaperInfoNothingToGet) {
   WallpaperInfo info;
   EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &info));
 }
 
-TEST_P(WallpaperControllerTest, SetWallpaperInfoLocal) {
+TEST_F(WallpaperControllerTest, SetWallpaperInfoLocal) {
   WallpaperInfo info(
       GetDummyFileName(account_id_1), WALLPAPER_LAYOUT_CENTER_CROPPED,
       WallpaperType::kThirdParty, base::Time::Now().LocalMidnight());
@@ -3399,7 +3285,7 @@
                              account_id_1, info);
 }
 
-TEST_P(WallpaperControllerTest, SetWallpaperInfoLocalFromGooglePhotos) {
+TEST_F(WallpaperControllerTest, SetWallpaperInfoLocalFromGooglePhotos) {
   WallpaperInfo info(
       GooglePhotosWallpaperParams{account_id_1, kFakeGooglePhotosPhotoId,
                                   /*daily_refresh_enabled=*/false,
@@ -3410,37 +3296,7 @@
                              account_id_1, info);
 }
 
-// Test cases that only run with |kWallpaperWebUI| turned on.
-class WallpaperControllerWallpaperWebUiTest
-    : public WallpaperControllerTestBase {
- public:
-  WallpaperControllerWallpaperWebUiTest() = default;
-
-  WallpaperControllerWallpaperWebUiTest(
-      const WallpaperControllerWallpaperWebUiTest&) = delete;
-  WallpaperControllerWallpaperWebUiTest& operator=(
-      const WallpaperControllerWallpaperWebUiTest&) = delete;
-
-  ~WallpaperControllerWallpaperWebUiTest() override = default;
-
-  void SetUp() override {
-    scoped_feature_list_.InitWithFeatures(
-        {features::kWallpaperWebUI, features::kWallpaperFullScreenPreview,
-         features::kWallpaperGooglePhotosIntegration,
-         chromeos::features::kDarkLightMode},
-        {});
-    WallpaperControllerTestBase::SetUp();
-  }
-
-  base::test::ScopedFeatureList& scoped_feature_list() {
-    return scoped_feature_list_;
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_F(WallpaperControllerWallpaperWebUiTest, SetCustomWallpaper) {
+TEST_F(WallpaperControllerTest, SetCustomWallpaper) {
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
 
@@ -3487,31 +3343,21 @@
   EXPECT_EQ(custom_wallpaper_color, GetWallpaperColor());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, SetWallpaperInfoSynced) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerTest, SetWallpaperInfoSynced) {
   WallpaperInfo info = InfoWithType(WallpaperType::kOnline);
   EXPECT_TRUE(controller_->SetUserWallpaperInfo(account_id_1, info));
   AssertWallpaperInfoInPrefs(GetProfilePrefService(account_id_1),
                              prefs::kSyncableWallpaperInfo, account_id_1, info);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       SetWallpaperInfoSyncedFromGooglePhotos) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerTest, SetWallpaperInfoSyncedFromGooglePhotos) {
   WallpaperInfo info = InfoWithType(WallpaperType::kOnceGooglePhotos);
   EXPECT_TRUE(controller_->SetUserWallpaperInfo(account_id_1, info));
   AssertWallpaperInfoInPrefs(GetProfilePrefService(account_id_1),
                              prefs::kSyncableWallpaperInfo, account_id_1, info);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, SetWallpaperInfoSyncDisabled) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerTest, SetWallpaperInfoSyncDisabled) {
   client_.set_wallpaper_sync_enabled(false);
 
   WallpaperInfo expected_info = InfoWithType(WallpaperType::kCustomized);
@@ -3527,7 +3373,7 @@
                              expected_info);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, SetWallpaperInfoCustom) {
+TEST_F(WallpaperControllerTest, SetWallpaperInfoCustom) {
   WallpaperInfo synced_info = InfoWithType(WallpaperType::kOnline);
   PutWallpaperInfoInPrefs(account_id_1, synced_info,
                           GetProfilePrefService(account_id_1),
@@ -3544,7 +3390,7 @@
                              synced_info);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, OldOnlineInfoSynced_Discarded) {
+TEST_F(WallpaperControllerTest, OldOnlineInfoSynced_Discarded) {
   // Create a dictionary that looks like the preference from crrev.com/a040384.
   // DO NOT CHANGE as there are preferences like this in production.
   base::Value wallpaper_info_dict(base::Value::Type::DICTIONARY);
@@ -3575,7 +3421,7 @@
   EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &actual));
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, MigrateWallpaperInfo) {
+TEST_F(WallpaperControllerTest, MigrateWallpaperInfo) {
   WallpaperInfo expected_info = InfoWithType(WallpaperType::kOnline);
   PutWallpaperInfoInPrefs(account_id_1, expected_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -3585,7 +3431,7 @@
                              expected_info);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, MigrateWallpaperInfoCustomized) {
+TEST_F(WallpaperControllerTest, MigrateWallpaperInfoCustomized) {
   WallpaperInfo expected_info = InfoWithType(WallpaperType::kCustomized);
   PutWallpaperInfoInPrefs(account_id_1, expected_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -3595,7 +3441,7 @@
                              expected_info);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, MigrateWallpaperInfoDaily) {
+TEST_F(WallpaperControllerTest, MigrateWallpaperInfoDaily) {
   WallpaperInfo expected_info = WallpaperInfo(OnlineWallpaperParams(
       account_id_1, kAssetId, GURL(kDummyUrl),
       TestWallpaperControllerClient::kDummyCollectionId,
@@ -3611,7 +3457,7 @@
   EXPECT_EQ(client_.migrate_collection_id_from_chrome_app_count(), 1u);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        MigrateWallpaperInfoDoesntHappenWhenSyncedInfoAlreadyExists) {
   SetBypassDecode();
 
@@ -3638,7 +3484,7 @@
                              synced_info);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        ActiveUserPrefServiceChangedSyncedInfoHandledLocally) {
   CacheOnlineWallpaper(kDummyUrl);
 
@@ -3665,8 +3511,7 @@
   EXPECT_EQ(WallpaperType::kOnline, actual_info.type);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       ActiveUserPrefServiceChanged_SyncDisabled) {
+TEST_F(WallpaperControllerTest, ActiveUserPrefServiceChanged_SyncDisabled) {
   CacheOnlineWallpaper(kDummyUrl);
   WallpaperInfo synced_info = {kDummyUrl, WALLPAPER_LAYOUT_CENTER_CROPPED,
                                WallpaperType::kOnline, base::Time::Now()};
@@ -3692,8 +3537,7 @@
   EXPECT_EQ(WallpaperType::kThirdParty, actual_info.type);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       HandleWallpaperInfoSyncedLocalIsPolicy) {
+TEST_F(WallpaperControllerTest, HandleWallpaperInfoSyncedLocalIsPolicy) {
   CacheOnlineWallpaper(kDummyUrl);
   PutWallpaperInfoInPrefs(account_id_1, InfoWithType(WallpaperType::kPolicy),
                           GetLocalPrefService(), prefs::kUserWallpaperInfo);
@@ -3711,7 +3555,7 @@
   EXPECT_NE(WallpaperType::kOnline, actual_info.type);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        HandleWallpaperInfoSyncedLocalIsThirdPartyAndOlder) {
   CacheOnlineWallpaper(kDummyUrl);
 
@@ -3735,7 +3579,7 @@
   EXPECT_EQ(WallpaperType::kOnline, actual_info.type);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        HandleWallpaperInfoSyncedLocalIsThirdPartyAndNewer) {
   CacheOnlineWallpaper(kDummyUrl);
   PutWallpaperInfoInPrefs(account_id_1,
@@ -3758,7 +3602,7 @@
   EXPECT_EQ(WallpaperType::kThirdParty, actual_info.type);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, HandleWallpaperInfoSyncedOnline) {
+TEST_F(WallpaperControllerTest, HandleWallpaperInfoSyncedOnline) {
   CacheOnlineWallpaper(kDummyUrl);
 
   // Attempt to set an online wallpaper without providing the image data. Verify
@@ -3779,8 +3623,7 @@
   EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       HandleWallpaperInfoSyncedInactiveUser) {
+TEST_F(WallpaperControllerTest, HandleWallpaperInfoSyncedInactiveUser) {
   CacheOnlineWallpaper(kDummyUrl);
 
   // Make account_id_1 the inactive user.
@@ -3798,7 +3641,7 @@
   EXPECT_NE(controller_->GetWallpaperType(), WallpaperType::kOnline);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, UpdateDailyRefreshWallpaper) {
+TEST_F(WallpaperControllerTest, UpdateDailyRefreshWallpaper) {
   std::string expected{"fun_collection"};
   SimulateUserLogin(account_id_1);
 
@@ -3813,7 +3656,7 @@
 }
 
 // Disabled due to flakes; see crbug/1320991.
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        DISABLED_UpdateDailyRefreshWallpaperCalledOnLogin) {
   SimulateUserLogin(account_id_1);
 
@@ -3838,8 +3681,7 @@
             client_.get_fetch_daily_refresh_wallpaper_param());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       UpdateDailyRefreshWallpaper_NotEnabled) {
+TEST_F(WallpaperControllerTest, UpdateDailyRefreshWallpaper_NotEnabled) {
   SimulateUserLogin(account_id_1);
   WallpaperInfo info = {std::string(), WALLPAPER_LAYOUT_CENTER,
                         WallpaperType::kOnline, DayBeforeYesterdayish()};
@@ -3850,8 +3692,7 @@
   EXPECT_EQ(std::string(), client_.get_fetch_daily_refresh_wallpaper_param());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       UpdateDailyRefreshWallpaper_NoCollectionId) {
+TEST_F(WallpaperControllerTest, UpdateDailyRefreshWallpaper_NoCollectionId) {
   SimulateUserLogin(account_id_1);
   controller_->SetUserWallpaperInfo(
       account_id_1,
@@ -3862,7 +3703,7 @@
   EXPECT_EQ(std::string(), client_.get_fetch_daily_refresh_wallpaper_param());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        UpdateDailyRefreshWallpaper_TimerStartsOnPrefServiceChange) {
   using base::Time;
 
@@ -3887,7 +3728,7 @@
   ASSERT_LE(delta, update_time + base::Hours(1) + base::Minutes(1));
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        UpdateDailyRefreshWallpaper_RetryTimerTriggersOnFailedFetchInfo) {
   using base::Time;
 
@@ -3911,7 +3752,7 @@
   ASSERT_LE(delay, one_hour + base::Minutes(1));
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        UpdateDailyRefreshWallpaper_RetryTimerTriggersOnFailedFetchData) {
   using base::Time;
 
@@ -3938,9 +3779,7 @@
   ASSERT_LE(delay, one_hour + base::Minutes(1));
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, MigrateCustomWallpaper) {
-  scoped_feature_list().Reset();
-  scoped_feature_list().InitWithFeatures({}, {features::kWallpaperWebUI});
+TEST_F(WallpaperControllerTest, MigrateCustomWallpaper) {
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
 
@@ -3951,14 +3790,11 @@
   RunAllTasksUntilIdle();
   ClearLogin();
 
-  scoped_feature_list().Reset();
-  scoped_feature_list().InitWithFeatures({features::kWallpaperWebUI}, {});
-
   SimulateUserLogin(account_id_1);
   EXPECT_EQ(account_id_1, client_.get_save_wallpaper_to_drive_fs_account_id());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, OnGoogleDriveMounted) {
+TEST_F(WallpaperControllerTest, OnGoogleDriveMounted) {
   WallpaperInfo local_info = InfoWithType(WallpaperType::kCustomized);
   PutWallpaperInfoInPrefs(account_id_1, local_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -3968,8 +3804,7 @@
   EXPECT_EQ(account_id_1, client_.get_save_wallpaper_to_drive_fs_account_id());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       OnGoogleDriveMounted_WallpaperIsntCustom) {
+TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_WallpaperIsntCustom) {
   WallpaperInfo local_info = InfoWithType(WallpaperType::kOnline);
   PutWallpaperInfoInPrefs(account_id_1, local_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -3978,8 +3813,7 @@
   EXPECT_TRUE(client_.get_save_wallpaper_to_drive_fs_account_id().empty());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       OnGoogleDriveMounted_AlreadySynced) {
+TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_AlreadySynced) {
   WallpaperInfo local_info = InfoWithType(WallpaperType::kCustomized);
   PutWallpaperInfoInPrefs(account_id_1, local_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -4000,8 +3834,7 @@
   EXPECT_FALSE(client_.get_save_wallpaper_to_drive_fs_account_id().is_valid());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       OnGoogleDriveMounted_OldLocalInfo) {
+TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_OldLocalInfo) {
   WallpaperInfo local_info =
       WallpaperInfo("a_url", WALLPAPER_LAYOUT_CENTER_CROPPED,
                     WallpaperType::kCustomized, DayBeforeYesterdayish());
@@ -4024,8 +3857,7 @@
             account_id_1);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       OnGoogleDriveMounted_NewLocalInfo) {
+TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_NewLocalInfo) {
   WallpaperInfo local_info = WallpaperInfo(
       "a_url", WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kCustomized,
       base::Time::Now().LocalMidnight());
@@ -4045,7 +3877,7 @@
   EXPECT_EQ(account_id_1, client_.get_save_wallpaper_to_drive_fs_account_id());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, SetDailyRefreshCollectionId) {
+TEST_F(WallpaperControllerTest, SetDailyRefreshCollectionId) {
   controller_->SetUserWallpaperInfo(
       account_id_1,
       WallpaperInfo(std::string(), WALLPAPER_LAYOUT_CENTER,
@@ -4066,8 +3898,7 @@
             controller_->GetDailyRefreshCollectionId(account_id_1));
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       SetDailyRefreshCollectionId_Empty) {
+TEST_F(WallpaperControllerTest, SetDailyRefreshCollectionId_Empty) {
   std::string collection_id = "fun_collection";
   WallpaperInfo info = {std::string(), WALLPAPER_LAYOUT_CENTER,
                         WallpaperType::kDaily, DayBeforeYesterdayish()};
@@ -4090,7 +3921,7 @@
 
 // WallpaperType should not change with an empty collection id if the previous
 // WallpaperType isn't |WallpaperType::kDaily|.
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        SetDailyRefreshCollectionId_Empty_NotTypeDaily) {
   controller_->SetUserWallpaperInfo(
       account_id_1,
@@ -4109,8 +3940,7 @@
             controller_->GetDailyRefreshCollectionId(account_id_1));
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
-       UpdateWallpaperOnColorModeChanged) {
+TEST_F(WallpaperControllerTest, UpdateWallpaperOnColorModeChanged) {
   SimulateUserLogin(account_id_1);
 
   auto run_loop = std::make_unique<base::RunLoop>();
@@ -4153,7 +3983,7 @@
   EXPECT_EQ(expected, actual);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        UpdateWallpaperWithMissingVariantsOnColorModeChanged) {
   SimulateUserLogin(account_id_1);
 
@@ -4199,7 +4029,7 @@
   EXPECT_EQ(expected, actual);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        UpdateWallpaperInfoWithOnlineWallpaperVariants) {
   SimulateUserLogin(account_id_1);
 
@@ -4223,7 +4053,7 @@
   EXPECT_EQ(expected, actual);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest, SetOnlineWallpaperIfExists) {
+TEST_F(WallpaperControllerTest, SetOnlineWallpaperIfExists) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER_CROPPED;
@@ -4296,7 +4126,7 @@
   EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        HandleWallpaperInfoSyncedForDarkLightWallpapers_NotSynced) {
   SimulateUserLogin(account_id_1);
   CacheOnlineWallpaper(kDummyUrl);
@@ -4338,7 +4168,7 @@
   EXPECT_EQ(1, GetWallpaperCount());
 }
 
-TEST_F(WallpaperControllerWallpaperWebUiTest,
+TEST_F(WallpaperControllerTest,
        HandleWallpaperInfoSyncedForDarkLightWallpapers_AlreadySynced) {
   SimulateUserLogin(account_id_1);
   CacheOnlineWallpaper(kDummyUrl);
@@ -4382,19 +4212,16 @@
 }
 
 class WallpaperControllerGooglePhotosWallpaperTest
-    : public WallpaperControllerTestBase,
+    : public WallpaperControllerTest,
       public testing::WithParamInterface<bool> {
  public:
   WallpaperControllerGooglePhotosWallpaperTest() {
     if (GooglePhotosEnabled()) {
       scoped_feature_list_.InitWithFeatures(
-          {ash::features::kWallpaperWebUI,
-           ash::features::kWallpaperGooglePhotosIntegration},
-          {});
+          {ash::features::kWallpaperGooglePhotosIntegration}, {});
     } else {
       scoped_feature_list_.InitWithFeatures(
-          {}, {ash::features::kWallpaperWebUI,
-               ash::features::kWallpaperGooglePhotosIntegration});
+          {}, {ash::features::kWallpaperGooglePhotosIntegration});
     }
   }
 
diff --git a/ash/webui/DEPS b/ash/webui/DEPS
index 92944149..71abd90 100644
--- a/ash/webui/DEPS
+++ b/ash/webui/DEPS
@@ -1,10 +1,14 @@
 include_rules = [
   # Code in //ash sits below chrome in the dependency graph.
   "-chrome",
+
   # Code in //ash runs in the browser process.
   "+content/public/browser",
   "+content/public/common",
   "+content/public/test",
+
+  "+chromeos/ash/services/cros_healthd/public/cpp",
+  "+chromeos/ash/services/cros_healthd/public/mojom",
   "+mojo/core/embedder",
   "+ui/webui",
 ]
diff --git a/ash/webui/diagnostics_ui/DEPS b/ash/webui/diagnostics_ui/DEPS
index 020be15b..78afd32 100644
--- a/ash/webui/diagnostics_ui/DEPS
+++ b/ash/webui/diagnostics_ui/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+chromeos/login/login_state",
+  "+chromeos/services/network_config",
   "+chromeos/strings/grit/chromeos_strings.h",
   "+components",
   "+ui/base",
@@ -10,11 +11,6 @@
   "+ui/shell_dialogs",
   "+ui/web_dialogs",
 
-  # TODO(https://crbug.com/1164001): Remove when migrated to ash.
-  "+chromeos/services/cros_healthd/public/cpp",
-  "+chromeos/services/cros_healthd/public/mojom",
-  "+chromeos/services/network_config",
-
   # SFUL Metrics DEPS
   "+chromeos/components/feature_usage",
 ]
diff --git a/ash/webui/diagnostics_ui/backend/BUILD.gn b/ash/webui/diagnostics_ui/backend/BUILD.gn
index 2d1ffda..2eb8b3b 100644
--- a/ash/webui/diagnostics_ui/backend/BUILD.gn
+++ b/ash/webui/diagnostics_ui/backend/BUILD.gn
@@ -42,10 +42,10 @@
     "//ash/public/cpp",
     "//ash/webui/diagnostics_ui/mojom",
     "//base",
+    "//chromeos/ash/services/cros_healthd/public/cpp",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//chromeos/dbus/power",
     "//chromeos/dbus/power:power_manager_proto",
-    "//chromeos/services/cros_healthd/public/cpp",
-    "//chromeos/services/cros_healthd/public/mojom",
     "//chromeos/services/network_config:in_process_instance",
     "//chromeos/services/network_config/public/cpp",
     "//chromeos/services/network_health/public/mojom",
@@ -92,13 +92,13 @@
     "//ash/webui/diagnostics_ui/mojom",
     "//base",
     "//base/test:test_support",
+    "//chromeos/ash/services/cros_healthd/public/cpp",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/power",
     "//chromeos/dbus/power:power_manager_proto",
     "//chromeos/dbus/shill",
     "//chromeos/login/login_state:login_state",
-    "//chromeos/services/cros_healthd/public/cpp",
-    "//chromeos/services/cros_healthd/public/mojom",
     "//chromeos/services/network_config:in_process_instance",
     "//chromeos/services/network_config:network_config",
     "//chromeos/services/network_config/public/cpp:test_support",
diff --git a/ash/webui/diagnostics_ui/backend/cros_healthd_helpers.cc b/ash/webui/diagnostics_ui/backend/cros_healthd_helpers.cc
index 081cf97..8386b5d 100644
--- a/ash/webui/diagnostics_ui/backend/cros_healthd_helpers.cc
+++ b/ash/webui/diagnostics_ui/backend/cros_healthd_helpers.cc
@@ -6,8 +6,8 @@
 
 #include "base/logging.h"
 #include "base/strings/string_piece.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 
 namespace ash {
 namespace diagnostics {
diff --git a/ash/webui/diagnostics_ui/backend/cros_healthd_helpers.h b/ash/webui/diagnostics_ui/backend/cros_healthd_helpers.h
index 01f75c8..cfe845fc 100644
--- a/ash/webui/diagnostics_ui/backend/cros_healthd_helpers.h
+++ b/ash/webui/diagnostics_ui/backend/cros_healthd_helpers.h
@@ -5,8 +5,8 @@
 #ifndef ASH_WEBUI_DIAGNOSTICS_UI_BACKEND_CROS_HEALTHD_HELPERS_H_
 #define ASH_WEBUI_DIAGNOSTICS_UI_BACKEND_CROS_HEALTHD_HELPERS_H_
 
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom-forward.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-forward.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom-forward.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-forward.h"
 
 namespace ash {
 namespace diagnostics {
diff --git a/ash/webui/diagnostics_ui/backend/network_health_provider.h b/ash/webui/diagnostics_ui/backend/network_health_provider.h
index c780293..f5ae02c4 100644
--- a/ash/webui/diagnostics_ui/backend/network_health_provider.h
+++ b/ash/webui/diagnostics_ui/backend/network_health_provider.h
@@ -12,7 +12,7 @@
 #include "ash/webui/diagnostics_ui/mojom/network_health_provider.mojom.h"
 #include "base/containers/flat_map.h"
 #include "base/guid.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -35,7 +35,7 @@
 };
 
 class NetworkHealthProvider
-    : public chromeos::network_config::mojom::CrosNetworkConfigObserver,
+    : public chromeos::network_config::CrosNetworkConfigObserver,
       public mojom::NetworkHealthProvider {
  public:
   NetworkHealthProvider();
@@ -57,7 +57,6 @@
       mojo::PendingReceiver<mojom::NetworkHealthProvider> pending_receiver);
 
   // CrosNetworkConfigObserver
-  void OnNetworkStateListChanged() override {}
   void OnDeviceStateListChanged() override;
   void OnActiveNetworksChanged(
       std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
@@ -65,9 +64,6 @@
   void OnNetworkStateChanged(
       chromeos::network_config::mojom::NetworkStatePropertiesPtr network_state)
       override;
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
   // Returns the list of observer guids. Each guid corresponds to one network
   // interface. Additionally, updates the currently |active_guid_| to the first
diff --git a/ash/webui/diagnostics_ui/backend/network_health_provider_unittest.cc b/ash/webui/diagnostics_ui/backend/network_health_provider_unittest.cc
index 80a100a3..c91c8e1a5 100644
--- a/ash/webui/diagnostics_ui/backend/network_health_provider_unittest.cc
+++ b/ash/webui/diagnostics_ui/backend/network_health_provider_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/onc/network_onc_utils.h"
 #include "chromeos/dbus/shill/shill_ipconfig_client.h"
 #include "chromeos/login/login_state/login_state.h"
@@ -19,7 +20,6 @@
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_device_handler.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_type_pattern.h"
 #include "chromeos/network/system_token_cert_db_storage.h"
diff --git a/ash/webui/diagnostics_ui/backend/routine_properties.h b/ash/webui/diagnostics_ui/backend/routine_properties.h
index 7097a6a..7f438be 100644
--- a/ash/webui/diagnostics_ui/backend/routine_properties.h
+++ b/ash/webui/diagnostics_ui/backend/routine_properties.h
@@ -10,7 +10,7 @@
 #include <string>
 
 #include "ash/webui/diagnostics_ui/mojom/system_routine_controller.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 
 namespace ash {
 namespace diagnostics {
diff --git a/ash/webui/diagnostics_ui/backend/system_data_provider.cc b/ash/webui/diagnostics_ui/backend/system_data_provider.cc
index fd35c48..b7f23f6 100644
--- a/ash/webui/diagnostics_ui/backend/system_data_provider.cc
+++ b/ash/webui/diagnostics_ui/backend/system_data_provider.cc
@@ -16,9 +16,9 @@
 #include "base/i18n/time_formatting.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
diff --git a/ash/webui/diagnostics_ui/backend/system_data_provider.h b/ash/webui/diagnostics_ui/backend/system_data_provider.h
index bd82741..4586d78 100644
--- a/ash/webui/diagnostics_ui/backend/system_data_provider.h
+++ b/ash/webui/diagnostics_ui/backend/system_data_provider.h
@@ -10,8 +10,8 @@
 #include "ash/webui/diagnostics_ui/backend/cpu_usage_data.h"
 #include "ash/webui/diagnostics_ui/mojom/system_data_provider.mojom.h"
 #include "base/memory/weak_ptr.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/ash/webui/diagnostics_ui/backend/system_data_provider_unittest.cc b/ash/webui/diagnostics_ui/backend/system_data_provider_unittest.cc
index 298c6881..1f783be 100644
--- a/ash/webui/diagnostics_ui/backend/system_data_provider_unittest.cc
+++ b/ash/webui/diagnostics_ui/backend/system_data_provider_unittest.cc
@@ -21,11 +21,11 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "base/timer/mock_timer.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
diff --git a/ash/webui/diagnostics_ui/backend/system_routine_controller.cc b/ash/webui/diagnostics_ui/backend/system_routine_controller.cc
index 1fe7f7f..52ac2d8 100644
--- a/ash/webui/diagnostics_ui/backend/system_routine_controller.cc
+++ b/ash/webui/diagnostics_ui/backend/system_routine_controller.cc
@@ -19,9 +19,9 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "base/values.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/nullable_primitives.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/nullable_primitives.mojom.h"
 #include "content/public/browser/device_service.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/ash/webui/diagnostics_ui/backend/system_routine_controller.h b/ash/webui/diagnostics_ui/backend/system_routine_controller.h
index 66c408d..829c2b6 100644
--- a/ash/webui/diagnostics_ui/backend/system_routine_controller.h
+++ b/ash/webui/diagnostics_ui/backend/system_routine_controller.h
@@ -10,8 +10,8 @@
 #include "ash/webui/diagnostics_ui/mojom/system_routine_controller.mojom.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom-forward.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom-forward.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/ash/webui/diagnostics_ui/backend/system_routine_controller_unittest.cc b/ash/webui/diagnostics_ui/backend/system_routine_controller_unittest.cc
index cae4858..d9b8d00 100644
--- a/ash/webui/diagnostics_ui/backend/system_routine_controller_unittest.cc
+++ b/ash/webui/diagnostics_ui/backend/system_routine_controller_unittest.cc
@@ -16,9 +16,9 @@
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
 #include "services/device/public/cpp/test/test_wake_lock_provider.h"
diff --git a/ash/webui/eche_app_ui/BUILD.gn b/ash/webui/eche_app_ui/BUILD.gn
index 36e32377..48e729b9 100644
--- a/ash/webui/eche_app_ui/BUILD.gn
+++ b/ash/webui/eche_app_ui/BUILD.gn
@@ -98,6 +98,7 @@
     "//ash/webui/eche_app_ui/proto",
     "//ash/webui/resources:eche_app_resources",
     "//ash/webui/resources:eche_bundle_resources",
+    "//chromeos/services/network_config/public/cpp",
     "//components/prefs",
     "//content/public/browser",
     "//mojo/public/js:resources",
diff --git a/ash/webui/eche_app_ui/system_info_provider.h b/ash/webui/eche_app_ui/system_info_provider.h
index a183500..dad6e0a9 100644
--- a/ash/webui/eche_app_ui/system_info_provider.h
+++ b/ash/webui/eche_app_ui/system_info_provider.h
@@ -8,7 +8,7 @@
 #include "ash/public/cpp/screen_backlight_observer.h"
 #include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/webui/eche_app_ui/mojom/eche_app.mojom.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -31,7 +31,7 @@
     : public mojom::SystemInfoProvider,
       public ScreenBacklightObserver,
       public TabletModeObserver,
-      public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+      public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   explicit SystemInfoProvider(
       std::unique_ptr<SystemInfo> system_info,
@@ -61,18 +61,10 @@
 
   void SetTabletModeChanged(bool enabled);
 
-  // network_config::mojom::CrosNetworkConfigObserver overrides:
-  void OnActiveNetworksChanged(
-      std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
-          networks) override {}
-  void OnDeviceStateListChanged() override {}
+  // network_config::CrosNetworkConfigObserver overrides:
   void OnNetworkStateChanged(
       chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
       override;
-  void OnNetworkStateListChanged() override {}
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
   void FetchWifiNetworkList();
   void OnWifiNetworkList(
diff --git a/ash/webui/os_feedback_ui/os_feedback_ui.cc b/ash/webui/os_feedback_ui/os_feedback_ui.cc
index 3b56ee9..8cdd54a 100644
--- a/ash/webui/os_feedback_ui/os_feedback_ui.cc
+++ b/ash/webui/os_feedback_ui/os_feedback_ui.cc
@@ -64,11 +64,19 @@
       {"confirmationTitleOnline", IDS_FEEDBACK_TOOL_PAGE_TITLE_AFTER_SENT},
       {"exploreAppDescription",
        IDS_FEEDBACK_TOOL_RESOURCES_EXPLORE_APP_DESCRIPTION},
+      {"exploreAppLabel", IDS_FEEDBACK_TOOL_RESOURCES_EXPLORE_APP_LABEL},
       {"diagnosticsAppLabel",
        IDS_FEEDBACK_TOOL_RESOURCES_DIAGNOSTICS_APP_LABEL},
+      {"diagnosticsAppDescription",
+       IDS_FEEDBACK_TOOL_RESOURCES_DIAGNOSTICS_APP_DESCRIPTION},
+      {"askCommunityLabel", IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_LABEL},
+      {"askCommunityDescription",
+       IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_DESCRIPTION},
       {"userConsentLabel", IDS_FEEDBACK_TOOL_USER_CONSENT_LABEL},
       {"includeSystemInfoAndMetricsCheckboxLabel",
        IDS_FEEDBACK_TOOL_INCLUDE_SYSTEM_INFO_AND_METRICS_CHECKBOX_LABEL},
+      {"anonymousUser", IDS_FEEDBACK_TOOL_ANONYMOUS_EMAIL_OPTION},
+      {"thankYouNoteOffline", IDS_FEEDBACK_TOOL_THANK_YOU_NOTE_OFFLINE},
   };
 
   source->AddLocalizedStrings(kLocalizedStrings);
diff --git a/ash/webui/os_feedback_ui/resources/confirmation_page.html b/ash/webui/os_feedback_ui/resources/confirmation_page.html
index 644a388f..069bd15 100644
--- a/ash/webui/os_feedback_ui/resources/confirmation_page.html
+++ b/ash/webui/os_feedback_ui/resources/confirmation_page.html
@@ -29,19 +29,19 @@
     <div id="helpResources">
       <p id="helpResourcesLabel">Here are some other helpful resources:</p>
       <cr-link-row id="explore" start-icon="help-resources:explore"
-          label="Explore app" external
+          label="[[i18n('exploreAppLabel')]]" external
           sub-label="[[i18n('exploreAppDescription')]]"
           on-click="handleLinkClicked_">
       </cr-link-row>
       <cr-link-row id="diagnostics" start-icon="help-resources:diagnostics"
           label="[[i18n('diagnosticsAppLabel')]]" external
-          sub-label="Run tests and troubleshooting for hardware issues"
+          sub-label="[[i18n('diagnosticsAppDescription')]]"
           on-click="handleLinkClicked_">
       </cr-link-row>
       <cr-link-row id="chromebookCommunity"
           start-icon="help-resources2:chromebook-community"
-          label="Chromebook community"
-          sub-label="Ask the experts in the Chromebook help forum"
+          label="[[i18n('askCommunityLabel')]]"
+          sub-label="[[i18n('askCommunityDescription')]]"
           hidden="[[isOffline_(sendReportStatus)]]" external
           on-click="handleLinkClicked_">
       </cr-link-row>
diff --git a/ash/webui/os_feedback_ui/resources/confirmation_page.js b/ash/webui/os_feedback_ui/resources/confirmation_page.js
index 25c7832..7104688 100644
--- a/ash/webui/os_feedback_ui/resources/confirmation_page.js
+++ b/ash/webui/os_feedback_ui/resources/confirmation_page.js
@@ -84,9 +84,7 @@
   getMessage_() {
     // TODO(xiangdongkong): Localize the strings.
     if (this.isOffline_()) {
-      return 'Thanks for the feedback. Your feedback helps improve Chrome OS ' +
-          'and will be reviewed by the Chrome OS team. Because of the number ' +
-          ' of reports submitted, you won’t receive a direct reply. ';
+      return this.i18n('thankYouNoteOffline');
     }
     return 'Your feedback helps improve ChromeOS and will be reviewed by ' +
         'our team. Because of the large number of reports, we won\’t be able ' +
diff --git a/ash/webui/os_feedback_ui/resources/help_content.html b/ash/webui/os_feedback_ui/resources/help_content.html
index 694c770..62ee9b40 100644
--- a/ash/webui/os_feedback_ui/resources/help_content.html
+++ b/ash/webui/os_feedback_ui/resources/help_content.html
@@ -1,4 +1,9 @@
 <style>
+  a[href] {
+    color: var(--cros-text-color-primary);
+    text-decoration: none;
+  }
+
   .help-item {
     display: flex;
     margin:  12px 0 0;
diff --git a/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html b/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html
index 74ea0da..664ddfa5 100644
--- a/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html
+++ b/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html
@@ -9,6 +9,10 @@
       background-color: var(--cros-bg-color);
     }
 
+    a[href] {
+      color: var(--cros-link-color);
+    }
+
     #container {
       display: flex;
       flex-direction: column;
diff --git a/ash/webui/os_feedback_ui/resources/share_data_page.html b/ash/webui/os_feedback_ui/resources/share_data_page.html
index 8786239f..f6c285a 100644
--- a/ash/webui/os_feedback_ui/resources/share_data_page.html
+++ b/ash/webui/os_feedback_ui/resources/share_data_page.html
@@ -1,4 +1,7 @@
 <style include="os-feedback-shared">
+  a[href] {
+    text-decoration: none;
+  }
 
   #privacyNote {
     font-size: 12px;
@@ -73,7 +76,7 @@
 </style>
 <div id="container">
   <div id="header">
-    <h1 class="page-title">Send feedback</h1>
+    <h1 class="page-title">[[i18n('pageTitle')]]</h1>
   </div>
   <div id="content">
     <!-- Attach files -->
@@ -101,7 +104,7 @@
       <h2 id="userEmailLabel">[[i18n('userEmailLabel')]]</h2>
       <select id="userEmailDropDown" aria-labelledby="userEmailLabel">
         <option value$="[[feedbackContext.email]]">[[feedbackContext.email]]</option>
-        <option value="">Don't include email address</option>
+        <option value="" id="anonymousUser">[[i18n('anonymousUser')]]</option>
       </select>
     </div>
     <!-- User consent -->
diff --git a/ash/webui/personalization_app/search/search_tag_registry.cc b/ash/webui/personalization_app/search/search_tag_registry.cc
index eb50e521..0763357 100644
--- a/ash/webui/personalization_app/search/search_tag_registry.cc
+++ b/ash/webui/personalization_app/search/search_tag_registry.cc
@@ -112,6 +112,7 @@
               IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT2,
               IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT3,
               IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT4,
+              IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT5,
           },
       .relative_url = kUserSubpageRelativeUrl,
   });
diff --git a/ash/webui/shimless_rma/backend/BUILD.gn b/ash/webui/shimless_rma/backend/BUILD.gn
index a729342..066fe666 100644
--- a/ash/webui/shimless_rma/backend/BUILD.gn
+++ b/ash/webui/shimless_rma/backend/BUILD.gn
@@ -48,11 +48,11 @@
     "//base/test:test_support",
     "//chromeos/ash/components/dbus/rmad",
     "//chromeos/ash/components/dbus/rmad:rmad_proto",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/update_engine:update_engine",
     "//chromeos/login/login_state:login_state",
     "//chromeos/network:network",
-    "//chromeos/network:test_support",
     "//chromeos/services/network_config/public/cpp:test_support",
     "//chromeos/services/network_config/public/mojom:mojom",
     "//chromeos/services/network_config/public/mojom:network_types_shared_cpp_sources",
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
index 938473a..b24992b4 100644
--- a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
+++ b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/test/task_environment.h"
 #include "chromeos/ash/components/dbus/rmad/fake_rmad_client.h"
 #include "chromeos/ash/components/dbus/rmad/rmad_client.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/update_engine/update_engine.pb.h"
 #include "chromeos/dbus/update_engine/update_engine_client.h"
@@ -26,7 +27,6 @@
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/network_type_pattern.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
diff --git a/ash/webui/shimless_rma/backend/version_updater_unittest.cc b/ash/webui/shimless_rma/backend/version_updater_unittest.cc
index ca23c26b..83a742da 100644
--- a/ash/webui/shimless_rma/backend/version_updater_unittest.cc
+++ b/ash/webui/shimless_rma/backend/version_updater_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/ash/components/network/onc/network_onc_utils.h"
 #include "chromeos/ash/components/network/proxy/ui_proxy_config_service.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -21,7 +22,6 @@
 #include "chromeos/network/network_device_handler.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_profile_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
 #include "chromeos/services/network_config/public/mojom/network_types.mojom-shared.h"
diff --git a/ash/webui/telemetry_extension_ui/DEPS b/ash/webui/telemetry_extension_ui/DEPS
index f396279..922b277 100644
--- a/ash/webui/telemetry_extension_ui/DEPS
+++ b/ash/webui/telemetry_extension_ui/DEPS
@@ -2,7 +2,5 @@
   # Do not add chrome here (use a delegate instead).
   "+chrome/browser/ash/wilco_dtc_supportd/mojo_utils.h",
 
-  # TODO(https://crbug.com/1164001): Remove when these moves to ash.
   "+chromeos/dbus",
-  "+chromeos/services/cros_healthd",
 ]
diff --git a/ash/webui/telemetry_extension_ui/mojom/diagnostics_service.mojom b/ash/webui/telemetry_extension_ui/mojom/diagnostics_service.mojom
index 5214fe4..ae37319 100644
--- a/ash/webui/telemetry_extension_ui/mojom/diagnostics_service.mojom
+++ b/ash/webui/telemetry_extension_ui/mojom/diagnostics_service.mojom
@@ -7,7 +7,7 @@
 
 // Note: This is a subset of the cros_healthd diagnostics service interface
 // which is located in
-// //chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.
+// //chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.
 // This interface serves as PII filtering and data post-processing service
 // between the source (cros_healthd) and the clients
 // (third-party telemetry extensions).
diff --git a/ash/webui/telemetry_extension_ui/mojom/probe_service.mojom b/ash/webui/telemetry_extension_ui/mojom/probe_service.mojom
index 1b4c3c6..86c3987 100644
--- a/ash/webui/telemetry_extension_ui/mojom/probe_service.mojom
+++ b/ash/webui/telemetry_extension_ui/mojom/probe_service.mojom
@@ -6,7 +6,8 @@
 // consumed by the Telemetry Extension APIs implementation.
 
 // Note: this is a subset of the cros_healthd probe service interface which is
-// located in //chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.
+// located in
+// //chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.
 // This interface serves as PII filtering and data post-processing service
 // between the source (cros_healthd) and the clients
 // (third-party telemetry extensions).
diff --git a/ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom b/ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom
index 83405fc..063f8c1 100644
--- a/ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom
+++ b/ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom
@@ -6,7 +6,8 @@
 // the Telemetry Extension APIs implementation but it is not currently used.
 
 // Note: this is a subset of the cros_healthd probe service interface which is
-// located in //chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.
+// located in
+// //chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.
 
 module ash.health.mojom;
 
diff --git a/ash/webui/telemetry_extension_ui/services/BUILD.gn b/ash/webui/telemetry_extension_ui/services/BUILD.gn
index 7910ac2..ac92009b 100644
--- a/ash/webui/telemetry_extension_ui/services/BUILD.gn
+++ b/ash/webui/telemetry_extension_ui/services/BUILD.gn
@@ -14,6 +14,8 @@
     "diagnostics_service.h",
     "diagnostics_service_converters.cc",
     "diagnostics_service_converters.h",
+    "fake_probe_service.cc",
+    "fake_probe_service.h",
     "lid_observer.cc",
     "lid_observer.h",
     "power_observer.cc",
@@ -30,10 +32,10 @@
     "//ash/webui/telemetry_extension_ui/mojom",
     "//base",
     "//chrome/browser/ash/wilco_dtc_supportd:mojo_utils",
+    "//chromeos/ash/services/cros_healthd/public/cpp",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//chromeos/dbus",
     "//chromeos/dbus/debug_daemon",
-    "//chromeos/services/cros_healthd/public/cpp",
-    "//chromeos/services/cros_healthd/public/mojom",
   ]
 }
 
@@ -51,10 +53,10 @@
     "//base",
     "//base/test:test_support",
     "//chrome/browser/ash/wilco_dtc_supportd:mojo_utils",
+    "//chromeos/ash/services/cros_healthd/public/cpp",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//chromeos/dbus",
     "//chromeos/dbus/debug_daemon",
-    "//chromeos/services/cros_healthd/public/cpp",
-    "//chromeos/services/cros_healthd/public/mojom",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/ash/webui/telemetry_extension_ui/services/bluetooth_observer.cc b/ash/webui/telemetry_extension_ui/services/bluetooth_observer.cc
index e32b9b5..968924f 100644
--- a/ash/webui/telemetry_extension_ui/services/bluetooth_observer.cc
+++ b/ash/webui/telemetry_extension_ui/services/bluetooth_observer.cc
@@ -8,7 +8,7 @@
 
 #include "ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom.h"
 #include "base/bind.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 
 namespace ash {
 
diff --git a/ash/webui/telemetry_extension_ui/services/bluetooth_observer.h b/ash/webui/telemetry_extension_ui/services/bluetooth_observer.h
index 3c2da6b5..e3b8e18 100644
--- a/ash/webui/telemetry_extension_ui/services/bluetooth_observer.h
+++ b/ash/webui/telemetry_extension_ui/services/bluetooth_observer.h
@@ -6,7 +6,7 @@
 #define ASH_WEBUI_TELEMETRY_EXTENSION_UI_SERVICES_BLUETOOTH_OBSERVER_H_
 
 #include "ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom-forward.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
diff --git a/ash/webui/telemetry_extension_ui/services/diagnostics_service.cc b/ash/webui/telemetry_extension_ui/services/diagnostics_service.cc
index 49e6f16..d65289f1 100644
--- a/ash/webui/telemetry_extension_ui/services/diagnostics_service.cc
+++ b/ash/webui/telemetry_extension_ui/services/diagnostics_service.cc
@@ -9,9 +9,9 @@
 
 #include "ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.h"
 #include "base/bind.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/nullable_primitives.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/nullable_primitives.mojom.h"
 
 namespace ash {
 
diff --git a/ash/webui/telemetry_extension_ui/services/diagnostics_service.h b/ash/webui/telemetry_extension_ui/services/diagnostics_service.h
index 4571ef4..26207f2 100644
--- a/ash/webui/telemetry_extension_ui/services/diagnostics_service.h
+++ b/ash/webui/telemetry_extension_ui/services/diagnostics_service.h
@@ -6,7 +6,7 @@
 #define ASH_WEBUI_TELEMETRY_EXTENSION_UI_SERVICES_DIAGNOSTICS_SERVICE_H_
 
 #include "ash/webui/telemetry_extension_ui/mojom/diagnostics_service.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.cc b/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.cc
index f02ece584..8afcee7 100644
--- a/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.cc
+++ b/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.cc
@@ -8,7 +8,7 @@
 #include "base/notreached.h"
 #include "base/strings/string_piece.h"
 #include "chrome/browser/ash/wilco_dtc_supportd/mojo_utils.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
diff --git a/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.h b/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.h
index 149b0ea..84bf0f2 100644
--- a/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.h
+++ b/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.h
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "ash/webui/telemetry_extension_ui/mojom/diagnostics_service.mojom-forward.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "mojo/public/cpp/system/handle.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters_unittest.cc b/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters_unittest.cc
index ede0cd76..6d8c9973 100644
--- a/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters_unittest.cc
+++ b/ash/webui/telemetry_extension_ui/services/diagnostics_service_converters_unittest.cc
@@ -5,7 +5,7 @@
 #include "ash/webui/telemetry_extension_ui/services/diagnostics_service_converters.h"
 
 #include "ash/webui/telemetry_extension_ui/mojom/diagnostics_service.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
diff --git a/ash/webui/telemetry_extension_ui/services/fake_probe_service.cc b/ash/webui/telemetry_extension_ui/services/fake_probe_service.cc
new file mode 100644
index 0000000..698b600
--- /dev/null
+++ b/ash/webui/telemetry_extension_ui/services/fake_probe_service.cc
@@ -0,0 +1,82 @@
+// 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 "ash/webui/telemetry_extension_ui/services/fake_probe_service.h"
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include "ash/webui/telemetry_extension_ui/mojom/probe_service.mojom-shared.h"
+#include "ash/webui/telemetry_extension_ui/mojom/probe_service.mojom.h"
+#include "ash/webui/telemetry_extension_ui/services/probe_service.h"
+#include "ash/webui/telemetry_extension_ui/services/probe_service_converters.h"
+#include "base/bind.h"
+#include "base/check.h"
+#include "base/location.h"
+#include "base/memory/ptr_util.h"
+#include "base/task/thread_pool.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+
+namespace ash {
+
+FakeProbeService::FakeProbeService(
+    mojo::PendingReceiver<health::mojom::ProbeService> receiver,
+    health::mojom::TelemetryInfoPtr telem_info,
+    health::mojom::OemDataPtr oem_data,
+    std::vector<health::mojom::ProbeCategoryEnum>* requested_categories)
+    : receiver_(this, std::move(receiver)),
+      telem_info_(std::move(telem_info)),
+      oem_data_(std::move(oem_data)),
+      requested_categories_(requested_categories) {}
+
+FakeProbeService::~FakeProbeService() = default;
+
+void FakeProbeService::ProbeTelemetryInfo(
+    const std::vector<health::mojom::ProbeCategoryEnum>& categories,
+    ProbeTelemetryInfoCallback callback) {
+  DCHECK(requested_categories_->empty());
+  requested_categories_->insert(requested_categories_->end(),
+                                categories.begin(), categories.end());
+
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), telem_info_.Clone()));
+}
+
+void FakeProbeService::GetOemData(GetOemDataCallback callback) {
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), oem_data_.Clone()));
+}
+
+void FakeProbeService::Factory::SetProbeTelemetryInfoResponseForTesting(
+    health::mojom::TelemetryInfoPtr response_info) {
+  telem_info_ = std::move(response_info);
+}
+
+void FakeProbeService::Factory::SetOemDataResponseForTesting(
+    health::mojom::OemDataPtr oem_data) {
+  oem_data_ = std::move(oem_data);
+}
+
+std::vector<health::mojom::ProbeCategoryEnum>
+FakeProbeService::Factory::GetAndClearRequestedCategories() {
+  return std::move(requested_categories_);
+}
+
+std::unique_ptr<health::mojom::ProbeService>
+FakeProbeService::Factory::CreateInstance(
+    mojo::PendingReceiver<health::mojom::ProbeService> receiver) {
+  return base::WrapUnique<FakeProbeService>(
+      new FakeProbeService(std::move(receiver), telem_info_->Clone(),
+                           oem_data_.Clone(), &requested_categories_));
+}
+
+FakeProbeService::Factory::Factory() = default;
+FakeProbeService::Factory::~Factory() {
+  DCHECK(requested_categories_.empty())
+      << "FakeProbeService::Factory::CheckAndClearRequestedCategories has not "
+         "been called, you probably forgot to check the requested categories";
+};
+
+}  // namespace ash
diff --git a/ash/webui/telemetry_extension_ui/services/fake_probe_service.h b/ash/webui/telemetry_extension_ui/services/fake_probe_service.h
new file mode 100644
index 0000000..9a2fc8f
--- /dev/null
+++ b/ash/webui/telemetry_extension_ui/services/fake_probe_service.h
@@ -0,0 +1,82 @@
+// 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 ASH_WEBUI_TELEMETRY_EXTENSION_UI_SERVICES_FAKE_PROBE_SERVICE_H_
+#define ASH_WEBUI_TELEMETRY_EXTENSION_UI_SERVICES_FAKE_PROBE_SERVICE_H_
+
+#include <memory>
+#include <vector>
+
+#include "ash/webui/telemetry_extension_ui/mojom/probe_service.mojom-shared.h"
+#include "ash/webui/telemetry_extension_ui/mojom/probe_service.mojom.h"
+#include "ash/webui/telemetry_extension_ui/services/probe_service.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+
+namespace ash {
+
+class FakeProbeService : public health::mojom::ProbeService {
+ public:
+  class Factory : public ash::ProbeService::Factory {
+   public:
+    Factory();
+    ~Factory() override;
+
+    // Sets the one-time response of |ProbeTelemetryInfo| method.
+    void SetProbeTelemetryInfoResponseForTesting(
+        health::mojom::TelemetryInfoPtr response_info);
+
+    // Sets the one-time response of |GetOemData| method.
+    void SetOemDataResponseForTesting(health::mojom::OemDataPtr oem_data);
+
+    // Returns all categories that have been requested after the
+    // FakeProbeService has been created and invoked.
+    std::vector<health::mojom::ProbeCategoryEnum>
+    GetAndClearRequestedCategories();
+
+   protected:
+    // ProbeService::Factory:
+    std::unique_ptr<health::mojom::ProbeService> CreateInstance(
+        mojo::PendingReceiver<health::mojom::ProbeService> receiver) override;
+
+   private:
+    health::mojom::TelemetryInfoPtr telem_info_{
+        health::mojom::TelemetryInfo::New()};
+
+    health::mojom::OemDataPtr oem_data_{health::mojom::OemData::New()};
+
+    std::vector<health::mojom::ProbeCategoryEnum> requested_categories_;
+  };
+
+  FakeProbeService(const FakeProbeService&) = delete;
+  FakeProbeService& operator=(const FakeProbeService&) = delete;
+  ~FakeProbeService() override;
+
+ private:
+  explicit FakeProbeService(
+      mojo::PendingReceiver<health::mojom::ProbeService> receiver,
+      health::mojom::TelemetryInfoPtr telem_info,
+      health::mojom::OemDataPtr oem_data,
+      std::vector<health::mojom::ProbeCategoryEnum>* requested_categories);
+
+  void ProbeTelemetryInfo(
+      const std::vector<health::mojom::ProbeCategoryEnum>& categories,
+      ProbeTelemetryInfoCallback callback) override;
+
+  void GetOemData(GetOemDataCallback callback) override;
+
+  mojo::Receiver<health::mojom::ProbeService> receiver_;
+
+  health::mojom::TelemetryInfoPtr telem_info_;
+
+  health::mojom::OemDataPtr oem_data_;
+
+  // A pointer to the requested categories, gets filled up by
+  // |ProbeTelemetryInfo|.
+  std::vector<health::mojom::ProbeCategoryEnum>* requested_categories_;
+};
+
+}  // namespace ash
+
+#endif  // ASH_WEBUI_TELEMETRY_EXTENSION_UI_SERVICES_FAKE_PROBE_SERVICE_H_
diff --git a/ash/webui/telemetry_extension_ui/services/lid_observer.cc b/ash/webui/telemetry_extension_ui/services/lid_observer.cc
index e3e89b1..e4ca3dc6 100644
--- a/ash/webui/telemetry_extension_ui/services/lid_observer.cc
+++ b/ash/webui/telemetry_extension_ui/services/lid_observer.cc
@@ -8,7 +8,7 @@
 
 #include "ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom.h"
 #include "base/bind.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 
 namespace ash {
 
diff --git a/ash/webui/telemetry_extension_ui/services/lid_observer.h b/ash/webui/telemetry_extension_ui/services/lid_observer.h
index 097aa7c..12b001d 100644
--- a/ash/webui/telemetry_extension_ui/services/lid_observer.h
+++ b/ash/webui/telemetry_extension_ui/services/lid_observer.h
@@ -6,7 +6,7 @@
 #define ASH_WEBUI_TELEMETRY_EXTENSION_UI_SERVICES_LID_OBSERVER_H_
 
 #include "ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom-forward.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
diff --git a/ash/webui/telemetry_extension_ui/services/power_observer.cc b/ash/webui/telemetry_extension_ui/services/power_observer.cc
index 7303cb2..1b5b2e5 100644
--- a/ash/webui/telemetry_extension_ui/services/power_observer.cc
+++ b/ash/webui/telemetry_extension_ui/services/power_observer.cc
@@ -8,7 +8,7 @@
 
 #include "ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom.h"
 #include "base/bind.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 
 namespace ash {
 
diff --git a/ash/webui/telemetry_extension_ui/services/power_observer.h b/ash/webui/telemetry_extension_ui/services/power_observer.h
index 896de58..a2ed3962 100644
--- a/ash/webui/telemetry_extension_ui/services/power_observer.h
+++ b/ash/webui/telemetry_extension_ui/services/power_observer.h
@@ -6,7 +6,7 @@
 #define ASH_WEBUI_TELEMETRY_EXTENSION_UI_SERVICES_POWER_OBSERVER_H_
 
 #include "ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom-forward.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
diff --git a/ash/webui/telemetry_extension_ui/services/probe_service.cc b/ash/webui/telemetry_extension_ui/services/probe_service.cc
index 3438ad8..a56498e4 100644
--- a/ash/webui/telemetry_extension_ui/services/probe_service.cc
+++ b/ash/webui/telemetry_extension_ui/services/probe_service.cc
@@ -8,10 +8,11 @@
 
 #include "ash/webui/telemetry_extension_ui/services/probe_service_converters.h"
 #include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace ash {
@@ -21,6 +22,26 @@
 constexpr char kOemDataLogName[] = "oemdata";
 }  // namespace
 
+// static
+ProbeService::Factory* ProbeService::Factory::test_factory_ = nullptr;
+
+// static
+std::unique_ptr<health::mojom::ProbeService> ProbeService::Factory::Create(
+    mojo::PendingReceiver<health::mojom::ProbeService> receiver) {
+  if (test_factory_) {
+    return test_factory_->CreateInstance(std::move(receiver));
+  }
+
+  return base::WrapUnique<ProbeService>(new ProbeService(std::move(receiver)));
+}
+
+// static
+void ProbeService::Factory::SetForTesting(ProbeService::Factory* test_factory) {
+  test_factory_ = test_factory;
+}
+
+ProbeService::Factory::~Factory() = default;
+
 ProbeService::ProbeService(
     mojo::PendingReceiver<health::mojom::ProbeService> receiver)
     : receiver_(this, std::move(receiver)) {}
diff --git a/ash/webui/telemetry_extension_ui/services/probe_service.h b/ash/webui/telemetry_extension_ui/services/probe_service.h
index 606bf8a..63be7e3 100644
--- a/ash/webui/telemetry_extension_ui/services/probe_service.h
+++ b/ash/webui/telemetry_extension_ui/services/probe_service.h
@@ -5,10 +5,11 @@
 #ifndef ASH_WEBUI_TELEMETRY_EXTENSION_UI_SERVICES_PROBE_SERVICE_H_
 #define ASH_WEBUI_TELEMETRY_EXTENSION_UI_SERVICES_PROBE_SERVICE_H_
 
+#include <memory>
 #include <vector>
 
 #include "ash/webui/telemetry_extension_ui/mojom/probe_service.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -22,13 +23,31 @@
 
 class ProbeService : public health::mojom::ProbeService {
  public:
-  explicit ProbeService(
-      mojo::PendingReceiver<health::mojom::ProbeService> receiver);
+  class Factory {
+   public:
+    static std::unique_ptr<health::mojom::ProbeService> Create(
+        mojo::PendingReceiver<health::mojom::ProbeService> receiver);
+    static void SetForTesting(Factory* test_factory);
+
+    virtual ~Factory();
+
+   protected:
+    virtual std::unique_ptr<health::mojom::ProbeService> CreateInstance(
+        mojo::PendingReceiver<health::mojom::ProbeService> receiver) = 0;
+
+   private:
+    static Factory* test_factory_;
+  };
+
   ProbeService(const ProbeService&) = delete;
   ProbeService& operator=(const ProbeService&) = delete;
   ~ProbeService() override;
 
  private:
+  explicit ProbeService(
+      mojo::PendingReceiver<health::mojom::ProbeService> receiver);
+
+  // health::mojom::ProbeService override
   void ProbeTelemetryInfo(
       const std::vector<health::mojom::ProbeCategoryEnum>& categories,
       ProbeTelemetryInfoCallback callback) override;
diff --git a/ash/webui/telemetry_extension_ui/services/probe_service_converters.cc b/ash/webui/telemetry_extension_ui/services/probe_service_converters.cc
index 3ad4d5a..3c13c08 100644
--- a/ash/webui/telemetry_extension_ui/services/probe_service_converters.cc
+++ b/ash/webui/telemetry_extension_ui/services/probe_service_converters.cc
@@ -10,7 +10,7 @@
 #include "ash/webui/telemetry_extension_ui/mojom/probe_service.mojom.h"
 #include "base/notreached.h"
 #include "base/strings/string_number_conversions.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 
 namespace ash {
 namespace converters {
diff --git a/ash/webui/telemetry_extension_ui/services/probe_service_converters.h b/ash/webui/telemetry_extension_ui/services/probe_service_converters.h
index c925ac16..dafc7ee 100644
--- a/ash/webui/telemetry_extension_ui/services/probe_service_converters.h
+++ b/ash/webui/telemetry_extension_ui/services/probe_service_converters.h
@@ -10,8 +10,8 @@
 
 #include "ash/webui/telemetry_extension_ui/mojom/probe_service.mojom-forward.h"
 #include "base/check.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-forward.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-forward.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/nullable_primitives.mojom-forward.h"
 
 namespace ash {
 
diff --git a/ash/webui/telemetry_extension_ui/services/probe_service_converters_unittest.cc b/ash/webui/telemetry_extension_ui/services/probe_service_converters_unittest.cc
index a8ea2ab..f4a18f1 100644
--- a/ash/webui/telemetry_extension_ui/services/probe_service_converters_unittest.cc
+++ b/ash/webui/telemetry_extension_ui/services/probe_service_converters_unittest.cc
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "ash/webui/telemetry_extension_ui/mojom/probe_service.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/webui/telemetry_extension_ui/services/probe_service_unittest.cc b/ash/webui/telemetry_extension_ui/services/probe_service_unittest.cc
index d58a5d8..7a02f6a7 100644
--- a/ash/webui/telemetry_extension_ui/services/probe_service_unittest.cc
+++ b/ash/webui/telemetry_extension_ui/services/probe_service_unittest.cc
@@ -10,9 +10,9 @@
 #include "base/bind.h"
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -52,8 +52,9 @@
   base::test::TaskEnvironment task_environment_;
 
   mojo::Remote<health::mojom::ProbeService> remote_probe_service_;
-  ProbeService probe_service_{
-      remote_probe_service_.BindNewPipeAndPassReceiver()};
+  std::unique_ptr<ash::health::mojom::ProbeService> probe_service_{
+      ProbeService::Factory::Create(
+          remote_probe_service_.BindNewPipeAndPassReceiver())};
 
   FakeDebugDaemonClient* fake_debugd_client_ = nullptr;
 };
diff --git a/ash/webui/telemetry_extension_ui/services/system_events_service_unittest.cc b/ash/webui/telemetry_extension_ui/services/system_events_service_unittest.cc
index ebca04d8..9430c182 100644
--- a/ash/webui/telemetry_extension_ui/services/system_events_service_unittest.cc
+++ b/ash/webui/telemetry_extension_ui/services/system_events_service_unittest.cc
@@ -9,8 +9,8 @@
 #include "ash/webui/telemetry_extension_ui/mojom/system_events_service.mojom.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/ash/wm/float/float_controller.cc b/ash/wm/float/float_controller.cc
index 29cdf17a..3480dc5b 100644
--- a/ash/wm/float/float_controller.cc
+++ b/ash/wm/float/float_controller.cc
@@ -6,17 +6,88 @@
 
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/shell.h"
 #include "ash/wm/desks/desks_util.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "ash/wm/tablet_mode/tablet_mode_window_state.h"
+#include "ash/wm/window_state.h"
+#include "ash/wm/work_area_insets.h"
 #include "base/check_op.h"
 #include "chromeos/ui/base/window_properties.h"
+#include "ui/aura/window_delegate.h"
 
 namespace ash {
 
+namespace {
+
+// The ideal dimensions of a float window before factoring in its minimum size
+// (if any) is the available work area multiplied by these ratios.
+constexpr float kFloatWindowTabletWidthRatio = 0.3333333f;
+constexpr float kFloatWindowTabletHeightRatio = 0.8f;
+
+// The distance from the edge of the floated window to the edge of the work area
+// when it is floated.
+constexpr int kFloatWindowPaddingDp = 8;
+
+bool InTabletMode() {
+  return Shell::Get()->tablet_mode_controller()->InTabletMode();
+}
+
+gfx::Size GetPreferredFloatWindowTabletSize(const gfx::Rect& work_area) {
+  const int preferred_width =
+      static_cast<int>(work_area.width() * kFloatWindowTabletWidthRatio);
+  const int preferred_height =
+      work_area.height() * kFloatWindowTabletHeightRatio;
+  return gfx::Size(preferred_width, preferred_height);
+}
+
+}  // namespace
+
 FloatController::FloatController() = default;
 
 FloatController::~FloatController() = default;
 
-bool FloatController::IsFloated(aura::Window* window) const {
+// static
+gfx::Rect FloatController::GetPreferredFloatWindowTabletBounds(
+    aura::Window* window) {
+  DCHECK(CanFloatWindowInTablet(window));
+  const gfx::Rect work_area = WorkAreaInsets::ForWindow(window->GetRootWindow())
+                                  ->user_work_area_bounds();
+  const gfx::Size preferred_size = GetPreferredFloatWindowTabletSize(work_area);
+  const gfx::Size minimum_size = window->delegate()->GetMinimumSize();
+
+  const int width = std::max(preferred_size.width(), minimum_size.width());
+  DCHECK_GT(preferred_size.height(), minimum_size.height());
+
+  // TODO(sammiequon): This assumes the float window is to be magnetized to
+  // the right. Once dragging and interactions with other window states is
+  // allowed, it needs to be reworked.
+  gfx::Rect float_bounds(work_area.right() - width,
+                         work_area.bottom() - preferred_size.height(), width,
+                         preferred_size.height());
+  float_bounds.Offset(-kFloatWindowPaddingDp, -kFloatWindowPaddingDp);
+  return float_bounds;
+}
+
+// static
+bool FloatController::CanFloatWindowInTablet(aura::Window* window) {
+  auto* window_state = WindowState::Get(window);
+  if (!window_state || !window_state->CanResize())
+    return false;
+
+  const gfx::Rect work_area = WorkAreaInsets::ForWindow(window->GetRootWindow())
+                                  ->user_work_area_bounds();
+  const int preferred_height =
+      GetPreferredFloatWindowTabletSize(work_area).height();
+  const gfx::Size minimum_size = window->delegate()->GetMinimumSize();
+  if (minimum_size.width() > work_area.width() / 2 ||
+      minimum_size.height() > preferred_height) {
+    return false;
+  }
+  return true;
+}
+
+bool FloatController::IsFloated(const aura::Window* window) const {
   DCHECK(window);
   return float_window_ == window;
 }
@@ -25,6 +96,35 @@
   DCHECK_EQ(float_window_, window);
   float_window_observation_.Reset();
   float_window_ = nullptr;
+  tablet_mode_observation_.Reset();
+  display_observer_.reset();
+}
+
+void FloatController::OnTabletModeStarting() {
+  DCHECK(float_window_);
+  aura::Window* floated_window = float_window_;
+  if (!CanFloatWindowInTablet(floated_window))
+    ResetFloatedWindow();
+
+  MaybeUpdateWindowUIAndBoundsForTablet(floated_window);
+}
+
+void FloatController::OnTabletModeEnded() {
+  DCHECK(float_window_);
+  MaybeUpdateWindowUIAndBoundsForTablet(float_window_);
+}
+
+void FloatController::OnTabletControllerDestroyed() {
+  tablet_mode_observation_.Reset();
+}
+
+void FloatController::OnDisplayMetricsChanged(const display::Display& display,
+                                              uint32_t metrics) {
+  DCHECK(float_window_);
+  if ((display::DisplayObserver::DISPLAY_METRIC_WORK_AREA & metrics) == 0)
+    return;
+  if (!CanFloatWindowInTablet(float_window_))
+    ResetFloatedWindow();
 }
 
 void FloatController::Float(aura::Window* window) {
@@ -38,6 +138,10 @@
       window->GetRootWindow()->GetChildById(kShellWindowId_FloatContainer);
   if (window->parent() != float_container)
     float_container->AddChild(window);
+
+  tablet_mode_observation_.Observe(Shell::Get()->tablet_mode_controller());
+  display_observer_.emplace(this);
+  MaybeUpdateWindowUIAndBoundsForTablet(window);
 }
 
 void FloatController::Unfloat(aura::Window* window) {
@@ -47,6 +151,10 @@
       ->AddChild(float_window_);
   float_window_observation_.Reset();
   float_window_ = nullptr;
+
+  tablet_mode_observation_.Reset();
+  display_observer_.reset();
+  MaybeUpdateWindowUIAndBoundsForTablet(window);
 }
 
 void FloatController::ResetFloatedWindow() {
@@ -54,4 +162,18 @@
     float_window_->SetProperty(chromeos::kWindowToggleFloatKey, false);
 }
 
-}  // namespace ash
\ No newline at end of file
+void FloatController::MaybeUpdateWindowUIAndBoundsForTablet(
+    aura::Window* window) {
+  DCHECK(window);
+
+  if (!InTabletMode())
+    return;
+
+  // TODO(sophiewen): Update rounded corners and shadow.
+
+  WindowState* window_state = WindowState::Get(window);
+  DCHECK(window_state);
+  TabletModeWindowState::UpdateWindowPosition(window_state, /*animate=*/true);
+}
+
+}  // namespace ash
diff --git a/ash/wm/float/float_controller.h b/ash/wm/float/float_controller.h
index c02c19b..e528a90 100644
--- a/ash/wm/float/float_controller.h
+++ b/ash/wm/float/float_controller.h
@@ -6,9 +6,12 @@
 #define ASH_WM_FLOAT_FLOAT_CONTROLLER_H_
 
 #include "ash/ash_export.h"
+#include "ash/public/cpp/tablet_mode_observer.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/scoped_observation.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
+#include "ui/display/display_observer.h"
 
 namespace ash {
 
@@ -16,23 +19,43 @@
 // pips. When a window is 'floated', it remains always on top for the user so
 // that they can complete secondary tasks. Floated window stays in the
 // |float_container|.
-class ASH_EXPORT FloatController : public aura::WindowObserver {
+class ASH_EXPORT FloatController : public aura::WindowObserver,
+                                   public TabletModeObserver,
+                                   public display::DisplayObserver {
  public:
   FloatController();
   FloatController(const FloatController&) = delete;
   FloatController& operator=(const FloatController&) = delete;
   ~FloatController() override;
 
+  // Gets the ideal float bounds of `window` in tablet mode if it were to be
+  // floated.
+  static gfx::Rect GetPreferredFloatWindowTabletBounds(aura::Window* window);
+
+  // Determines if a window can be floated in tablet mode.
+  static bool CanFloatWindowInTablet(aura::Window* window);
+
   aura::Window* float_window() { return float_window_; }
 
   // Return true if `window` is floated, otherwise false.
-  bool IsFloated(aura::Window* window) const;
+  bool IsFloated(const aura::Window* window) const;
 
   // aura::WindowObserver:
   void OnWindowDestroying(aura::Window* window) override;
 
+  // TabletModeObserver:
+  void OnTabletModeStarting() override;
+  void OnTabletModeEnded() override;
+  void OnTabletControllerDestroyed() override;
+
+  // display::DisplayObserver:
+  void OnDisplayMetricsChanged(const display::Display& display,
+                               uint32_t metrics) override;
+
  private:
   friend class DefaultState;
+  friend class TabletModeWindowState;
+
   // Floats/Unfloats `window`.
   // Only one floating window is allowed, floating a new window will
   // unfloat the other floated window (if any).
@@ -42,6 +65,10 @@
   // Unfloats floated window.
   void ResetFloatedWindow();
 
+  // Updates `window`'s shadow and bounds depending on whether is in floated and
+  // if it is in tablet mode.
+  void MaybeUpdateWindowUIAndBoundsForTablet(aura::Window* window);
+
   // Only one floating window is allowed, updated when a new window
   // is floated.
   aura::Window* float_window_ = nullptr;
@@ -49,8 +76,12 @@
   // Observes floated window.
   base::ScopedObservation<aura::Window, aura::WindowObserver>
       float_window_observation_{this};
+
+  base::ScopedObservation<TabletModeController, TabletModeObserver>
+      tablet_mode_observation_{this};
+  absl::optional<display::ScopedOptionalDisplayObserver> display_observer_;
 };
 
 }  // namespace ash
 
-#endif  // ASH_WM_FLOAT_FLOAT_CONTROLLER_H_
\ No newline at end of file
+#endif  // ASH_WM_FLOAT_FLOAT_CONTROLLER_H_
diff --git a/ash/wm/float/float_controller_unittest.cc b/ash/wm/float/float_controller_unittest.cc
index b5a5563f..b812a1c 100644
--- a/ash/wm/float/float_controller_unittest.cc
+++ b/ash/wm/float/float_controller_unittest.cc
@@ -8,8 +8,10 @@
 #include "ash/constants/ash_features.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/test/scoped_feature_list.h"
 #include "chromeos/ui/wm/features.h"
+#include "ui/aura/test/test_window_delegate.h"
 #include "ui/wm/core/window_util.h"
 
 namespace ash {
@@ -61,4 +63,71 @@
   EXPECT_FALSE(controller->IsFloated(window_2.get()));
 }
 
-}  // namespace ash
\ No newline at end of file
+// Tests that a window can be floated in tablet mode, unless its minimum width
+// is greater than half the work area.
+TEST_F(WindowFloatTest, TabletPositioningLandscape) {
+  UpdateDisplay("800x600");
+
+  aura::test::TestWindowDelegate window_delegate;
+  std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
+      &window_delegate, /*id=*/-1, gfx::Rect(300, 300)));
+  wm::ActivateWindow(window.get());
+
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+
+  FloatController* controller = Shell::Get()->float_controller();
+
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  ASSERT_TRUE(controller->IsFloated(window.get()));
+
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  ASSERT_FALSE(controller->IsFloated(window.get()));
+
+  window_delegate.set_minimum_size(gfx::Size(600, 600));
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  EXPECT_FALSE(controller->IsFloated(window.get()));
+}
+
+// Tests that a window that cannot be floated in tablet mode unfloats after
+// entering tablet mode.
+TEST_F(WindowFloatTest, FloatWindowUnfloatsEnterTablet) {
+  UpdateDisplay("800x600");
+
+  aura::test::TestWindowDelegate window_delegate;
+  std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
+      &window_delegate, /*id=*/-1, gfx::Rect(300, 300)));
+  window_delegate.set_minimum_size(gfx::Size(600, 600));
+  wm::ActivateWindow(window.get());
+
+  FloatController* controller = Shell::Get()->float_controller();
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  ASSERT_TRUE(controller->IsFloated(window.get()));
+
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+  EXPECT_FALSE(controller->IsFloated(window.get()));
+}
+
+// Tests that a floated window unfloats if a display change makes it no longer a
+// valid floating window.
+TEST_F(WindowFloatTest, FloatWindowUnfloatsDisplayChange) {
+  UpdateDisplay("1800x1000");
+
+  aura::test::TestWindowDelegate window_delegate;
+  std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
+      &window_delegate, /*id=*/-1, gfx::Rect(300, 300)));
+  window_delegate.set_minimum_size(gfx::Size(400, 400));
+  wm::ActivateWindow(window.get());
+
+  // Enter tablet mode and float `window`.
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+  FloatController* controller = Shell::Get()->float_controller();
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  ASSERT_TRUE(controller->IsFloated(window.get()));
+
+  // If the display width is 700, the minimum width exceeds half the display
+  // width.
+  UpdateDisplay("700x600");
+  EXPECT_FALSE(controller->IsFloated(window.get()));
+}
+
+}  // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.cc b/ash/wm/tablet_mode/tablet_mode_window_state.cc
index 63cfc64..67b0837 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_state.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_state.cc
@@ -15,6 +15,7 @@
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/wm/desks/desks_controller.h"
+#include "ash/wm/float/float_controller.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/screen_pinning_controller.h"
@@ -25,6 +26,7 @@
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
 #include "chromeos/ui/base/window_state_type.h"
+#include "chromeos/ui/wm/features.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/compositor/layer.h"
@@ -99,6 +101,11 @@
         ->GetSnappedWindowBoundsInParent(SplitViewController::RIGHT, window);
   }
 
+  if (chromeos::wm::features::IsFloatWindowEnabled() &&
+      state_object->IsFloated()) {
+    return FloatController::GetPreferredFloatWindowTabletBounds(window);
+  }
+
   gfx::Rect bounds_in_parent;
   // Make the window as big as possible.
 
@@ -307,8 +314,13 @@
       }
       break;
     }
-    // TODO(shidi): Float is currently disabled for tablet mode.
     case WM_EVENT_FLOAT:
+      // Not all windows can be floated.
+      if (!FloatController::CanFloatWindowInTablet(window_state->window()))
+        return;
+
+      UpdateWindow(window_state, WindowStateType::kFloated,
+                   /*=animated=*/true);
       break;
     case WM_EVENT_SNAP_PRIMARY:
     case WM_EVENT_SNAP_SECONDARY:
@@ -432,10 +444,11 @@
          target_state == WindowStateType::kTrustedPinned ||
          (target_state == WindowStateType::kNormal &&
           (!window_state->CanMaximize() ||
-           !!::wm::GetTransientParent(window_state->window()))) ||
+           !!wm::GetTransientParent(window_state->window()))) ||
          target_state == WindowStateType::kFullscreen ||
          target_state == WindowStateType::kPrimarySnapped ||
-         target_state == WindowStateType::kSecondarySnapped);
+         target_state == WindowStateType::kSecondarySnapped ||
+         target_state == WindowStateType::kFloated);
 
   if (current_state_type_ == target_state) {
     if (target_state == WindowStateType::kMinimized)
@@ -450,8 +463,15 @@
   window_state->UpdateWindowPropertiesFromStateType();
   window_state->NotifyPreStateTypeChange(old_state_type);
 
+  if (target_state == WindowStateType::kFloated)
+    Shell::Get()->float_controller()->Float(window_state->window());
+
+  // Unfloat floated window when exiting float state to another state.
+  if (old_state_type == WindowStateType::kFloated)
+    Shell::Get()->float_controller()->Unfloat(window_state->window());
+
   if (target_state == WindowStateType::kMinimized) {
-    ::wm::SetWindowVisibilityAnimationType(
+    wm::SetWindowVisibilityAnimationType(
         window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
     window_state->window()->Hide();
     if (window_state->IsActive())
@@ -518,9 +538,9 @@
             bounds_in_parent, base::Seconds(1), gfx::Tween::ZERO);
         return;
       }
-      // If we animate (to) tablet mode, we want to use the cross fade to
-      // avoid flashing.
-      if (window_state->IsMaximized())
+      // Use cross fade in some cases to avoid flashing and/or for better
+      // performance.
+      if (window_state->IsMaximized() || window_state->IsFloated())
         window_state->SetBoundsDirectCrossFade(bounds_in_parent);
       else
         window_state->SetBoundsDirectAnimated(bounds_in_parent);
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 7ea3827..4249616 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2374,8 +2374,6 @@
       "trace_event/process_memory_dump.cc",
       "trace_event/process_memory_dump.h",
       "trace_event/task_execution_macros.h",
-      "trace_event/thread_instruction_count.cc",
-      "trace_event/thread_instruction_count.h",
       "trace_event/trace_arguments.cc",
       "trace_event/trace_arguments.h",
       "trace_event/trace_buffer.cc",
diff --git a/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java
index 2015ab4..7fe8b56 100644
--- a/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java
+++ b/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java
@@ -554,4 +554,42 @@
             mRwLock.readLock().unlock();
         }
     }
+
+    @VisibleForTesting
+    @Override
+    public int getHistogramValueCountForTesting(String name, int sample) {
+        mRwLock.readLock().lock();
+        try {
+            if (mDelegate != null) return mDelegate.getHistogramValueCountForTesting(name, sample);
+
+            Histogram histogram = mHistogramByName.get(name);
+            if (histogram == null) return 0;
+            int sampleCount = 0;
+            synchronized (histogram) {
+                for (int i = 0; i < histogram.mSamples.size(); i++) {
+                    if (histogram.mSamples.get(i) == sample) sampleCount++;
+                }
+            }
+            return sampleCount;
+        } finally {
+            mRwLock.readLock().unlock();
+        }
+    }
+
+    @VisibleForTesting
+    @Override
+    public int getHistogramTotalCountForTesting(String name) {
+        mRwLock.readLock().lock();
+        try {
+            if (mDelegate != null) return mDelegate.getHistogramTotalCountForTesting(name);
+
+            Histogram histogram = mHistogramByName.get(name);
+            if (histogram == null) return 0;
+            synchronized (histogram) {
+                return histogram.mSamples.size();
+            }
+        } finally {
+            mRwLock.readLock().unlock();
+        }
+    }
 }
diff --git a/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java
index 9979f61..6b9ee66 100644
--- a/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java
+++ b/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java
@@ -70,6 +70,16 @@
         NativeUmaRecorderJni.get().recordUserAction(name, millisSinceEvent);
     }
 
+    @Override
+    public int getHistogramValueCountForTesting(String name, int sample) {
+        return NativeUmaRecorderJni.get().getHistogramValueCountForTesting(name, sample, 0);
+    }
+
+    @Override
+    public int getHistogramTotalCountForTesting(String name) {
+        return NativeUmaRecorderJni.get().getHistogramTotalCountForTesting(name, 0);
+    }
+
     private long getNativeHint(String name) {
         Long hint = mNativeHints.get(name);
         // Note: If key is null, we don't have it cached. In that case, pass 0
@@ -87,7 +97,7 @@
 
     /** Natives API to record metrics. */
     @NativeMethods
-    interface Natives {
+    public interface Natives {
         long recordBooleanHistogram(String name, long nativeHint, boolean sample);
         long recordExponentialHistogram(
                 String name, long nativeHint, int sample, int min, int max, int numBuckets);
@@ -105,5 +115,8 @@
          *         Should be positive.
          */
         void recordUserAction(String name, long millisSinceEvent);
+
+        int getHistogramValueCountForTesting(String name, int sample, long snapshotPtr);
+        int getHistogramTotalCountForTesting(String name, long snapshotPtr);
     }
 }
diff --git a/base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java
index 196a729..74bb57d8 100644
--- a/base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java
+++ b/base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java
@@ -21,4 +21,14 @@
 
     @Override
     public void recordUserAction(String name, long elapsedRealtimeMillis) {}
+
+    @Override
+    public int getHistogramValueCountForTesting(String name, int sample) {
+        return 0;
+    }
+
+    @Override
+    public int getHistogramTotalCountForTesting(String name) {
+        return 0;
+    }
 }
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
index fd891d2..7f0351f6 100644
--- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
+++ b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -270,7 +270,7 @@
     @VisibleForTesting
     @Deprecated
     public static int getHistogramValueCountForTesting(String name, int sample) {
-        return RecordHistogramJni.get().getHistogramValueCountForTesting(name, sample, 0);
+        return UmaRecorderHolder.get().getHistogramValueCountForTesting(name, sample);
     }
 
     /**
@@ -282,7 +282,7 @@
     @VisibleForTesting
     @Deprecated
     public static int getHistogramTotalCountForTesting(String name) {
-        return RecordHistogramJni.get().getHistogramTotalCountForTesting(name, 0);
+        return UmaRecorderHolder.get().getHistogramTotalCountForTesting(name);
     }
 
     /**
@@ -290,8 +290,6 @@
      */
     @NativeMethods
     public interface Natives {
-        int getHistogramValueCountForTesting(String name, int sample, long snapshotPtr);
-        int getHistogramTotalCountForTesting(String name, long snapshotPtr);
         long createHistogramSnapshotForTesting();
         void destroyHistogramSnapshotForTesting(long snapshotPtr);
     }
diff --git a/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java
index 0d37d81..70d6f7e9 100644
--- a/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java
+++ b/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java
@@ -4,6 +4,8 @@
 
 package org.chromium.base.metrics;
 
+import androidx.annotation.VisibleForTesting;
+
 /** Common interface for code recording UMA metrics. */
 public interface UmaRecorder {
     /** Records a single sample of a boolean histogram. */
@@ -57,4 +59,23 @@
      *         the action was observed.
      */
     void recordUserAction(String name, long elapsedRealtimeMillis);
+
+    /**
+     * Returns the number of samples recorded in the given bucket of the given histogram.
+     * Does not reset between batched tests. Use HistogramTestRule instead.
+     *
+     * @param name name of the histogram to look up
+     * @param sample the bucket containing this sample value will be looked up
+     */
+    @VisibleForTesting
+    int getHistogramValueCountForTesting(String name, int sample);
+
+    /**
+     * Returns the number of samples recorded for the given histogram.
+     * Does not reset between batched tests. Use HistogramTestRule instead.
+     *
+     * @param name name of the histogram to look up
+     */
+    @VisibleForTesting
+    int getHistogramTotalCountForTesting(String name);
 }
diff --git a/base/android/junit/src/org/chromium/base/metrics/CachingUmaRecorderTest.java b/base/android/junit/src/org/chromium/base/metrics/CachingUmaRecorderTest.java
index fab7ea3..f5e9fb8 100644
--- a/base/android/junit/src/org/chromium/base/metrics/CachingUmaRecorderTest.java
+++ b/base/android/junit/src/org/chromium/base/metrics/CachingUmaRecorderTest.java
@@ -6,6 +6,7 @@
 
 import static org.hamcrest.Matchers.greaterThan;
 import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.times;
@@ -59,6 +60,17 @@
                 "cachingUmaRecorderTest.recordBooleanHistogram", true);
         cachingUmaRecorder.recordBooleanHistogram(
                 "cachingUmaRecorderTest.recordBooleanHistogram", false);
+
+        assertEquals(3,
+                cachingUmaRecorder.getHistogramTotalCountForTesting(
+                        "cachingUmaRecorderTest.recordBooleanHistogram"));
+        assertEquals(2,
+                cachingUmaRecorder.getHistogramValueCountForTesting(
+                        "cachingUmaRecorderTest.recordBooleanHistogram", 1));
+        assertEquals(1,
+                cachingUmaRecorder.getHistogramValueCountForTesting(
+                        "cachingUmaRecorderTest.recordBooleanHistogram", 0));
+
         cachingUmaRecorder.setDelegate(mUmaRecorder);
 
         verify(mUmaRecorder, times(2))
@@ -73,6 +85,12 @@
 
         cachingUmaRecorder.recordExponentialHistogram(
                 "cachingUmaRecorderTest.recordExponentialHistogram", 72, 1, 1000, 50);
+        assertEquals(1,
+                cachingUmaRecorder.getHistogramTotalCountForTesting(
+                        "cachingUmaRecorderTest.recordExponentialHistogram"));
+        assertEquals(1,
+                cachingUmaRecorder.getHistogramValueCountForTesting(
+                        "cachingUmaRecorderTest.recordExponentialHistogram", 72));
         cachingUmaRecorder.setDelegate(mUmaRecorder);
 
         verify(mUmaRecorder)
@@ -86,6 +104,13 @@
 
         cachingUmaRecorder.recordLinearHistogram(
                 "cachingUmaRecorderTest.recordLinearHistogram", 72, 1, 1000, 50);
+        assertEquals(1,
+                cachingUmaRecorder.getHistogramTotalCountForTesting(
+                        "cachingUmaRecorderTest.recordLinearHistogram"));
+        assertEquals(1,
+                cachingUmaRecorder.getHistogramValueCountForTesting(
+                        "cachingUmaRecorderTest.recordLinearHistogram", 72));
+
         cachingUmaRecorder.setDelegate(mUmaRecorder);
 
         verify(mUmaRecorder)
@@ -99,6 +124,12 @@
 
         cachingUmaRecorder.recordSparseHistogram(
                 "cachingUmaRecorderTest.recordSparseHistogram", 72);
+        assertEquals(1,
+                cachingUmaRecorder.getHistogramTotalCountForTesting(
+                        "cachingUmaRecorderTest.recordSparseHistogram"));
+        assertEquals(1,
+                cachingUmaRecorder.getHistogramValueCountForTesting(
+                        "cachingUmaRecorderTest.recordSparseHistogram", 72));
         cachingUmaRecorder.setDelegate(mUmaRecorder);
 
         verify(mUmaRecorder)
@@ -318,6 +349,16 @@
         public void recordUserAction(String name, long elapsedRealtimeMillis) {
             throw new UnsupportedOperationException();
         }
+
+        @Override
+        public int getHistogramValueCountForTesting(String name, int sample) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int getHistogramTotalCountForTesting(String name) {
+            throw new UnsupportedOperationException();
+        }
     }
 
     @Test
@@ -407,6 +448,16 @@
         public void recordUserAction(String name, long elapsedRealtimeMillis) {
             recordedSamples.addAndGet((int) elapsedRealtimeMillis, 1);
         }
+
+        @Override
+        public int getHistogramValueCountForTesting(String name, int sample) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int getHistogramTotalCountForTesting(String name) {
+            throw new UnsupportedOperationException();
+        }
     }
 
     @Test
diff --git a/base/android/native_uma_recorder.cc b/base/android/native_uma_recorder.cc
index 35cebe3fe..e3ed4550 100644
--- a/base/android/native_uma_recorder.cc
+++ b/base/android/native_uma_recorder.cc
@@ -10,6 +10,7 @@
 #include "base/metrics/histogram.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/sparse_histogram.h"
+#include "base/metrics/statistics_recorder.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/lock.h"
@@ -20,6 +21,9 @@
 
 namespace {
 
+using HistogramsSnapshot =
+    std::map<std::string, std::unique_ptr<HistogramSamples>>;
+
 // Simple thread-safe wrapper for caching histograms. This avoids
 // relatively expensive JNI string translation for each recording.
 class HistogramCache {
@@ -218,5 +222,53 @@
                             Milliseconds(j_millis_since_event));
 }
 
+// This backs a Java test util for testing histograms -
+// MetricsUtils.HistogramDelta. It should live in a test-specific file, but we
+// currently can't have test-specific native code packaged in test-specific Java
+// targets - see http://crbug.com/415945.
+jint JNI_NativeUmaRecorder_GetHistogramValueCountForTesting(
+    JNIEnv* env,
+    const JavaParamRef<jstring>& histogram_name,
+    jint sample,
+    jlong snapshot_ptr) {
+  std::string name = android::ConvertJavaStringToUTF8(env, histogram_name);
+  HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
+  if (histogram == nullptr) {
+    // No samples have been recorded for this histogram (yet?).
+    return 0;
+  }
+
+  int actual_count = histogram->SnapshotSamples()->GetCount(sample);
+  if (snapshot_ptr) {
+    auto* snapshot = reinterpret_cast<HistogramsSnapshot*>(snapshot_ptr);
+    auto snapshot_data = snapshot->find(name);
+    if (snapshot_data != snapshot->end())
+      actual_count -= snapshot_data->second->GetCount(sample);
+  }
+
+  return actual_count;
+}
+
+jint JNI_NativeUmaRecorder_GetHistogramTotalCountForTesting(
+    JNIEnv* env,
+    const JavaParamRef<jstring>& histogram_name,
+    jlong snapshot_ptr) {
+  std::string name = android::ConvertJavaStringToUTF8(env, histogram_name);
+  HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
+  if (histogram == nullptr) {
+    // No samples have been recorded for this histogram.
+    return 0;
+  }
+
+  int actual_count = histogram->SnapshotSamples()->TotalCount();
+  if (snapshot_ptr) {
+    auto* snapshot = reinterpret_cast<HistogramsSnapshot*>(snapshot_ptr);
+    auto snapshot_data = snapshot->find(name);
+    if (snapshot_data != snapshot->end())
+      actual_count -= snapshot_data->second->TotalCount();
+  }
+  return actual_count;
+}
+
 }  // namespace android
 }  // namespace base
diff --git a/base/android/record_histogram.cc b/base/android/record_histogram.cc
index 7e8063a9..cdcb470 100644
--- a/base/android/record_histogram.cc
+++ b/base/android/record_histogram.cc
@@ -19,54 +19,6 @@
 using HistogramsSnapshot =
     std::map<std::string, std::unique_ptr<HistogramSamples>>;
 
-// This backs a Java test util for testing histograms -
-// MetricsUtils.HistogramDelta. It should live in a test-specific file, but we
-// currently can't have test-specific native code packaged in test-specific Java
-// targets - see http://crbug.com/415945.
-jint JNI_RecordHistogram_GetHistogramValueCountForTesting(
-    JNIEnv* env,
-    const JavaParamRef<jstring>& histogram_name,
-    jint sample,
-    jlong snapshot_ptr) {
-  std::string name = android::ConvertJavaStringToUTF8(env, histogram_name);
-  HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
-  if (histogram == nullptr) {
-    // No samples have been recorded for this histogram (yet?).
-    return 0;
-  }
-
-  int actual_count = histogram->SnapshotSamples()->GetCount(sample);
-  if (snapshot_ptr) {
-    auto* snapshot = reinterpret_cast<HistogramsSnapshot*>(snapshot_ptr);
-    auto snapshot_data = snapshot->find(name);
-    if (snapshot_data != snapshot->end())
-      actual_count -= snapshot_data->second->GetCount(sample);
-  }
-
-  return actual_count;
-}
-
-jint JNI_RecordHistogram_GetHistogramTotalCountForTesting(
-    JNIEnv* env,
-    const JavaParamRef<jstring>& histogram_name,
-    jlong snapshot_ptr) {
-  std::string name = android::ConvertJavaStringToUTF8(env, histogram_name);
-  HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
-  if (histogram == nullptr) {
-    // No samples have been recorded for this histogram.
-    return 0;
-  }
-
-  int actual_count = histogram->SnapshotSamples()->TotalCount();
-  if (snapshot_ptr) {
-    auto* snapshot = reinterpret_cast<HistogramsSnapshot*>(snapshot_ptr);
-    auto snapshot_data = snapshot->find(name);
-    if (snapshot_data != snapshot->end())
-      actual_count -= snapshot_data->second->TotalCount();
-  }
-  return actual_count;
-}
-
 jlong JNI_RecordHistogram_CreateHistogramSnapshotForTesting(JNIEnv* env) {
   HistogramsSnapshot* snapshot = new HistogramsSnapshot();
   for (const auto* const histogram : StatisticsRecorder::GetHistograms()) {
diff --git a/base/base_switches.cc b/base/base_switches.cc
index 5d0c6a53..1694693 100644
--- a/base/base_switches.cc
+++ b/base/base_switches.cc
@@ -171,12 +171,6 @@
 #endif
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-// Controls whether or not retired instruction counts are surfaced for threads
-// in trace events on Linux.
-//
-// This flag requires the BPF sandbox to be disabled.
-const char kEnableThreadInstructionCount[] = "enable-thread-instruction-count";
-
 // TODO(crbug.com/1176772): Remove kEnableCrashpad and IsCrashpadEnabled() when
 // Crashpad is fully enabled on Linux. Indicates that Crashpad should be
 // enabled.
diff --git a/base/base_switches.h b/base/base_switches.h
index e50e279..f8843aee 100644
--- a/base/base_switches.h
+++ b/base/base_switches.h
@@ -61,8 +61,6 @@
 #endif
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-extern const char kEnableThreadInstructionCount[];
-
 // TODO(crbug.com/1176772): Remove kEnableCrashpad and IsCrashpadEnabled() when
 // Crashpad is fully enabled on Linux.
 extern const char kEnableCrashpad[];
diff --git a/base/fuchsia/service_provider_impl.h b/base/fuchsia/service_provider_impl.h
index fd17bdc..0404ea17 100644
--- a/base/fuchsia/service_provider_impl.h
+++ b/base/fuchsia/service_provider_impl.h
@@ -26,7 +26,8 @@
 // Implementation of the legacy sys.ServiceProvider interface which delegates
 // requests to an underlying fuchsia.io.Directory of services.
 // TODO(https://crbug.com/1065707): Remove this when it is no longer required
-// by the //fuchsia/base AgentImpl.
+// by //fuchsia_web/runners/common/modular/agent_impl.h and
+// //fuchsia_web/runners/web/web_runner_smoke_test.cc.
 class BASE_EXPORT ServiceProviderImpl : public ::fuchsia::sys::ServiceProvider {
  public:
   // Constructor that creates ServiceProvider for public services in the
diff --git a/base/memory/raw_ptr_unittest.cc b/base/memory/raw_ptr_unittest.cc
index 719ff96..b96147ed 100644
--- a/base/memory/raw_ptr_unittest.cc
+++ b/base/memory/raw_ptr_unittest.cc
@@ -1398,6 +1398,26 @@
   void func() { ++x; }
 };
 
+#define ASAN_BRP_PROTECTED(x) "MiraclePtr Status: PROTECTED\\n.*" x
+#define ASAN_BRP_MANUAL_ANALYSIS(x) \
+  "MiraclePtr Status: MANUAL ANALYSIS REQUIRED\\n.*" x
+#define ASAN_BRP_NOT_PROTECTED(x) "MiraclePtr Status: NOT PROTECTED\\n.*" x
+
+const char* kAsanBrpProtected_Dereference =
+    ASAN_BRP_PROTECTED("dangling pointer was being dereferenced");
+const char* kAsanBrpMaybeProtected_Extraction = ASAN_BRP_MANUAL_ANALYSIS(
+    "pointer to the same region was extracted from a raw_ptr<T>");
+const char* kAsanBrpNotProtected_Instantiation = ASAN_BRP_NOT_PROTECTED(
+    "pointer to an already freed region was assigned to a raw_ptr<T>");
+const char* kAsanBrpNotProtected_EarlyAllocation = ASAN_BRP_NOT_PROTECTED(
+    "region was allocated before MiraclePtr was activated");
+const char* kAsanBrpNotProtected_NoRawPtrAccess =
+    ASAN_BRP_NOT_PROTECTED("No raw_ptr<T> access to this region was detected");
+
+#undef ASAN_BRP_PROTECTED
+#undef ASAN_BRP_MANUAL_ANALYSIS
+#undef ASAN_BRP_NOT_PROTECTED
+
 TEST(AsanBackupRefPtrImpl, Dereference) {
   if (RawPtrAsanService::GetInstance().mode() !=
       RawPtrAsanService::Mode::kEnabled) {
@@ -1420,13 +1440,13 @@
   delete protected_ptr.get();
 
   EXPECT_DEATH_IF_SUPPORTED((*protected_ptr).x = 1,
-                            "dangling pointer was being dereferenced");
+                            kAsanBrpProtected_Dereference);
   EXPECT_DEATH_IF_SUPPORTED((*protected_ptr).func(),
-                            "dangling pointer was being dereferenced");
+                            kAsanBrpProtected_Dereference);
   EXPECT_DEATH_IF_SUPPORTED(++(protected_ptr->x),
-                            "dangling pointer was being dereferenced");
+                            kAsanBrpProtected_Dereference);
   EXPECT_DEATH_IF_SUPPORTED(protected_ptr->func(),
-                            "dangling pointer was being dereferenced");
+                            kAsanBrpProtected_Dereference);
 }
 
 TEST(AsanBackupRefPtrImpl, Extraction) {
@@ -1452,7 +1472,7 @@
         AsanStruct* ptr2 = protected_ptr;
         ptr2->x = 1;
       },
-      "pointer to the same region was extracted from a raw_ptr<T>");
+      kAsanBrpMaybeProtected_Extraction);
 }
 
 TEST(AsanBackupRefPtrImpl, Instantiation) {
@@ -1475,7 +1495,7 @@
 
   EXPECT_DEATH_IF_SUPPORTED(
       { [[maybe_unused]] raw_ptr<AsanStruct> protected_ptr2 = ptr; },
-      "pointer to an already freed region was assigned to a raw_ptr<T>");
+      kAsanBrpNotProtected_Instantiation);
 }
 
 TEST(AsanBackupRefPtrImpl, InstantiationInvalidPointer) {
@@ -1519,7 +1539,7 @@
   delete ptr;  // Should crash now.
   EXPECT_DEATH_IF_SUPPORTED(
       { [[maybe_unused]] raw_ptr<AsanStruct> protected_ptr2 = ptr; },
-      "pointer to an already freed region was assigned to a raw_ptr<T>");
+      kAsanBrpNotProtected_Instantiation);
 }
 
 TEST(AsanBackupRefPtrImpl, EarlyAllocationDetection) {
@@ -1530,22 +1550,31 @@
     return;
   }
 
-  AsanStruct* ptr1 = new AsanStruct;
+  raw_ptr<AsanStruct> unsafe_ptr = new AsanStruct;
 
   base::RawPtrAsanService::GetInstance().Configure(
       base::EnableDereferenceCheck(true), base::EnableExtractionCheck(true),
       base::EnableInstantiationCheck(true));
 
-  AsanStruct* ptr2 = new AsanStruct;
+  raw_ptr<AsanStruct> safe_ptr = new AsanStruct;
 
-  EXPECT_FALSE(RawPtrAsanService::GetInstance().IsSupportedAllocation(ptr1));
-  EXPECT_TRUE(RawPtrAsanService::GetInstance().IsSupportedAllocation(ptr2));
+  EXPECT_FALSE(
+      RawPtrAsanService::GetInstance().IsSupportedAllocation(unsafe_ptr.get()));
+  EXPECT_TRUE(
+      RawPtrAsanService::GetInstance().IsSupportedAllocation(safe_ptr.get()));
 
-  delete ptr1;
-  delete ptr2;
+  delete safe_ptr.get();
+  delete unsafe_ptr.get();
 
-  EXPECT_FALSE(RawPtrAsanService::GetInstance().IsSupportedAllocation(ptr1));
-  EXPECT_TRUE(RawPtrAsanService::GetInstance().IsSupportedAllocation(ptr2));
+  EXPECT_FALSE(
+      RawPtrAsanService::GetInstance().IsSupportedAllocation(unsafe_ptr.get()));
+  EXPECT_TRUE(
+      RawPtrAsanService::GetInstance().IsSupportedAllocation(safe_ptr.get()));
+
+  EXPECT_DEATH_IF_SUPPORTED({ unsafe_ptr->func(); },
+                            kAsanBrpNotProtected_EarlyAllocation);
+  EXPECT_DEATH_IF_SUPPORTED({ safe_ptr->func(); },
+                            kAsanBrpProtected_Dereference);
 }
 
 #endif  // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
diff --git a/base/system/sys_info.cc b/base/system/sys_info.cc
index 35af9cd..a4c99975 100644
--- a/base/system/sys_info.cc
+++ b/base/system/sys_info.cc
@@ -100,18 +100,15 @@
 #endif
 
 void SysInfo::GetHardwareInfo(base::OnceCallback<void(HardwareInfo)> callback) {
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_APPLE)
-  base::ThreadPool::PostTaskAndReplyWithResult(
-      FROM_HERE, {}, base::BindOnce(&GetHardwareInfoSync), std::move(callback));
-#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
-  base::ThreadPool::PostTaskAndReplyWithResult(
-      FROM_HERE, {base::MayBlock()}, base::BindOnce(&GetHardwareInfoSync),
-      std::move(callback));
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
+  constexpr base::TaskTraits kTraits = {base::MayBlock()};
 #else
-  NOTIMPLEMENTED();
-  base::SequencedTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), HardwareInfo()));
+  constexpr base::TaskTraits kTraits = {};
 #endif
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, kTraits, base::BindOnce(&GetHardwareInfoSync),
+      std::move(callback));
 }
 
 // static
diff --git a/base/test/android/javatests/src/org/chromium/base/test/metrics/HistogramTestRule.java b/base/test/android/javatests/src/org/chromium/base/test/metrics/HistogramTestRule.java
index 51f178a3..dd4e1c4 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/metrics/HistogramTestRule.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/metrics/HistogramTestRule.java
@@ -8,6 +8,7 @@
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
+import org.chromium.base.metrics.NativeUmaRecorderJni;
 import org.chromium.base.metrics.RecordHistogramJni;
 
 /**
@@ -56,7 +57,7 @@
      */
     public int getHistogramValueCount(String name, int sample) {
         assert mSnapShotPtr != 0;
-        return RecordHistogramJni.get().getHistogramValueCountForTesting(
+        return NativeUmaRecorderJni.get().getHistogramValueCountForTesting(
                 name, sample, mSnapShotPtr);
     }
 
@@ -67,6 +68,6 @@
      */
     public int getHistogramTotalCount(String name) {
         assert mSnapShotPtr != 0;
-        return RecordHistogramJni.get().getHistogramTotalCountForTesting(name, mSnapShotPtr);
+        return NativeUmaRecorderJni.get().getHistogramTotalCountForTesting(name, mSnapShotPtr);
     }
 }
diff --git a/base/test/repeating_test_future.h b/base/test/repeating_test_future.h
index 88ce4c5..2ecd391 100644
--- a/base/test/repeating_test_future.h
+++ b/base/test/repeating_test_future.h
@@ -134,8 +134,11 @@
   base::RepeatingCallback<void(CallbackArgumentsTypes...)> GetCallback() {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return base::BindRepeating(
-        &RepeatingTestFuture<Types...>::AddValueFromCallbackArguments<
-            CallbackArgumentsTypes...>,
+        [](WeakPtr<RepeatingTestFuture<Types...>> future,
+           CallbackArgumentsTypes... values) {
+          if (future)
+            future->AddValue(std::forward<CallbackArgumentsTypes>(values)...);
+        },
         weak_ptr_factory_.GetWeakPtr());
   }
 
@@ -207,14 +210,6 @@
     return result;
   }
 
-  // Used by GetCallback() to adapt between the form in which the callback
-  // provides arguments, and the argument types specified to this template.
-  // e.g. callbacks often carry arguments as |const Foo&| rather than |Foo|.
-  template <typename... CallbackArgumentsTypes>
-  void AddValueFromCallbackArguments(CallbackArgumentsTypes... values) {
-    AddValue(std::forward<CallbackArgumentsTypes>(values)...);
-  }
-
   base::queue<TupleType> elements_ GUARDED_BY_CONTEXT(sequence_checker_);
 
   // Used by Wait() to know when AddValue() is called.
diff --git a/base/test/test_future.h b/base/test/test_future.h
index f85be35..135f15f7 100644
--- a/base/test/test_future.h
+++ b/base/test/test_future.h
@@ -150,9 +150,13 @@
   template <typename... CallbackArgumentsTypes>
   base::OnceCallback<void(CallbackArgumentsTypes...)> GetCallback() {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    return base::BindOnce(&TestFuture<Types...>::SetValueFromCallbackArguments<
-                              CallbackArgumentsTypes...>,
-                          weak_ptr_factory_.GetWeakPtr());
+    return base::BindOnce(
+        [](WeakPtr<TestFuture<Types...>> future,
+           CallbackArgumentsTypes... values) {
+          if (future)
+            future->SetValue(std::forward<CallbackArgumentsTypes>(values)...);
+        },
+        weak_ptr_factory_.GetWeakPtr());
   }
 
   base::OnceCallback<void(Types...)> GetCallback() {
@@ -215,14 +219,6 @@
   }
 
  private:
-  // Used by GetCallback() to adapt between the form in which the callback
-  // provides arguments, and the argument types specified to this template.
-  // e.g. callbacks often carry arguments as |const Foo&| rather than |Foo|.
-  template <typename... CallbackArgumentsTypes>
-  void SetValueFromCallbackArguments(CallbackArgumentsTypes... values) {
-    SetValue(std::forward<CallbackArgumentsTypes>(values)...);
-  }
-
   [[nodiscard]] const TupleType& GetTuple() {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     bool success = Wait();
diff --git a/base/trace_event/event_name_filter_unittest.cc b/base/trace_event/event_name_filter_unittest.cc
index a0c34fa..a3c9c87 100644
--- a/base/trace_event/event_name_filter_unittest.cc
+++ b/base/trace_event/event_name_filter_unittest.cc
@@ -5,7 +5,6 @@
 #include "base/trace_event/event_name_filter.h"
 
 #include "base/memory/ptr_util.h"
-#include "base/trace_event/thread_instruction_count.h"
 #include "base/trace_event/trace_event_impl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -14,8 +13,8 @@
 
 const TraceEvent& MakeTraceEvent(const char* name) {
   static TraceEvent event;
-  event.Reset(0, TimeTicks(), ThreadTicks(), ThreadInstructionCount(), 'b',
-              nullptr, name, "", 0, 0, nullptr, 0);
+  event.Reset(0, TimeTicks(), ThreadTicks(), 'b', nullptr, name, "", 0, 0,
+              nullptr, 0);
   return event;
 }
 
diff --git a/base/trace_event/thread_instruction_count.cc b/base/trace_event/thread_instruction_count.cc
deleted file mode 100644
index 0321d6d2..0000000
--- a/base/trace_event/thread_instruction_count.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2019 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 "base/trace_event/thread_instruction_count.h"
-
-#include "base/base_switches.h"
-#include "base/check_op.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/no_destructor.h"
-#include "base/threading/thread_local_storage.h"
-#include "build/build_config.h"
-
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-#include <linux/perf_event.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-
-// Special constants used for counter FD states.
-constexpr int kPerfFdDisabled = -2;
-constexpr int kPerfFdOpenFailed = -1;
-constexpr int kPerfFdUninitialized = 0;
-
-ThreadLocalStorage::Slot& InstructionCounterFdSlot() {
-  static NoDestructor<ThreadLocalStorage::Slot> fd_slot([](void* fd_ptr) {
-    int fd = reinterpret_cast<intptr_t>(fd_ptr);
-    if (fd > kPerfFdUninitialized)
-      close(fd);
-  });
-  return *fd_slot;
-}
-
-// Opens a new file descriptor that emits the value of
-// PERF_COUNT_HW_INSTRUCTIONS in userspace (excluding kernel and hypervisor
-// instructions) for the given |thread_id|, or 0 for the calling thread.
-//
-// Returns kPerfFdOpenFailed if opening the file descriptor failed, or
-// kPerfFdDisabled if performance counters are disabled in the calling process.
-int OpenInstructionCounterFdForThread(int thread_id) {
-  // This switch is only propagated for processes that are unaffected by the
-  // BPF sandbox, such as the browser process or renderers with --no-sandbox.
-  const base::CommandLine& command_line =
-      *base::CommandLine::ForCurrentProcess();
-  if (!command_line.HasSwitch(switches::kEnableThreadInstructionCount))
-    return kPerfFdDisabled;
-
-  struct perf_event_attr pe = {0};
-  pe.type = PERF_TYPE_HARDWARE;
-  pe.size = sizeof(struct perf_event_attr);
-  pe.config = PERF_COUNT_HW_INSTRUCTIONS;
-  pe.exclude_kernel = 1;
-  pe.exclude_hv = 1;
-
-  int fd = syscall(__NR_perf_event_open, &pe, thread_id, /* cpu */ -1,
-                   /* group_fd */ -1, /* flags */ 0);
-  if (fd < 0) {
-    LOG(ERROR) << "perf_event_open failed, omitting instruction counters";
-    return kPerfFdOpenFailed;
-  }
-  return fd;
-}
-
-// Retrieves the active perf counter FD for the current thread, performing
-// lazy-initialization if necessary.
-int InstructionCounterFdForCurrentThread() {
-  auto& slot = InstructionCounterFdSlot();
-  int fd = reinterpret_cast<intptr_t>(slot.Get());
-  if (fd == kPerfFdUninitialized) {
-    fd = OpenInstructionCounterFdForThread(0);
-    slot.Set(reinterpret_cast<void*>(fd));
-  }
-  return fd;
-}
-
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-
-}  // namespace
-
-bool ThreadInstructionCount::IsSupported() {
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-  // If we can't initialize the counter FD, mark as disabled.
-  int counter_fd = InstructionCounterFdForCurrentThread();
-  if (counter_fd <= 0)
-    return false;
-
-  return true;
-#else
-  return false;
-#endif
-}
-
-ThreadInstructionCount ThreadInstructionCount::Now() {
-  DCHECK(IsSupported());
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-  int fd = InstructionCounterFdForCurrentThread();
-  if (fd <= 0)
-    return ThreadInstructionCount();
-
-  uint64_t instructions = 0;
-  ssize_t bytes_read = read(fd, &instructions, sizeof(instructions));
-  CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(instructions)))
-      << "Short reads of small size from kernel memory is not expected. If "
-         "this fails, use HANDLE_EINTR.";
-  return ThreadInstructionCount(instructions);
-#else
-  return ThreadInstructionCount();
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-}
-
-}  // namespace trace_event
-}  // namespace base
diff --git a/base/trace_event/thread_instruction_count.h b/base/trace_event/thread_instruction_count.h
deleted file mode 100644
index e515f8e..0000000
--- a/base/trace_event/thread_instruction_count.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2019 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 BASE_TRACE_EVENT_THREAD_INSTRUCTION_COUNT_H_
-#define BASE_TRACE_EVENT_THREAD_INSTRUCTION_COUNT_H_
-
-#include <stdint.h>
-
-#include "base/base_export.h"
-
-namespace base {
-namespace trace_event {
-
-// Represents the number of instructions that were retired between two samples
-// of a thread's performance counters.
-class BASE_EXPORT ThreadInstructionDelta {
- public:
-  constexpr ThreadInstructionDelta() : delta_(0) {}
-  explicit constexpr ThreadInstructionDelta(int64_t delta) : delta_(delta) {}
-
-  constexpr int64_t ToInternalValue() const { return delta_; }
-
- private:
-  int64_t delta_;
-};
-
-// Uses the system's performance counters in order to measure the number of
-// instructions that have been retired on the current thread.
-class BASE_EXPORT ThreadInstructionCount {
- public:
-  // Returns true if the platform supports hardware retired instruction
-  // counters.
-  static bool IsSupported();
-
-  // Returns the number of retired instructions relative to some epoch count,
-  // or -1 if getting the current instruction count failed / is disabled.
-  static ThreadInstructionCount Now();
-
-  constexpr ThreadInstructionCount() : value_(-1) {}
-  explicit constexpr ThreadInstructionCount(int64_t value) : value_(value) {}
-
-  constexpr bool is_null() const { return value_ == -1; }
-
-  constexpr ThreadInstructionDelta operator-(
-      ThreadInstructionCount other) const {
-    return ThreadInstructionDelta(value_ - other.value_);
-  }
-
-  constexpr int64_t ToInternalValue() const { return value_; }
-
- private:
-  int64_t value_;
-};
-
-}  // namespace trace_event
-}  // namespace base
-
-#endif  // BASE_TRACE_EVENT_THREAD_INSTRUCTION_COUNT_H_
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index d94d9ec..8e25a3d 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -23,7 +23,6 @@
 #include "base/time/time_override.h"
 #include "base/trace_event/builtin_categories.h"
 #include "base/trace_event/common/trace_event_common.h"
-#include "base/trace_event/thread_instruction_count.h"
 #include "base/trace_event/trace_arguments.h"
 #include "base/trace_event/trace_category.h"
 #include "base/trace_event/trace_log.h"
@@ -578,15 +577,14 @@
                          const char* name,
                          base::trace_event::TraceEventHandle handle);
 
-void BASE_EXPORT UpdateTraceEventDurationExplicit(
-    const unsigned char* category_group_enabled,
-    const char* name,
-    base::trace_event::TraceEventHandle handle,
-    base::PlatformThreadId thread_id,
-    bool explicit_timestamps,
-    const base::TimeTicks& now,
-    const base::ThreadTicks& thread_now,
-    base::trace_event::ThreadInstructionCount thread_instruction_now);
+void BASE_EXPORT
+UpdateTraceEventDurationExplicit(const unsigned char* category_group_enabled,
+                                 const char* name,
+                                 base::trace_event::TraceEventHandle handle,
+                                 base::PlatformThreadId thread_id,
+                                 bool explicit_timestamps,
+                                 const base::TimeTicks& now,
+                                 const base::ThreadTicks& thread_now);
 
 // These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template
 // functions are defined here instead of in the macro, because the arg_values
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 032ae7b..5d9aec8 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -85,7 +85,6 @@
 TraceEvent::TraceEvent(PlatformThreadId thread_id,
                        TimeTicks timestamp,
                        ThreadTicks thread_timestamp,
-                       ThreadInstructionCount thread_instruction_count,
                        char phase,
                        const unsigned char* category_group_enabled,
                        const char* name,
@@ -96,7 +95,6 @@
                        unsigned int flags)
     : timestamp_(timestamp),
       thread_timestamp_(thread_timestamp),
-      thread_instruction_count_(thread_instruction_count),
       scope_(scope),
       id_(id),
       category_group_enabled_(category_group_enabled),
@@ -117,7 +115,6 @@
   // Only reset fields that won't be initialized in Reset(int, ...), or that may
   // hold references to other objects.
   duration_ = TimeDelta::FromInternalValue(-1);
-  thread_instruction_delta_ = ThreadInstructionDelta();
   args_.Reset();
   parameter_copy_storage_.Reset();
 }
@@ -125,7 +122,6 @@
 void TraceEvent::Reset(PlatformThreadId thread_id,
                        TimeTicks timestamp,
                        ThreadTicks thread_timestamp,
-                       ThreadInstructionCount thread_instruction_count,
                        char phase,
                        const unsigned char* category_group_enabled,
                        const char* name,
@@ -144,7 +140,6 @@
   thread_id_ = thread_id;
   flags_ = flags;
   bind_id_ = bind_id;
-  thread_instruction_count_ = thread_instruction_count;
   phase_ = phase;
 
   InitArgs(args);
@@ -158,8 +153,7 @@
 }
 
 void TraceEvent::UpdateDuration(const TimeTicks& now,
-                                const ThreadTicks& thread_now,
-                                ThreadInstructionCount thread_instruction_now) {
+                                const ThreadTicks& thread_now) {
   DCHECK_EQ(duration_.ToInternalValue(), -1);
   duration_ = now - timestamp_;
 
@@ -167,11 +161,6 @@
   // initialized when it was recorded.
   if (thread_timestamp_ != ThreadTicks())
     thread_duration_ = thread_now - thread_timestamp_;
-
-  if (!thread_instruction_count_.is_null()) {
-    thread_instruction_delta_ =
-        thread_instruction_now - thread_instruction_count_;
-  }
 }
 
 void TraceEvent::EstimateTraceMemoryOverhead(
@@ -254,10 +243,6 @@
       if (thread_duration != -1)
         StringAppendF(out, ",\"tdur\":%" PRId64, thread_duration);
     }
-    if (!thread_instruction_count_.is_null()) {
-      int64_t thread_instructions = thread_instruction_delta_.ToInternalValue();
-      StringAppendF(out, ",\"tidelta\":%" PRId64, thread_instructions);
-    }
   }
 
   // Output tts if thread_timestamp is valid.
@@ -266,12 +251,6 @@
     StringAppendF(out, ",\"tts\":%" PRId64, thread_time_int64);
   }
 
-  // Output ticount if thread_instruction_count is valid.
-  if (!thread_instruction_count_.is_null()) {
-    int64_t thread_instructions = thread_instruction_count_.ToInternalValue();
-    StringAppendF(out, ",\"ticount\":%" PRId64, thread_instructions);
-  }
-
   // Output async tts marker field if flag is set.
   if (flags_ & TRACE_EVENT_FLAG_ASYNC_TTS) {
     StringAppendF(out, ", \"use_async_tts\":1");
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index 98116388b..d495a65 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -18,7 +18,6 @@
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
 #include "base/trace_event/common/trace_event_common.h"
-#include "base/trace_event/thread_instruction_count.h"
 #include "base/trace_event/trace_arguments.h"
 #include "base/trace_event/trace_event_memory_overhead.h"
 #include "build/build_config.h"
@@ -56,7 +55,6 @@
   TraceEvent(PlatformThreadId thread_id,
              TimeTicks timestamp,
              ThreadTicks thread_timestamp,
-             ThreadInstructionCount thread_instruction_count,
              char phase,
              const unsigned char* category_group_enabled,
              const char* name,
@@ -87,7 +85,6 @@
   void Reset(PlatformThreadId thread_id,
              TimeTicks timestamp,
              ThreadTicks thread_timestamp,
-             ThreadInstructionCount thread_instruction_count,
              char phase,
              const unsigned char* category_group_enabled,
              const char* name,
@@ -97,9 +94,7 @@
              TraceArguments* args,
              unsigned int flags);
 
-  void UpdateDuration(const TimeTicks& now,
-                      const ThreadTicks& thread_now,
-                      ThreadInstructionCount thread_instruction_now);
+  void UpdateDuration(const TimeTicks& now, const ThreadTicks& thread_now);
 
   void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
 
@@ -111,17 +106,11 @@
 
   TimeTicks timestamp() const { return timestamp_; }
   ThreadTicks thread_timestamp() const { return thread_timestamp_; }
-  ThreadInstructionCount thread_instruction_count() const {
-    return thread_instruction_count_;
-  }
   char phase() const { return phase_; }
   PlatformThreadId thread_id() const { return thread_id_; }
   ProcessId process_id() const { return process_id_; }
   TimeDelta duration() const { return duration_; }
   TimeDelta thread_duration() const { return thread_duration_; }
-  ThreadInstructionDelta thread_instruction_delta() const {
-    return thread_instruction_delta_;
-  }
   const char* scope() const { return scope_; }
   unsigned long long id() const { return id_; }
   unsigned int flags() const { return flags_; }
@@ -163,8 +152,6 @@
   ThreadTicks thread_timestamp_ = ThreadTicks();
   TimeDelta duration_ = TimeDelta::FromInternalValue(-1);
   TimeDelta thread_duration_ = TimeDelta();
-  ThreadInstructionCount thread_instruction_count_ = ThreadInstructionCount();
-  ThreadInstructionDelta thread_instruction_delta_ = ThreadInstructionDelta();
   // scope_ and id_ can be used to store phase-specific data.
   // The following should be default-initialized to the expression
   // trace_event_internal::kGlobalScope, which is nullptr, but its definition
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc
index 9f8851c..8b9d23f 100644
--- a/base/trace_event/trace_event_unittest.cc
+++ b/base/trace_event/trace_event_unittest.cc
@@ -1401,35 +1401,13 @@
             TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name1",
             trace_event_internal::kGlobalScope, trace_event_internal::kNoId, 0,
             trace_event_internal::kNoId, "arg1", "argval", "arg2", "argval");
-    // Test that static TRACE_STR_COPY NULL string arguments are not copied.
-    const char* str1 = nullptr;
-    const char* str2 = nullptr;
-#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
-    // DynamicString{nullptr} is not supported in perfetto for debug-args-value.
-    // After reverting the definition of `TRACE_STR_COPY` to nop, this
-    // difference in perfetto vs non-perfetto won't be required here.
-    [[maybe_unused]] TraceEventHandle handle2 =
-        trace_event_internal::AddTraceEvent(
-            TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name2",
-            trace_event_internal::kGlobalScope, trace_event_internal::kNoId, 0,
-            trace_event_internal::kNoId, "arg1", str1, "arg2", str2);
-#else
-    [[maybe_unused]] TraceEventHandle handle2 =
-        trace_event_internal::AddTraceEvent(
-            TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name2",
-            trace_event_internal::kGlobalScope, trace_event_internal::kNoId, 0,
-            trace_event_internal::kNoId, "arg1", TRACE_STR_COPY(str1), "arg2",
-            TRACE_STR_COPY(str2));
+#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
     EXPECT_GT(tracer->GetStatus().event_count, 1u);
     const TraceEvent* event1 = tracer->GetEventByHandle(handle1);
-    const TraceEvent* event2 = tracer->GetEventByHandle(handle2);
     ASSERT_TRUE(event1);
-    ASSERT_TRUE(event2);
     EXPECT_STREQ("name1", event1->name());
-    EXPECT_STREQ("name2", event2->name());
     EXPECT_TRUE(event1->parameter_copy_storage().empty());
-    EXPECT_TRUE(event2->parameter_copy_storage().empty());
-#endif  // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
+#endif
     EndTraceAndFlush();
   }
 }
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index baad0f0..f9f27c1 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -45,7 +45,6 @@
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/memory_dump_provider.h"
 #include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/thread_instruction_count.h"
 #include "base/trace_event/trace_buffer.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
@@ -122,11 +121,6 @@
              : ThreadTicks();
 }
 
-ThreadInstructionCount ThreadInstructionNow() {
-  return ThreadInstructionCount::IsSupported() ? ThreadInstructionCount::Now()
-                                               : ThreadInstructionCount();
-}
-
 template <typename T>
 void InitializeMetadataEvent(TraceEvent* trace_event,
                              PlatformThreadId thread_id,
@@ -139,10 +133,8 @@
   TraceArguments args(arg_name, value);
   base::TimeTicks now = TRACE_TIME_TICKS_NOW();
   ThreadTicks thread_now;
-  ThreadInstructionCount thread_instruction_count;
   trace_event->Reset(
-      thread_id, now, thread_now, thread_instruction_count,
-      TRACE_EVENT_PHASE_METADATA,
+      thread_id, now, thread_now, TRACE_EVENT_PHASE_METADATA,
       TraceLog::GetInstance()->GetCategoryGroupEnabled("__metadata"),
       metadata_name,
       trace_event_internal::kGlobalScope,  // scope
@@ -371,8 +363,7 @@
     PlatformThreadId thread_id,
     bool explicit_timestamps,
     const TimeTicks& now,
-    const ThreadTicks& thread_now,
-    ThreadInstructionCount thread_instruction_now) {
+    const ThreadTicks& thread_now) {
   perfetto::DynamicCategory category(
       TraceLog::GetInstance()->GetCategoryGroupName(category_group_enabled));
   auto phase = TRACE_EVENT_PHASE_END;
@@ -1844,16 +1835,6 @@
     bind_id = MangleEventId(bind_id);
 
   TimeTicks offset_event_timestamp = OffsetTimestamp(timestamp);
-  ThreadInstructionCount thread_instruction_now;
-  // If timestamp is provided explicitly, don't record thread instruction count
-  // as it would be for the wrong timestamp. Similarly, if we record an event
-  // for another process or thread, we shouldn't report the current thread's
-  // thread time.
-  if (!(flags & TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP ||
-        flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID ||
-        thread_id != PlatformThread::CurrentId())) {
-    thread_instruction_now = ThreadInstructionNow();
-  }
 
   ThreadLocalEventBuffer* thread_local_event_buffer = nullptr;
   if (*category_group_enabled & RECORDING_MODE) {
@@ -1867,10 +1848,9 @@
     auto trace_event_override =
         add_trace_event_override_.load(std::memory_order_relaxed);
     if (trace_event_override) {
-      TraceEvent new_trace_event(thread_id, offset_event_timestamp,
-                                 thread_timestamp, thread_instruction_now,
-                                 phase, category_group_enabled, name, scope, id,
-                                 bind_id, args, flags);
+      TraceEvent new_trace_event(
+          thread_id, offset_event_timestamp, thread_timestamp, phase,
+          category_group_enabled, name, scope, id, bind_id, args, flags);
 
       trace_event_override(
           &new_trace_event,
@@ -1884,9 +1864,8 @@
   bool disabled_by_filters = false;
   if (*category_group_enabled & TraceCategory::ENABLED_FOR_FILTERING) {
     auto new_trace_event = std::make_unique<TraceEvent>(
-        thread_id, offset_event_timestamp, thread_timestamp,
-        thread_instruction_now, phase, category_group_enabled, name, scope, id,
-        bind_id, args, flags);
+        thread_id, offset_event_timestamp, thread_timestamp, phase,
+        category_group_enabled, name, scope, id, bind_id, args, flags);
 
     disabled_by_filters = true;
     ForEachCategoryFilter(
@@ -1919,9 +1898,8 @@
         *trace_event = std::move(*filtered_trace_event);
       } else {
         trace_event->Reset(thread_id, offset_event_timestamp, thread_timestamp,
-                           thread_instruction_now, phase,
-                           category_group_enabled, name, scope, id, bind_id,
-                           args, flags);
+                           phase, category_group_enabled, name, scope, id,
+                           bind_id, args, flags);
       }
 
 #if BUILDFLAG(IS_ANDROID)
@@ -1950,11 +1928,10 @@
   auto thread_id = base::PlatformThread::CurrentId();
   ThreadTicks thread_now = ThreadNow();
   TimeTicks now = OffsetNow();
-  ThreadInstructionCount thread_instruction_now = ThreadInstructionNow();
   AutoLock lock(lock_);
   auto trace_event = std::make_unique<TraceEvent>(
-      thread_id, now, thread_now, thread_instruction_now,
-      TRACE_EVENT_PHASE_METADATA, category_group_enabled, name,
+      thread_id, now, thread_now, TRACE_EVENT_PHASE_METADATA,
+      category_group_enabled, name,
       trace_event_internal::kGlobalScope,  // scope
       trace_event_internal::kNoId,         // id
       trace_event_internal::kNoId,         // bind_id
@@ -2031,10 +2008,9 @@
   if (!*category_group_enabled)
     return;
 
-  UpdateTraceEventDurationExplicit(category_group_enabled, name, handle,
-                                   base::PlatformThread::CurrentId(),
-                                   /*explicit_timestamps=*/false, OffsetNow(),
-                                   ThreadNow(), ThreadInstructionNow());
+  UpdateTraceEventDurationExplicit(
+      category_group_enabled, name, handle, base::PlatformThread::CurrentId(),
+      /*explicit_timestamps=*/false, OffsetNow(), ThreadNow());
 }
 
 void TraceLog::UpdateTraceEventDurationExplicit(
@@ -2044,8 +2020,7 @@
     PlatformThreadId thread_id,
     bool explicit_timestamps,
     const TimeTicks& now,
-    const ThreadTicks& thread_now,
-    ThreadInstructionCount thread_instruction_now) {
+    const ThreadTicks& thread_now) {
   if (!*category_group_enabled)
     return;
 
@@ -2067,8 +2042,7 @@
         update_duration_override_.load(std::memory_order_relaxed);
     if (update_duration_override) {
       update_duration_override(category_group_enabled, name, handle, thread_id,
-                               explicit_timestamps, now, thread_now,
-                               thread_instruction_now);
+                               explicit_timestamps, now, thread_now);
       return;
     }
   }
@@ -2081,7 +2055,7 @@
     if (trace_event) {
       DCHECK(trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE);
 
-      trace_event->UpdateDuration(now, thread_now, thread_instruction_now);
+      trace_event->UpdateDuration(now, thread_now);
 #if BUILDFLAG(IS_ANDROID)
       trace_event->SendToATrace();
 #endif
@@ -2501,12 +2475,11 @@
     base::PlatformThreadId thread_id,
     bool explicit_timestamps,
     const base::TimeTicks& now,
-    const base::ThreadTicks& thread_now,
-    base::trace_event::ThreadInstructionCount thread_instruction_now) {
+    const base::ThreadTicks& thread_now) {
   return base::trace_event::TraceLog::GetInstance()
       ->UpdateTraceEventDurationExplicit(category_group_enabled, name, handle,
                                          thread_id, explicit_timestamps, now,
-                                         thread_now, thread_instruction_now);
+                                         thread_now);
 }
 
 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h
index 7fe2528..c0566ab 100644
--- a/base/trace_event/trace_log.h
+++ b/base/trace_event/trace_log.h
@@ -258,8 +258,7 @@
                PlatformThreadId thread_id,
                bool explicit_timestamps,
                const TimeTicks& now,
-               const ThreadTicks& thread_now,
-               ThreadInstructionCount thread_instruction_now);
+               const ThreadTicks& thread_now);
   // The callbacks will be called up until the point where the flush is
   // finished, i.e. must be callable until OutputCallback is called with
   // has_more_events==false.
@@ -368,8 +367,7 @@
       PlatformThreadId thread_id,
       bool explicit_timestamps,
       const TimeTicks& now,
-      const ThreadTicks& thread_now,
-      ThreadInstructionCount thread_instruction_now);
+      const ThreadTicks& thread_now);
 
   void EndFilteredEvent(const unsigned char* category_group_enabled,
                         const char* name,
diff --git a/base/trace_event/typed_macros_internal.cc b/base/trace_event/typed_macros_internal.cc
index 4e1fdaf0..886251a 100644
--- a/base/trace_event/typed_macros_internal.cc
+++ b/base/trace_event/typed_macros_internal.cc
@@ -6,7 +6,6 @@
 
 #include "base/notreached.h"
 #include "base/time/time.h"
-#include "base/trace_event/thread_instruction_count.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/typed_macros.h"
 
@@ -18,12 +17,6 @@
              : base::ThreadTicks();
 }
 
-base::trace_event::ThreadInstructionCount ThreadInstructionNow() {
-  return base::trace_event::ThreadInstructionCount::IsSupported()
-             ? base::trace_event::ThreadInstructionCount::Now()
-             : base::trace_event::ThreadInstructionCount();
-}
-
 base::trace_event::PrepareTrackEventFunction g_typed_event_callback = nullptr;
 base::trace_event::PrepareTracePacketFunction g_trace_packet_callback = nullptr;
 base::trace_event::EmitEmptyTracePacketFunction g_empty_packet_callback =
@@ -165,16 +158,14 @@
   // Only emit thread time / instruction count for events on the default track
   // without explicit timestamp.
   base::ThreadTicks thread_now;
-  base::trace_event::ThreadInstructionCount thread_instruction_now;
   if ((flags & TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP) == 0 && !explicit_track) {
     thread_now = ThreadNow();
-    thread_instruction_now = ThreadInstructionNow();
   }
 
   base::trace_event::TraceEvent event(
-      thread_id, ts, thread_now, thread_instruction_now, phase,
-      category_group_enabled, name.value, trace_event_internal::kGlobalScope,
-      trace_event_internal::kNoId, trace_event_internal::kNoId, nullptr, flags);
+      thread_id, ts, thread_now, phase, category_group_enabled, name.value,
+      trace_event_internal::kGlobalScope, trace_event_internal::kNoId,
+      trace_event_internal::kNoId, nullptr, flags);
 
   return g_typed_event_callback(&event);
 }
diff --git a/base/values.cc b/base/values.cc
index 09f92b0..9916ccde 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -8,7 +8,7 @@
 // build time. Try not to raise this limit unless absolutely necessary. See
 // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
 #ifndef NACL_TC_REV
-#pragma clang max_tokens_here 460000
+#pragma clang max_tokens_here 470000
 #endif
 
 #include <algorithm>
diff --git a/base/win/scoped_process_information_unittest.cc b/base/win/scoped_process_information_unittest.cc
index 92e108f..32c6ef38 100644
--- a/base/win/scoped_process_information_unittest.cc
+++ b/base/win/scoped_process_information_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/process/process.h"
 #include "base/strings/string_util.h"
 #include "base/test/multiprocess_test.h"
+#include "base/win/windows_version.h"
 #include "testing/multiprocess_func_list.h"
 
 namespace {
@@ -123,13 +124,11 @@
   EXPECT_FALSE(process_info.IsValid());
 }
 
-// Disabled due to flakiness on Windows builds. http://crbug.com/1337165
-#if BUILDFLAG(IS_WIN)
-#define MAYBE_Duplicate DISABLED_Duplicate
-#else
-#define MAYBE_Duplicate Duplicate
-#endif
-TEST_F(ScopedProcessInformationTest, MAYBE_Duplicate) {
+TEST_F(ScopedProcessInformationTest, Duplicate) {
+  if (base::win::GetVersion() <= base::win::Version::WIN7) {
+    // Disabled on Windows 7 due to flakiness. https://crbug.com/1336879
+    GTEST_SKIP();
+  }
   PROCESS_INFORMATION temp_process_information;
   DoCreateProcess("ReturnSeven", &temp_process_information);
   base::win::ScopedProcessInformation process_info;
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn
index 716deb7..22c07588 100644
--- a/build/android/BUILD.gn
+++ b/build/android/BUILD.gn
@@ -120,24 +120,38 @@
   deps = [ ":apk_installer_data" ]
 }
 
-python_library("test_runner_py") {
+group("test_runner_py") {
+  testonly = true
+  deps = [
+    ":test_runner_core_py",
+    ":test_runner_device_support",
+  ]
+}
+
+python_library("test_runner_core_py") {
   testonly = true
   pydeps_file = "test_runner.pydeps"
   data = [
     "pylib/gtest/filter/",
     "pylib/instrumentation/render_test.html.jinja",
     "test_wrapper/logdog_wrapper.py",
+    "//third_party/requests/",
+  ]
+  data_deps = [ ":logdog_wrapper_py" ]
+}
+
+group("test_runner_device_support") {
+  testonly = true
+  data = [
     "${android_sdk_build_tools}/aapt",
     "${android_sdk_build_tools}/dexdump",
     "${android_sdk_build_tools}/lib64/libc++.so",
     "${android_sdk_build_tools}/split-select",
     "${android_sdk_root}/platform-tools/adb",
-    "//third_party/requests/",
   ]
   data_deps = [
     ":apk_installer_data",
     ":devil_chromium_py",
-    ":logdog_wrapper_py",
     ":stack_tools",
   ]
 
@@ -152,7 +166,7 @@
 
   # Proguard is needed only when using apks (rather than native executables).
   if (enable_java_templates) {
-    deps = [ "//build/android/stacktrace:java_deobfuscate" ]
+    data_deps += [ "//build/android/stacktrace:java_deobfuscate" ]
   }
 }
 
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index f05a02c..d726e32 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -48,31 +48,35 @@
 
 # All _java_resource_types targets must conform to these patterns.
 java_resource_patterns = [
-  "*:*_assets",
+  "*_assets",
+  "*_grd",
+  "*_java_strings",
+  "*locale_paks",
+  "*_resources",
+  "*strings_java",
   "*android*:assets",
   "*:*_apk_*resources",
   "*android*:resources",
-  "*:*_resources",
-  "*:*_grd",
-  "*:*locale_paks",
-  "*:*_java_strings",
-  "*:*strings_java",
 ]
 
 # All _java_library_types targets must conform to these patterns. This includes
 # all non-leaf targets that use java_library_impl.
 java_library_patterns = [
-  "*:*_java",
-  "*:*_javalib",
-  "*:*_java_*",  # e.g. chrome_java_test_support
+  "*_java",
+  "*_javalib",
+  "*javatests",
+  "*_bundle_module",
+  "*:*_java_*",  # E.g. chrome_java_test_support
   "*:java",
+  "*/java",  # to allow filtering without expanding labels //a/java ->
+             # //a/java:java
   "*:junit",
+  "*/junit",
   "*:junit_*",
   "*:*_junit_*",
-  "*:*javatests",
-  "*:*_bundle_module",
 
-  # TODO(agrieve): Rename targets below to match above patterns.
+  # TODO(agrieve): Rename to glue_java
+  "//android_webview/glue",
   "//android_webview/glue:glue",
 ]
 
@@ -734,9 +738,12 @@
       deps = invoker.deps
     }
     data_deps = [
-      "//build/android:test_runner_py",
+      "//build/android:test_runner_core_py",
       "//testing:test_scripts_shared",
     ]
+    if (_test_type != "junit") {
+      data_deps += [ "//build/android:test_runner_device_support" ]
+    }
     if (defined(invoker.data_deps)) {
       data_deps += invoker.data_deps
     }
@@ -1001,6 +1008,8 @@
             filter_exclude(filter_include(invoker.deps, java_library_patterns),
                            java_resource_patterns)
         foreach(_lib_dep, _lib_deps) {
+          # Expand //foo/java -> //foo/java:java
+          _lib_dep = get_label_info(_lib_dep, "label_no_toolchain")
           deps += [
             "${_lib_dep}__assetres",
             "${_lib_dep}__header",
@@ -3458,6 +3467,9 @@
       _java_header_deps = []
       _java_impl_deps = []
       foreach(_lib_dep, _lib_deps) {
+        # Expand //foo/java -> //foo/java:java
+        _lib_dep = get_label_info(_lib_dep, "label_no_toolchain")
+
         # This is a java library dep, so it has header and impl targets.
         _java_header_deps += [ "${_lib_dep}__header" ]
         _java_impl_deps += [ "${_lib_dep}__impl" ]
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 10a0f30..6228259 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1105,6 +1105,8 @@
       # Depend on non-library deps and on __assetres subtargets of library deps.
       deps = filter_exclude(_deps, _lib_deps)
       foreach(_lib_dep, _lib_deps) {
+        # Expand //foo/java -> //foo/java:java
+        _lib_dep = get_label_info(_lib_dep, "label_no_toolchain")
         deps += [ "${_lib_dep}__assetres" ]
       }
 
@@ -1671,6 +1673,8 @@
                            java_resource_patterns)
         _other_deps = filter_exclude(invoker.deps, _lib_deps)
         foreach(_lib_dep, _lib_deps) {
+          # Expand //foo/java -> //foo/java:java
+          _lib_dep = get_label_info(_lib_dep, "label_no_toolchain")
           deps += [ "${_lib_dep}__header" ]
         }
         deps += _other_deps
diff --git a/build/config/c++/BUILD.gn b/build/config/c++/BUILD.gn
index a67ae4bf..2e5843b 100644
--- a/build/config/c++/BUILD.gn
+++ b/build/config/c++/BUILD.gn
@@ -87,13 +87,8 @@
     assert(!export_libcxxabi_from_executables,
            "Don't use libcxxabi on Windows.")
 
-    if (is_clang) {
-      cflags_cc +=
-          [ "-imsvc" + rebase_path("$libcxx_prefix/include", root_build_dir) ]
-    } else {
-      cflags_cc +=
-          [ "-I" + rebase_path("$libcxx_prefix/include", root_build_dir) ]
-    }
+    cflags_cc +=
+        [ "-I" + rebase_path("$libcxx_prefix/include", root_build_dir) ]
 
     # Prevent libc++ from embedding linker flags to try to automatically link
     # against its runtime library. This is unnecessary with our build system,
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 6c9b73d..f0a9a086 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1176,13 +1176,11 @@
         ldflags += [ "-m64" ]
       }
     } else if (current_cpu == "riscv64") {
-      cflags += [
-        "-mabi=lp64d",
-        "--target=riscv64-linux-gnu",
-      ]
-      ldflags += [
-        "--target=riscv64-linux-gnu",
-      ]
+      if (is_clang) {
+        cflags += [ "--target=riscv64-linux-gnu" ]
+        ldflags += [ "--target=riscv64-linux-gnu" ]
+      }
+      cflags += [ "-mabi=lp64d" ]
     } else if (current_cpu == "s390x") {
       cflags += [ "-m64" ]
       ldflags += [ "-m64" ]
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index 7aece04..5550eec 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -84,9 +84,13 @@
   # Use it by default on official-optimized android and Chrome OS builds, but
   # not ARC or linux-chromeos since it's been seen to not play nicely with
   # Chrome's clang. crbug.com/1033839
+  # Disabled in iOS cronet builds since build step cronet_static_complete
+  # wants to build a .a file consumable by external clients, and they won't
+  # have the same LLVM revisions as us, making bitcode useless to them.
   use_thin_lto =
       is_cfi || (is_clang && is_official_build && chrome_pgo_phase != 1 &&
-                 (is_linux || is_win || is_mac || (is_ios && use_lld) ||
+                 (is_linux || is_win || is_mac ||
+                  (is_ios && use_lld && !is_cronet_build) ||
                   (is_android && target_os != "chromeos") ||
                   (is_chromeos && is_chromeos_device)))
 
diff --git a/build/config/fuchsia/test/README.md b/build/config/fuchsia/test/README.md
index a083229..6402a27 100644
--- a/build/config/fuchsia/test/README.md
+++ b/build/config/fuchsia/test/README.md
@@ -47,8 +47,11 @@
 https://fuchsia.dev/reference/fidl/fuchsia.web#ContextFeatureFlags.
 Any test-specific exceptions are documented for each file.
 
-#### audio_capabilities.test-cmx
-Corresponds to the `AUDIO` flag. Required for enabling audio input and output.
+#### audio_output.shard.test-cml
+Required by tests that need to enable audio output.
+
+#### platform_video_codecs.shard.test-cml
+Required by tests that need accelerated (e.g., hardware) video codecs.
 
 #### network.shard.test-cml
 For tests that need access to network services, including those that access a
diff --git a/build/config/fuchsia/test/audio_output.shard.test-cml b/build/config/fuchsia/test/audio_output.shard.test-cml
new file mode 100644
index 0000000..d46822a
--- /dev/null
+++ b/build/config/fuchsia/test/audio_output.shard.test-cml
@@ -0,0 +1,10 @@
+{
+  use: [
+    {
+      protocol: [
+        "fuchsia.media.Audio",
+        "fuchsia.media.AudioDeviceEnumerator",
+      ]
+    },
+  ],
+}
diff --git a/build/config/fuchsia/test/minimum.shard.test-cml b/build/config/fuchsia/test/minimum.shard.test-cml
index e0887367..1e42fbb3 100644
--- a/build/config/fuchsia/test/minimum.shard.test-cml
+++ b/build/config/fuchsia/test/minimum.shard.test-cml
@@ -61,7 +61,7 @@
         "fuchsia.hwinfo.Product",
         "fuchsia.media.ProfileProvider",
         "fuchsia.process.Launcher",
-        "fuchsia.sys.Loader",
+        "fuchsia.sys.Loader"
       ],
     },
   ],
diff --git a/build/config/fuchsia/test/platform_video_codecs.shard.test-cml b/build/config/fuchsia/test/platform_video_codecs.shard.test-cml
new file mode 100644
index 0000000..3935e0f
--- /dev/null
+++ b/build/config/fuchsia/test/platform_video_codecs.shard.test-cml
@@ -0,0 +1,9 @@
+{
+  use: [
+    {
+      protocol: [
+        "fuchsia.mediacodec.CodecFactory",
+      ]
+    },
+  ],
+}
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 48e7aff..3b726a8 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-8.20220621.3.1
+8.20220623.0.1
diff --git a/build/fuchsia/test/PRESUBMIT.py b/build/fuchsia/test/PRESUBMIT.py
index cba0965a..5e3cc9f 100644
--- a/build/fuchsia/test/PRESUBMIT.py
+++ b/build/fuchsia/test/PRESUBMIT.py
@@ -12,11 +12,30 @@
 
 # pylint: disable=invalid-name,missing-function-docstring
 def CommonChecks(input_api, output_api):
-    pylint_checks = input_api.canned_checks.GetPylint(input_api,
-                                                      output_api,
-                                                      pylintrc='pylintrc',
-                                                      version='2.7')
-    return input_api.RunTests(pylint_checks)
+    presubmit_dir = input_api.PresubmitLocalPath()
+
+    def J(*dirs):
+        """Returns a path relative to presubmit directory."""
+
+        return input_api.os_path.join(presubmit_dir, *dirs)
+
+    tests = []
+    unit_tests = [
+        J('publish_package_unittests.py'),
+    ]
+
+    tests.extend(
+        input_api.canned_checks.GetPylint(input_api,
+                                          output_api,
+                                          pylintrc='pylintrc',
+                                          version='2.7'))
+    tests.extend(
+        input_api.canned_checks.GetUnitTests(input_api,
+                                             output_api,
+                                             unit_tests=unit_tests,
+                                             run_on_python2=False,
+                                             run_on_python3=True))
+    return input_api.RunTests(tests)
 
 
 def CheckChangeOnUpload(input_api, output_api):
diff --git a/build/fuchsia/test/common.py b/build/fuchsia/test/common.py
index d70fac1..abccff6 100644
--- a/build/fuchsia/test/common.py
+++ b/build/fuchsia/test/common.py
@@ -14,7 +14,7 @@
 
 DIR_SRC_ROOT = os.path.abspath(
     os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir))
-REPO_ALIAS = 'chromium-test-package-server'
+REPO_ALIAS = 'fuchsia.com'
 SDK_ROOT = os.path.join(DIR_SRC_ROOT, 'third_party', 'fuchsia-sdk', 'sdk')
 
 
diff --git a/build/fuchsia/test/compatible_utils.py b/build/fuchsia/test/compatible_utils.py
new file mode 100644
index 0000000..bb5fb4f
--- /dev/null
+++ b/build/fuchsia/test/compatible_utils.py
@@ -0,0 +1,17 @@
+# 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.
+"""Functions used in both v1 and v2 scripts."""
+
+_FILTER_DIR = 'testing/buildbot/filters'
+
+
+# TODO(crbug.com/1279803): Until one can send files to the device when running
+# a test, filter files must be read from the test package.
+def map_filter_file_to_package_file(filter_file: str) -> str:
+    """Returns the path to |filter_file| within the test component's package."""
+
+    if not _FILTER_DIR in filter_file:
+        raise ValueError('CFv2 tests only support registered filter files '
+                         'present in the test package')
+    return '/pkg/' + filter_file[filter_file.index(_FILTER_DIR):]
diff --git a/build/fuchsia/test/publish_package.py b/build/fuchsia/test/publish_package.py
index d5cf012..a29457b 100755
--- a/build/fuchsia/test/publish_package.py
+++ b/build/fuchsia/test/publish_package.py
@@ -9,12 +9,16 @@
 import subprocess
 import sys
 
+from typing import Iterable
+
 from common import SDK_TOOLS_DIR
 
 _pm_tool = os.path.join(SDK_TOOLS_DIR, 'pm')
 
 
-def publish_packages(packages, repo: str, new_repo: bool = False) -> None:
+def publish_packages(packages: Iterable[str],
+                     repo: str,
+                     new_repo: bool = False) -> None:
     """Publish packages to a repo directory, initializing it if necessary."""
     if new_repo:
         subprocess.run([_pm_tool, 'newrepo', '-repo', repo], check=True)
diff --git a/build/fuchsia/test/publish_package_unittests.py b/build/fuchsia/test/publish_package_unittests.py
new file mode 100755
index 0000000..606f360
--- /dev/null
+++ b/build/fuchsia/test/publish_package_unittests.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env vpython3
+# 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.
+"""File for testing publish_package.py."""
+
+import argparse
+import unittest
+import unittest.mock as mock
+
+from io import StringIO
+
+import publish_package
+
+
+class PublishPackageTest(unittest.TestCase):
+    """Unittests for publish_package.py."""
+
+    def setUp(self) -> None:
+        self._subprocess_patcher = mock.patch('publish_package.subprocess.run')
+        self._subprocess_mock = self._subprocess_patcher.start()
+        self.addCleanup(self._subprocess_mock.stop)
+
+    def test_new_repo(self) -> None:
+        """Test setting |new_repo| to True in |publish_packages|."""
+
+        publish_package.publish_packages(['test_package'], 'test_repo', True)
+        self.assertEqual(self._subprocess_mock.call_count, 2)
+        first_call = self._subprocess_mock.call_args_list[0]
+        self.assertEqual('newrepo', first_call[0][0][1])
+
+    def test_no_new_repo(self) -> None:
+        """Test setting |new_repo| to False in |publish_packages|."""
+
+        publish_package.publish_packages(['test_package'], 'test_repo', False)
+        self.assertEqual(self._subprocess_mock.call_count, 1)
+        first_call = self._subprocess_mock.call_args_list[0]
+        self.assertEqual('publish', first_call[0][0][1])
+
+    def test_allow_temp_repo(self) -> None:
+        """Test setting |allow_temp_repo| to True in |register_package_args|."""
+
+        parser = argparse.ArgumentParser()
+        publish_package.register_package_args(parser, True)
+        args = parser.parse_args(['--no-repo-init'])
+        self.assertEqual(args.no_repo_init, True)
+
+    @mock.patch('sys.stderr', new_callable=StringIO)
+    def test_not_allow_temp_repo(self, mock_stderr) -> None:
+        """Test setting |allow_temp_repo| to False in
+        |register_package_args|."""
+
+        parser = argparse.ArgumentParser()
+        publish_package.register_package_args(parser)
+        with self.assertRaises(SystemExit):
+            parser.parse_args(['--no-repo-init'])
+        self.assertRegex(mock_stderr.getvalue(), 'unrecognized arguments')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/build/fuchsia/test/run_executable_test.py b/build/fuchsia/test/run_executable_test.py
index a92df96..84cc2f69 100755
--- a/build/fuchsia/test/run_executable_test.py
+++ b/build/fuchsia/test/run_executable_test.py
@@ -15,6 +15,7 @@
 
 from common import get_component_uri, register_common_args, \
                    register_device_args, resolve_packages, run_ffx_command
+from compatible_utils import map_filter_file_to_package_file
 from ffx_integration import FfxTestRunner
 from test_runner import TestRunner
 
@@ -65,6 +66,10 @@
             type=int,
             default=os.environ.get('GTEST_TOTAL_SHARDS'),
             help='Total number of swarming shards of this suite.')
+        parser.add_argument(
+            '--test-launcher-filter-file',
+            help='Filter file(s) passed to target test process. Use ";" to '
+            'separate multiple filter files.')
 
         args, child_args = parser.parse_known_args(self._test_args)
         if args.isolated_script_test_output:
@@ -76,16 +81,20 @@
             child_args.append('--test-launcher-shard-index=%d' %
                               args.test_launcher_shard_index)
         if args.test_launcher_total_shards:
-            child_args.append([
-                '--test-launcher-total-shards=%d' %
-                args.test_launcher_total_shards
-            ])
+            child_args.append('--test-launcher-total-shards=%d' %
+                              args.test_launcher_total_shards)
         if args.test_launcher_summary_output:
             self._test_launcher_summary_output = \
                 args.test_launcher_summary_output
             child_args.append(
                 '--test-launcher-summary-output=/custom_artifacts/%s' %
                 os.path.basename(self._test_launcher_summary_output))
+        if args.test_launcher_filter_file:
+            test_launcher_filter_files = map(
+                map_filter_file_to_package_file,
+                args.test_launcher_filter_file.split(';'))
+            child_args.append('--test-launcher-filter-file=' +
+                              ';'.join(test_launcher_filter_files))
         return child_args
 
     def _postprocess(self, test_runner: FfxTestRunner) -> None:
diff --git a/build/fuchsia/test/serve_repo.py b/build/fuchsia/test/serve_repo.py
index 43dd3f44..d7b5eb49 100755
--- a/build/fuchsia/test/serve_repo.py
+++ b/build/fuchsia/test/serve_repo.py
@@ -16,6 +16,7 @@
 
 # Contains information about the active ephemeral repository.
 _REPO_CONFIG_FILE = os.path.join('/', 'tmp', 'fuchsia-repo-config')
+_REPO_NAME = 'chromium-test-package-server'
 
 
 def _ensure_ffx_config(key: str, value: str) -> bool:
@@ -89,7 +90,7 @@
                             dest='repo',
                             help='Directory the repository is served from.')
     serve_args.add_argument('--repo-name',
-                            default='test',
+                            default=_REPO_NAME,
                             help='Name of the repository.')
 
 
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py
index 1b18653..02332e57 100755
--- a/build/fuchsia/test_runner.py
+++ b/build/fuchsia/test_runner.py
@@ -20,6 +20,10 @@
 from run_test_package import RunTestPackage, RunTestPackageArgs
 from runner_exceptions import HandleExceptionAndReturnExitCode
 
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
+                                             'test')))
+from compatible_utils import map_filter_file_to_package_file
+
 DEFAULT_TEST_SERVER_CONCURRENCY = 4
 
 TEST_DATA_DIR = '/tmp'
@@ -240,15 +244,6 @@
                          help='Arguments for the test process.')
 
 
-def MapFilterFileToPackageFile(filter_file):
-  # TODO(crbug.com/1279803): Until one can send file to the device when running
-  # a test, filter files must be read from the test package.
-  if not FILTER_DIR in filter_file:
-    raise ValueError('CFv2 tests only support registered filter files present '
-                     ' in the test package')
-  return '/pkg/' + filter_file[filter_file.index(FILTER_DIR):]
-
-
 def main():
   parser = argparse.ArgumentParser()
   AddTestExecutionArgs(parser)
@@ -357,7 +352,7 @@
           # TODO(crbug.com/1279803): Until one can send file to the device when
           # running a test, filter files must be read from the test package.
           test_launcher_filter_files = map(
-              MapFilterFileToPackageFile,
+              map_filter_file_to_package_file,
               args.test_launcher_filter_file.split(';'))
           child_args.append('--test-launcher-filter-file=' +
                             ';'.join(test_launcher_filter_files))
diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn
index e67f09f..102e712 100644
--- a/build/toolchain/linux/BUILD.gn
+++ b/build/toolchain/linux/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/dcheck_always_on.gni")
 import("//build/config/ozone.gni")
 import("//build/config/sysroot.gni")
 import("//build/config/ui.gni")
@@ -208,7 +209,7 @@
     chromeos_is_browser_only = true
     use_clang_coverage = false
     dcheck_always_on = false
-    symbol_level=1
+    symbol_level = 1
   }
 }
 
diff --git a/build/util/lastchange.py b/build/util/lastchange.py
index 02a3664..1970c4783 100755
--- a/build/util/lastchange.py
+++ b/build/util/lastchange.py
@@ -221,12 +221,22 @@
   parser.add_argument("-m", "--version-macro",
                     help=("Name of C #define when using --header. Defaults to "
                           "LAST_CHANGE."))
-  parser.add_argument("-o", "--output", metavar="FILE",
-                    help=("Write last change to FILE. "
-                          "Can be combined with --header to write both files."))
-  parser.add_argument("--header", metavar="FILE",
-                    help=("Write last change to FILE as a C/C++ header. "
-                          "Can be combined with --output to write both files."))
+  parser.add_argument("-o",
+                      "--output",
+                      metavar="FILE",
+                      help=("Write last change to FILE. "
+                            "Can be combined with other file-output-related "
+                            "options to write multiple files."))
+  parser.add_argument("--header",
+                      metavar="FILE",
+                      help=("Write last change to FILE as a C/C++ header. "
+                            "Can be combined with other file-output-related "
+                            "options to write multiple files."))
+  parser.add_argument("--revision",
+                      metavar="FILE",
+                      help=("Write last change to FILE as a one-line revision. "
+                            "Can be combined with other file-output-related "
+                            "options to write multiple files."))
   parser.add_argument("--merge-base-ref",
                     default=None,
                     help=("Only consider changes since the merge "
@@ -255,6 +265,7 @@
 
   out_file = args.output
   header = args.header
+  revision = args.revision
   commit_filter=args.filter
 
   while len(extras) and out_file is None:
@@ -311,7 +322,7 @@
         "LASTCHANGE_YEAR=%s" % lastchange_year,
     ]
     contents = '\n'.join(contents_lines) + '\n'
-    if not out_file and not args.header:
+    if not out_file and not header and not revision:
       sys.stdout.write(contents)
     else:
       if out_file:
@@ -324,6 +335,8 @@
         WriteIfChanged(header,
                        GetHeaderContents(header, args.version_macro,
                                          revision_string))
+      if revision:
+        WriteIfChanged(revision, revision_string)
 
   return 0
 
diff --git a/build_overrides/dawn.gni b/build_overrides/dawn.gni
index 288ceb28..80a4629 100644
--- a/build_overrides/dawn.gni
+++ b/build_overrides/dawn.gni
@@ -13,3 +13,5 @@
 dawn_vulkan_loader_dir = "//third_party/vulkan-deps/vulkan-loader/src"
 dawn_vulkan_validation_layers_dir =
     "//third_party/vulkan-deps/vulkan-validation-layers/src"
+
+dawn_version_file = "//gpu/webgpu/DAWN_VERSION"
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index de5d038..d1d52c7 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -10374,5 +10374,33 @@
 };
 MULTI_THREAD_TEST_F(LayerTreeHostTestNeedsNotifyReadyToActivateOnly);
 
+class LayerTreeHostTestDidCommitAndDrawFrame : public LayerTreeHostTest {
+ public:
+  void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+  void DidCommitAndDrawFrame() override { EXPECT_EQ(0, num_draws_); }
+
+  void DidReceiveCompositorFrameAck() override {
+    ++num_draws_;
+    if (num_draws_ == 2) {
+      EndTest();
+    }
+  }
+
+  void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+    EXPECT_EQ(0, host_impl->active_tree()->source_frame_number());
+  }
+
+  void DidReceiveCompositorFrameAckOnThread(
+      LayerTreeHostImpl* host_impl) override {
+    host_impl->SetViewportDamage(gfx::Rect(1, 1));
+    host_impl->RequestImplSideInvalidationForRerasterTiling();
+  }
+
+ protected:
+  int num_draws_ = 0;
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestDidCommitAndDrawFrame);
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index e253b21..aec88ca 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -797,8 +797,6 @@
   // This is run as a separate step from commit because it can be time-consuming
   // and ought not delay sending the next BeginMainFrame.
   host_impl_->CommitComplete();
-  // TODO(szager): This should be set at activation time. crbug.com/1323906
-  next_frame_is_newly_committed_frame_ = true;
 }
 
 void ProxyImpl::ScheduledActionActivateSyncTree() {
@@ -809,6 +807,7 @@
         "viz,benchmark", "MainFrame.Activate",
         TRACE_ID_LOCAL(host_impl_->sync_tree()->trace_id()),
         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+    next_frame_is_newly_committed_frame_ = true;
   }
   DCHECK(IsImplThread());
   host_impl_->ActivateSyncTree();
diff --git a/chrome/VERSION b/chrome/VERSION
index ee53288..24efee8c 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=105
 MINOR=0
-BUILD=5135
+BUILD=5138
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 045a52d1..202d618 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1112,6 +1112,7 @@
     "//components/browser_ui/notifications/android:java",
     "//components/browser_ui/share/android:java",
     "//components/browser_ui/site_settings/android:java",
+    "//components/browser_ui/styles/android:java",
     "//components/browser_ui/test/android:test_support_java",
     "//components/browser_ui/util/android:java",
     "//components/browser_ui/widget/android:java",
@@ -1580,7 +1581,6 @@
     "//chrome/browser/ui/android/layouts:java",
     "//chrome/browser/ui/android/layouts/test:java",
     "//chrome/browser/ui/android/layouts/third_party/float_property:java",
-    "//chrome/browser/ui/android/logo:javatests",
     "//chrome/browser/ui/android/multiwindow:javatests",
     "//chrome/browser/ui/android/native_page:java",
     "//chrome/browser/ui/android/night_mode:java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index 2f9dddef..8f29f63 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -240,6 +240,7 @@
   "junit/src/org/chromium/chrome/browser/tabmodel/UndoTabModelUnitTest.java",
   "junit/src/org/chromium/chrome/browser/tasks/EngagementTimeUtilTest.java",
   "junit/src/org/chromium/chrome/browser/tasks/JourneyManagerTest.java",
+  "junit/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtilUnitTest.java",
   "junit/src/org/chromium/chrome/browser/toolbar/LocationBarModelUnitTest.java",
   "junit/src/org/chromium/chrome/browser/toolbar/ToolbarTabControllerImplTest.java",
   "junit/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerActivityTest.java",
diff --git a/chrome/android/features/start_surface/javatests/start_surface_test_java_sources.gni b/chrome/android/features/start_surface/javatests/start_surface_test_java_sources.gni
index 88404dfa..b2015a72 100644
--- a/chrome/android/features/start_surface/javatests/start_surface_test_java_sources.gni
+++ b/chrome/android/features/start_surface/javatests/start_surface_test_java_sources.gni
@@ -17,5 +17,4 @@
   "//chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java",
   "//chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutPerfTest.java",
   "//chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java",
-  "//chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/tasks/TasksViewBinderTest.java",
 ]
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/tasks/TasksViewBinderTest.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/TasksViewBinderUnitTest.java
similarity index 85%
rename from chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/tasks/TasksViewBinderTest.java
rename to chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/TasksViewBinderUnitTest.java
index 119a0fc1..3a8e0127 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/tasks/TasksViewBinderTest.java
+++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/TasksViewBinderUnitTest.java
@@ -4,11 +4,6 @@
 
 package org.chromium.chrome.features.tasks;
 
-import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.action.ViewActions.replaceText;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -34,57 +29,61 @@
 import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TOP_TOOLBAR_PLACEHOLDER_HEIGHT;
 import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.VOICE_SEARCH_BUTTON_CLICK_LISTENER;
 
+import android.app.Activity;
 import android.graphics.drawable.ColorDrawable;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.widget.EditText;
 
 import androidx.test.filters.SmallTest;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
 
-import org.chromium.base.test.UiThreadTest;
-import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
+import org.chromium.ui.base.TestActivity;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
-import org.chromium.ui.test.util.BlankUiTestActivityTestCase;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /** Tests for {@link TasksViewBinder}. */
-@RunWith(ChromeJUnit4ClassRunner.class)
-public class TasksViewBinderTest extends BlankUiTestActivityTestCase {
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class TasksViewBinderUnitTest {
     private final AtomicBoolean mViewClicked = new AtomicBoolean();
     private final View.OnClickListener mViewOnClickListener = (v) -> mViewClicked.set(true);
+    private Activity mActivity;
     private TasksView mTasksView;
     private PropertyModel mTasksViewPropertyModel;
+
     @Mock
     private IncognitoCookieControlsManager mCookieControlsManager;
 
-    @Override
-    public void setUpTest() throws Exception {
-        super.setUpTest();
+    @Before
+    public void setUp() throws Exception {
+        mActivity = Robolectric.buildActivity(TestActivity.class).setup().get();
         MockitoAnnotations.initMocks(this);
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mTasksView = (TasksView) getActivity().getLayoutInflater().inflate(
-                    R.layout.tasks_view_layout, null);
-            getActivity().setContentView(mTasksView);
+        mTasksView =
+                (TasksView) mActivity.getLayoutInflater().inflate(R.layout.tasks_view_layout, null);
+        mActivity.setContentView(mTasksView);
 
-            mTasksViewPropertyModel = new PropertyModel(TasksSurfaceProperties.ALL_KEYS);
-            PropertyModelChangeProcessor.create(
-                    mTasksViewPropertyModel, mTasksView, TasksViewBinder::bind);
-        });
+        mTasksViewPropertyModel = new PropertyModel(TasksSurfaceProperties.ALL_KEYS);
+        PropertyModelChangeProcessor.create(
+                mTasksViewPropertyModel, mTasksView, TasksViewBinder::bind);
     }
 
     private boolean isViewVisible(int viewId) {
@@ -92,7 +91,6 @@
     }
 
     @Test
-    @UiThreadTest
     @SmallTest
     public void testSetTabCarouselMode() {
         mTasksViewPropertyModel.set(IS_TAB_CAROUSEL_VISIBLE, true);
@@ -103,7 +101,6 @@
     }
 
     @Test
-    @UiThreadTest
     @SmallTest
     public void testSetTabCarouselTitle() {
         mTasksViewPropertyModel.set(IS_TAB_CAROUSEL_TITLE_VISIBLE, true);
@@ -137,20 +134,23 @@
         };
 
         mViewClicked.set(false);
-        onView(withId(R.id.search_box_text)).perform(click());
+        mTasksView.findViewById(R.id.search_box_text).performClick();
         assertFalse(mViewClicked.get());
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mTasksViewPropertyModel.set(FAKE_SEARCH_BOX_CLICK_LISTENER, mViewOnClickListener);
         });
-        onView(withId(R.id.search_box_text)).perform(click());
+        mTasksView.findViewById(R.id.search_box_text).performClick();
         assertTrue(mViewClicked.get());
 
         textChanged.set(false);
-        onView(withId(R.id.search_box_text)).perform(replaceText("test"));
+        EditText searchBoxText = mTasksView.findViewById(R.id.search_box_text);
+        searchBoxText.setText("test");
+        searchBoxText.performClick();
         assertFalse(textChanged.get());
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> mTasksViewPropertyModel.set(FAKE_SEARCH_BOX_TEXT_WATCHER, textWatcher));
-        onView(withId(R.id.search_box_text)).perform(replaceText("test2"));
+        searchBoxText.setText("test2");
+        searchBoxText.performClick();
         assertTrue(textChanged.get());
 
         TestThreadUtils.runOnUiThreadBlocking(
@@ -160,7 +160,6 @@
 
     @Test
     @SmallTest
-    @DisabledTest(message = "crbug.com/1130093")
     public void testSetVoiceSearchButtonVisibilityAndClickListener() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mTasksViewPropertyModel.set(IS_FAKE_SEARCH_BOX_VISIBLE, true);
@@ -169,12 +168,12 @@
         assertTrue(isViewVisible(R.id.voice_search_button));
 
         mViewClicked.set(false);
-        onView(withId(R.id.voice_search_button)).perform(click());
+        mTasksView.findViewById(R.id.voice_search_button).performClick();
         assertFalse(mViewClicked.get());
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mTasksViewPropertyModel.set(VOICE_SEARCH_BUTTON_CLICK_LISTENER, mViewOnClickListener);
         });
-        onView(withId(R.id.voice_search_button)).perform(click());
+        mTasksView.findViewById(R.id.voice_search_button).performClick();
         assertTrue(mViewClicked.get());
 
         TestThreadUtils.runOnUiThreadBlocking(
@@ -192,12 +191,12 @@
         assertTrue(isViewVisible(R.id.lens_camera_button));
 
         mViewClicked.set(false);
-        onView(withId(R.id.lens_camera_button)).perform(click());
+        mTasksView.findViewById(R.id.lens_camera_button).performClick();
         assertFalse(mViewClicked.get());
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mTasksViewPropertyModel.set(LENS_BUTTON_CLICK_LISTENER, mViewOnClickListener);
         });
-        onView(withId(R.id.lens_camera_button)).perform(click());
+        mTasksView.findViewById(R.id.lens_camera_button).performClick();
         assertTrue(mViewClicked.get());
 
         TestThreadUtils.runOnUiThreadBlocking(
@@ -206,7 +205,6 @@
     }
 
     @Test
-    @UiThreadTest
     @SmallTest
     public void testSetMVTilesVisibility() {
         mTasksViewPropertyModel.set(MV_TILES_VISIBLE, true);
@@ -217,7 +215,6 @@
     }
 
     @Test
-    @UiThreadTest
     @SmallTest
     public void testSetMoreTabsClickListener() {
         mTasksViewPropertyModel.set(IS_TAB_CAROUSEL_VISIBLE, true);
@@ -235,16 +232,15 @@
     }
 
     @Test
-    @UiThreadTest
     @SmallTest
     public void testSetIncognitoMode() {
         mTasksViewPropertyModel.set(IS_INCOGNITO, true);
-        int backgroundColor = ChromeColors.getPrimaryBackgroundColor(getActivity(), true);
+        int backgroundColor = ChromeColors.getPrimaryBackgroundColor(mActivity, true);
         ColorDrawable viewColor = (ColorDrawable) mTasksView.getBackground();
         assertEquals(backgroundColor, viewColor.getColor());
 
         mTasksViewPropertyModel.set(IS_INCOGNITO, false);
-        backgroundColor = ChromeColors.getPrimaryBackgroundColor(getActivity(), false);
+        backgroundColor = ChromeColors.getPrimaryBackgroundColor(mActivity, false);
         viewColor = (ColorDrawable) mTasksView.getBackground();
         assertEquals(backgroundColor, viewColor.getColor());
     }
@@ -268,7 +264,6 @@
     }
 
     @Test
-    @UiThreadTest
     @SmallTest
     public void testSetTasksSurfaceBodyTopMargin() {
         ViewGroup.MarginLayoutParams params =
@@ -281,7 +276,6 @@
     }
 
     @Test
-    @UiThreadTest
     @SmallTest
     public void testSetMVTilesContainerTopMargin() {
         ViewGroup.MarginLayoutParams params =
@@ -295,7 +289,6 @@
     }
 
     @Test
-    @UiThreadTest
     @SmallTest
     public void testSetTabSwitcherTitleTopMargin() {
         ViewGroup.MarginLayoutParams params =
@@ -309,7 +302,6 @@
     }
 
     @Test
-    @UiThreadTest
     @SmallTest
     public void testSetTopToolbarLayoutHeight() {
         ViewGroup.LayoutParams params =
diff --git a/chrome/android/features/start_surface/junit/start_surface_junit_java_sources.gni b/chrome/android/features/start_surface/junit/start_surface_junit_java_sources.gni
index 7717fc1..f266219 100644
--- a/chrome/android/features/start_surface/junit/start_surface_junit_java_sources.gni
+++ b/chrome/android/features/start_surface/junit/start_surface_junit_java_sources.gni
@@ -9,4 +9,5 @@
   "//chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediatorUnitTest.java",
   "//chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/SingleTabViewBinderUnitTest.java",
   "//chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/TasksSurfaceMediatorUnitTest.java",
+  "//chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/tasks/TasksViewBinderUnitTest.java",
 ]
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index 2face667..3bc75cb 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -59,6 +59,7 @@
     "java/res/layout/bottom_tab_strip_toolbar.xml",
     "java/res/layout/closable_tab_grid_card_item.xml",
     "java/res/layout/closable_tab_list_card_item.xml",
+    "java/res/layout/coupon_card.xml",
     "java/res/layout/incognito_description_container_layout.xml",
     "java/res/layout/iph_drag_and_drop_dialog_layout.xml",
     "java/res/layout/large_message_card_item.xml",
@@ -93,6 +94,7 @@
   sources = [
     "java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/ClosableTabGridView.java",
+    "java/src/org/chromium/chrome/browser/tasks/tab_management/CouponCardView.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageService.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/LargeMessageCardView.java",
diff --git a/chrome/android/features/tab_ui/java/res/layout/coupon_card.xml b/chrome/android/features/tab_ui/java/res/layout/coupon_card.xml
new file mode 100644
index 0000000..53c9b1aa
--- /dev/null
+++ b/chrome/android/features/tab_ui/java/res/layout/coupon_card.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2022 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:app="http://schemas.android.com/apk/res-auto">
+    <LinearLayout
+        android:id="@+id/coupon_info_box"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:layout_marginStart="4dp"
+        android:orientation="horizontal"
+        android:background="@drawable/price_card_background">
+        <TextView
+            android:id="@+id/coupon_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="4dp"
+            android:layout_marginStart="10dp"
+            android:layout_marginEnd="10dp"
+            android:layout_marginBottom="4dp"
+            android:singleLine="true"
+            android:textAppearance="@style/TextAppearance.TextMediumThick"
+            android:textAlignment="viewStart" />
+    </LinearLayout>
+</merge>
diff --git a/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml b/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml
index af013b4..b11263a 100644
--- a/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml
+++ b/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml
@@ -60,6 +60,15 @@
                 android:layout_height="56dp"
                 android:layout_marginStart="4dp"
                 android:visibility="gone"/>
+            <org.chromium.chrome.browser.tasks.tab_management.CouponCardView
+                android:id="@+id/coupon_info_box_outer"
+                android:layout_below="@id/tab_title"
+                android:background="@drawable/price_card_scrim"
+                android:layout_width="match_parent"
+                android:layout_height="56dp"
+                android:layout_marginStart="4dp"
+                android:layout_marginEnd="4dp"
+                android:visibility="gone"/>
             <!-- TODO(crbug/1198288): Make decision on duplication of PriceCardView code.-->
             <org.chromium.chrome.browser.tasks.tab_management.StoreHoursCardView
                 android:id="@+id/store_hours_box_outer"
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CouponCardView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CouponCardView.java
new file mode 100644
index 0000000..ac70cdb
--- /dev/null
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CouponCardView.java
@@ -0,0 +1,43 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tasks.tab_management;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import org.chromium.chrome.tab_ui.R;
+
+/**
+ * Contains coupon information related to a shopping website. Currently only
+ * supports displaying the name of coupon when available coupon is detected.
+ */
+public class CouponCardView extends FrameLayout {
+    private TextView mCouponInfoBox;
+
+    public CouponCardView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * Sets the current price string and previous price string when a price drop is detected.
+     */
+    public void setCouponString(String couponName) {
+        // TODO(crbug.com/1335127): Display coupon discount amount as text for coupon
+        // annotations on Tab UI.
+        mCouponInfoBox.setText(couponName);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        LayoutInflater.from(getContext()).inflate(R.layout.coupon_card, this);
+        mCouponInfoBox = (TextView) findViewById(R.id.coupon_name);
+        mCouponInfoBox.setTextColor(
+                getContext().getColor(R.color.price_drop_annotation_text_green));
+    }
+}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CouponUtilities.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CouponUtilities.java
new file mode 100644
index 0000000..afc35908
--- /dev/null
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CouponUtilities.java
@@ -0,0 +1,19 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tasks.tab_management;
+import org.chromium.chrome.browser.flags.CachedFeatureFlags;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+
+/**
+ * Utility class for coupons in Tab UI.
+ */
+public class CouponUtilities {
+    /**
+     * @return Whether commerce coupons feature flag is enabled.
+     */
+    public static boolean isCouponsOnTabsEnabled() {
+        return CachedFeatureFlags.isEnabled(ChromeFeatureList.COMMERCE_COUPONS);
+    }
+}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java
index 7d320ba..127ecc21 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java
@@ -28,6 +28,7 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Callback;
 import org.chromium.chrome.browser.tab.TabUtils;
+import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.components.browser_ui.widget.chips.ChipView;
 import org.chromium.ui.modelutil.PropertyKey;
@@ -212,32 +213,45 @@
                 pageInfoButton.getPrimaryTextView().setText(query);
             }
         } else if (TabProperties.SHOPPING_PERSISTED_TAB_DATA_FETCHER == propertyKey) {
-            PriceCardView priceCardView =
-                    (PriceCardView) view.fastFindViewById(R.id.price_info_box_outer);
-            if (model.get(TabProperties.SHOPPING_PERSISTED_TAB_DATA_FETCHER) != null) {
-                model.get(TabProperties.SHOPPING_PERSISTED_TAB_DATA_FETCHER)
-                        .fetch((shoppingPersistedTabData) -> {
-                            if (shoppingPersistedTabData == null
-                                    || shoppingPersistedTabData.getPriceDrop() == null) {
-                                priceCardView.setVisibility(View.GONE);
+            fetchPriceDrop(model, (priceDrop) -> {
+                PriceCardView priceCardView =
+                        (PriceCardView) view.fastFindViewById(R.id.price_info_box_outer);
+                if (priceDrop == null) {
+                    priceCardView.setVisibility(View.GONE);
+                    return;
+                }
+                priceCardView.setPriceStrings(priceDrop.price, priceDrop.previousPrice);
+                priceCardView.setVisibility(View.VISIBLE);
+                priceCardView.setContentDescription(
+                        view.getResources().getString(R.string.accessibility_tab_price_card,
+                                priceDrop.previousPrice, priceDrop.price));
+            }, true);
+        } else if (TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER == propertyKey) {
+            CouponCardView couponCardView =
+                    (CouponCardView) view.fastFindViewById(R.id.coupon_info_box_outer);
+            if (model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER) == null) {
+                couponCardView.setVisibility(View.GONE);
+                return;
+            }
+            fetchPriceDrop(model, (priceDrop) -> {
+                if (priceDrop != null) {
+                    couponCardView.setVisibility(View.GONE);
+                    return;
+                }
+                model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER)
+                        .fetch((couponPersistedTabData) -> {
+                            // TODO(crbug.com/1337117): add logging for when
+                            // couponPersistedTabData is not null
+                            if (couponPersistedTabData == null
+                                    || couponPersistedTabData.getCoupon() == null) {
+                                couponCardView.setVisibility(View.GONE);
                             } else {
-                                priceCardView.setPriceStrings(
-                                        shoppingPersistedTabData.getPriceDrop().price,
-                                        shoppingPersistedTabData.getPriceDrop().previousPrice);
-                                priceCardView.setVisibility(View.VISIBLE);
-                                priceCardView.setContentDescription(view.getResources().getString(
-                                        R.string.accessibility_tab_price_card,
-                                        shoppingPersistedTabData.getPriceDrop().previousPrice,
-                                        shoppingPersistedTabData.getPriceDrop().price));
-                            }
-                            if (shoppingPersistedTabData != null) {
-                                shoppingPersistedTabData.logPriceDropMetrics(
-                                        SHOPPING_METRICS_IDENTIFIER);
+                                couponCardView.setCouponString(
+                                        couponPersistedTabData.getCoupon().couponName);
+                                couponCardView.setVisibility(View.VISIBLE);
                             }
                         });
-            } else {
-                priceCardView.setVisibility(View.GONE);
-            }
+            }, false);
         } else if (TabProperties.STORE_PERSISTED_TAB_DATA_FETCHER == propertyKey) {
             StoreHoursCardView storeHoursCardView =
                     (StoreHoursCardView) view.fastFindViewById(R.id.store_hours_box_outer);
@@ -324,6 +338,25 @@
         }
     }
 
+    private static void fetchPriceDrop(PropertyModel model,
+            Callback<ShoppingPersistedTabData.PriceDrop> callback, boolean shouldLog) {
+        if (model.get(TabProperties.SHOPPING_PERSISTED_TAB_DATA_FETCHER) == null) {
+            callback.onResult(null);
+            return;
+        }
+        model.get(TabProperties.SHOPPING_PERSISTED_TAB_DATA_FETCHER)
+                .fetch((shoppingPersistedTabData) -> {
+                    if (shoppingPersistedTabData == null) {
+                        callback.onResult(null);
+                        return;
+                    }
+                    if (shouldLog) {
+                        shoppingPersistedTabData.logPriceDropMetrics(SHOPPING_METRICS_IDENTIFIER);
+                    }
+                    callback.onResult(shoppingPersistedTabData.getPriceDrop());
+                });
+    }
+
     private static void updateThumbnail(ViewLookupCachingFrameLayout view, PropertyModel model) {
         TabListMediator.ThumbnailFetcher fetcher = model.get(TabProperties.THUMBNAIL_FETCHER);
         TabGridThumbnailView thumbnail =
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index dd965b6..0d6c6588 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -51,6 +51,7 @@
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tab.TabSelectionType;
+import org.chromium.chrome.browser.tab.state.CouponPersistedTabData;
 import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData;
 import org.chromium.chrome.browser.tab.state.StorePersistedTabData;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelFilter;
@@ -247,6 +248,28 @@
     }
 
     /**
+     * Asynchronously acquire {@link CouponPersistedTabData}
+     */
+    static class CouponPersistedTabDataFetcher {
+        protected Tab mTab;
+
+        /**
+         * @param tab {@link Tab} {@link CouponPersistedTabData} will be acquired for.
+         */
+        CouponPersistedTabDataFetcher(Tab tab) {
+            mTab = tab;
+        }
+
+        /**
+         * Asynchronously acquire {@link CouponPersistedTabData}
+         * @param callback {@link Callback} to pass {@link CouponPersistedTabData} back in
+         */
+        public void fetch(Callback<CouponPersistedTabData> callback) {
+            CouponPersistedTabData.from(mTab, (res) -> { callback.onResult(res); });
+        }
+    }
+
+    /**
      * The object to set to {@link TabProperties#THUMBNAIL_FETCHER} for the TabGridViewBinder to
      * obtain the thumbnail asynchronously.
      */
@@ -1696,7 +1719,14 @@
             } else {
                 mModel.get(index).model.set(TabProperties.STORE_PERSISTED_TAB_DATA_FETCHER, null);
             }
+            if (CouponUtilities.isCouponsOnTabsEnabled() && isUngroupedTab(pseudoTab.getId())) {
+                mModel.get(index).model.set(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER,
+                        new CouponPersistedTabDataFetcher(pseudoTab.getTab()));
+            } else {
+                mModel.get(index).model.set(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER, null);
+            }
         } else {
+            mModel.get(index).model.set(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER, null);
             mModel.get(index).model.set(TabProperties.SHOPPING_PERSISTED_TAB_DATA_FETCHER, null);
             mModel.get(index).model.set(TabProperties.STORE_PERSISTED_TAB_DATA_FETCHER, null);
         }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java
index 33b6b933..60f478f 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java
@@ -114,6 +114,9 @@
     public static final WritableObjectPropertyKey<TabListMediator.StorePersistedTabDataFetcher>
             STORE_PERSISTED_TAB_DATA_FETCHER = new WritableObjectPropertyKey<>(true);
 
+    public static final WritableObjectPropertyKey<TabListMediator.CouponPersistedTabDataFetcher>
+            COUPON_PERSISTED_TAB_DATA_FETCHER = new WritableObjectPropertyKey<>(true);
+
     public static final WritableObjectPropertyKey<TabListMediator.TabActionListener>
             PAGE_INFO_LISTENER = new WritableObjectPropertyKey<>();
 
@@ -138,7 +141,8 @@
             SEARCH_QUERY, PAGE_INFO_LISTENER, PAGE_INFO_ICON_DRAWABLE_ID, CARD_TYPE,
             CONTENT_DESCRIPTION_STRING, CLOSE_BUTTON_DESCRIPTION_STRING,
             SHOPPING_PERSISTED_TAB_DATA_FETCHER, STORE_PERSISTED_TAB_DATA_FETCHER,
-            SHOULD_SHOW_PRICE_DROP_TOOLTIP, GRID_CARD_WIDTH, GRID_CARD_HEIGHT};
+            COUPON_PERSISTED_TAB_DATA_FETCHER, SHOULD_SHOW_PRICE_DROP_TOOLTIP, GRID_CARD_WIDTH,
+            GRID_CARD_HEIGHT};
 
     public static final PropertyKey[] ALL_KEYS_TAB_STRIP =
             new PropertyKey[] {TAB_ID, TAB_SELECTED_LISTENER, TAB_CLOSED_LISTENER, FAVICON,
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
index 455d0d5..b2e23f2 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
@@ -57,6 +57,7 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.MockTab;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.state.CouponPersistedTabData;
 import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tab.state.LevelDBPersistedDataStorage;
 import org.chromium.chrome.browser.tab.state.LevelDBPersistedDataStorageJni;
@@ -139,6 +140,9 @@
             "The price of this item recently dropped from $10 to $5.00";
     private static final GURL TEST_GURL = new GURL("https://www.google.com");
 
+    private static final String EXPECTED_COUPON_NAME = "TEST";
+    private static final String EXPECTED_COUPON_CODE = "TESTCODE";
+
     private ViewGroup mTabGridView;
     private PropertyModel mGridModel;
     private PropertyModelChangeProcessor mGridMCP;
@@ -780,6 +784,93 @@
         }
     }
 
+    @Test
+    @MediumTest
+    @UiThreadTest
+    public void testCouponStringCouponAvailable() {
+        setCouponsEnabledForTesting();
+        Tab tab = MockTab.createAndInitialize(1, false);
+        MockCouponPersistedTabDataFetcher fetcher = new MockCouponPersistedTabDataFetcher(tab);
+        fetcher.setCouponStrings(EXPECTED_COUPON_NAME, EXPECTED_COUPON_CODE);
+        testCouponString(tab, fetcher, View.VISIBLE, EXPECTED_COUPON_NAME);
+    }
+
+    @Test
+    @MediumTest
+    @UiThreadTest
+    public void testCouponStringCouponEmpty() {
+        setCouponsEnabledForTesting();
+        Tab tab = MockTab.createAndInitialize(1, false);
+        MockCouponPersistedTabDataFetcher fetcher = new MockCouponPersistedTabDataFetcher(tab);
+        fetcher.setEmptyCoupon();
+        testCouponString(tab, fetcher, View.GONE, null);
+    }
+
+    @Test
+    @MediumTest
+    @UiThreadTest
+    public void testCouponStringFetcherNull() {
+        setCouponsEnabledForTesting();
+        Tab tab = MockTab.createAndInitialize(1, false);
+        testCouponString(tab, null, View.GONE, null);
+    }
+
+    @Test
+    @MediumTest
+    @UiThreadTest
+    public void testCouponStringCouponThenEmpty() {
+        setCouponsEnabledForTesting();
+        Tab tab = MockTab.createAndInitialize(1, false);
+        MockCouponPersistedTabDataFetcher fetcher = new MockCouponPersistedTabDataFetcher(tab);
+        fetcher.setCouponStrings(EXPECTED_COUPON_NAME, EXPECTED_COUPON_CODE);
+        testCouponString(tab, fetcher, View.VISIBLE, EXPECTED_COUPON_NAME);
+        fetcher.setEmptyCoupon();
+        testCouponString(tab, fetcher, View.GONE, null);
+    }
+
+    @Test
+    @MediumTest
+    @UiThreadTest
+    public void testCouponStringTurnFeatureOff() {
+        Tab tab = MockTab.createAndInitialize(1, false);
+        MockCouponPersistedTabDataFetcher fetcher = new MockCouponPersistedTabDataFetcher(tab);
+        fetcher.setCouponStrings(EXPECTED_COUPON_NAME, EXPECTED_COUPON_CODE);
+        testCouponString(tab, fetcher, View.VISIBLE, EXPECTED_COUPON_NAME);
+        testCouponString(tab, null, View.GONE, null);
+    }
+
+    @Test
+    @MediumTest
+    @UiThreadTest
+    public void testCouponStringPriceDropAvailable() {
+        setCouponsEnabledForTesting();
+        Tab tab = MockTab.createAndInitialize(1, false);
+
+        MockShoppingPersistedTabDataFetcher shoppingFetcher =
+                new MockShoppingPersistedTabDataFetcher(tab);
+        shoppingFetcher.setPriceStrings(EXPECTED_PRICE_STRING, EXPECTED_PREVIOUS_PRICE_STRING);
+        testPriceString(tab, shoppingFetcher, View.VISIBLE, EXPECTED_PRICE_STRING,
+                EXPECTED_PREVIOUS_PRICE_STRING);
+
+        MockCouponPersistedTabDataFetcher couponFetcher =
+                new MockCouponPersistedTabDataFetcher(tab);
+        couponFetcher.setCouponStrings(EXPECTED_COUPON_NAME, EXPECTED_COUPON_CODE);
+        testCouponString(tab, couponFetcher, View.GONE, null);
+    }
+
+    private void testCouponString(Tab tab, MockCouponPersistedTabDataFetcher fetcher,
+            int expectedVisibility, String expectedName) {
+        testGridSelected(mTabGridView, mGridModel);
+        CouponCardView couponCardView = mTabGridView.findViewById(R.id.coupon_info_box_outer);
+        TextView name = mTabGridView.findViewById(R.id.coupon_name);
+
+        mGridModel.set(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER, fetcher);
+        Assert.assertEquals(expectedVisibility, couponCardView.getVisibility());
+        if (expectedVisibility == View.VISIBLE) {
+            Assert.assertEquals(expectedName, name.getText());
+        }
+    }
+
     static class MockShoppingPersistedTabData extends ShoppingPersistedTabData {
         private PriceDrop mPriceDrop;
 
@@ -823,6 +914,49 @@
         }
     }
 
+    static class MockCouponPersistedTabData extends CouponPersistedTabData {
+        private Coupon mCoupon;
+
+        MockCouponPersistedTabData(Tab tab) {
+            super(tab);
+        }
+
+        public void setCoupon(String name, String code) {
+            mCoupon = new Coupon(name, code);
+        }
+
+        @Override
+        public Coupon getCoupon() {
+            return mCoupon;
+        }
+    }
+
+    /**
+     * Mock {@link TabListMediator.CouponPersistedTabDataFetcher} for testing purposes
+     */
+    static class MockCouponPersistedTabDataFetcher
+            extends TabListMediator.CouponPersistedTabDataFetcher {
+        private CouponPersistedTabData mCouponPersistedTabData;
+        MockCouponPersistedTabDataFetcher(Tab tab) {
+            super(tab);
+        }
+
+        public void setCouponStrings(String nameString, String codeString) {
+            mCouponPersistedTabData = new MockCouponPersistedTabData(mTab);
+            ((MockCouponPersistedTabData) mCouponPersistedTabData)
+                    .setCoupon(nameString, codeString);
+        }
+
+        public void setEmptyCoupon() {
+            mCouponPersistedTabData = new MockCouponPersistedTabData(mTab);
+        }
+
+        @Override
+        public void fetch(Callback<CouponPersistedTabData> callback) {
+            callback.onResult(mCouponPersistedTabData);
+        }
+    }
+
     @Test
     @MediumTest
     @UiThreadTest
@@ -957,4 +1091,11 @@
                 PriceTrackingFeatures.PRICE_TRACKING_PARAM, String.valueOf(value));
         FeatureList.setTestValues(testValues);
     }
+
+    private void setCouponsEnabledForTesting() {
+        FeatureList.TestValues testValues = new FeatureList.TestValues();
+
+        testValues.addFeatureFlagOverride(ChromeFeatureList.COMMERCE_COUPONS, true);
+        FeatureList.setTestValues(testValues);
+    }
 }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
index 8d0065f..298adbb 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -35,6 +35,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import static org.chromium.chrome.browser.flags.ChromeFeatureList.COMMERCE_COUPONS;
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS;
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.START_SURFACE_ANDROID;
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.STORE_HOURS;
@@ -1133,6 +1134,70 @@
     }
 
     @Test
+    public void testCouponFetcherActiveForForUngroupedTabs() {
+        prepareForCoupon();
+        resetWithRegularTabs(false);
+
+        assertThat(mModel.size(), equalTo(2));
+        assertThat(mModel.get(0).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER),
+                instanceOf(TabListMediator.CouponPersistedTabDataFetcher.class));
+        assertThat(mModel.get(1).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER),
+                instanceOf(TabListMediator.CouponPersistedTabDataFetcher.class));
+    }
+
+    @Test
+    public void testCouponFetcherInactiveForForGroupedTabs() {
+        prepareForCoupon();
+        resetWithRegularTabs(true);
+
+        assertThat(mModel.size(), equalTo(2));
+        assertNull(mModel.get(0).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER));
+        assertNull(mModel.get(1).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER));
+    }
+
+    @Test
+    public void testCouponFetcherGroupedThenUngrouped() {
+        prepareForCoupon();
+        resetWithRegularTabs(true);
+        assertThat(mModel.size(), equalTo(2));
+        assertNull(mModel.get(0).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER));
+        assertNull(mModel.get(1).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER));
+        resetWithRegularTabs(false);
+        assertThat(mModel.size(), equalTo(2));
+        assertThat(mModel.get(0).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER),
+                instanceOf(TabListMediator.CouponPersistedTabDataFetcher.class));
+        assertThat(mModel.get(1).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER),
+                instanceOf(TabListMediator.CouponPersistedTabDataFetcher.class));
+    }
+
+    @Test
+    public void testCouponFetcherUngroupedThenGrouped() {
+        prepareForCoupon();
+        resetWithRegularTabs(false);
+
+        assertThat(mModel.size(), equalTo(2));
+        assertThat(mModel.get(0).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER),
+                instanceOf(TabListMediator.CouponPersistedTabDataFetcher.class));
+        assertThat(mModel.get(1).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER),
+                instanceOf(TabListMediator.CouponPersistedTabDataFetcher.class));
+        resetWithRegularTabs(true);
+        assertThat(mModel.size(), equalTo(2));
+        assertNull(mModel.get(0).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER));
+        assertNull(mModel.get(1).model.get(TabProperties.COUPON_PERSISTED_TAB_DATA_FETCHER));
+    }
+
+    /**
+     * Set flags and initialize for verifying coupon annotations behavior
+     */
+    private void prepareForCoupon() {
+        CachedFeatureFlags.setForTesting(COMMERCE_COUPONS, true);
+        PriceTrackingFeatures.setIsSignedInAndSyncEnabledForTesting(true);
+        PersistedTabDataConfiguration.setUseTestConfig(true);
+        initAndAssertAllProperties();
+        setUpForTabGroupOperation(TabListMediatorType.TAB_SWITCHER, TabListMode.GRID);
+    }
+
+    @Test
     public void testStoreHoursFetcherActiveForForUngroupedTabs() {
         prepareForStoreHours();
         resetWithRegularTabs(false);
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni
index 5ae8b00..47d79306 100644
--- a/chrome/android/features/tab_ui/tab_management_java_sources.gni
+++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -7,6 +7,7 @@
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialog.java",
+  "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CouponUtilities.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/StoreTrackingUtilities.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java
index bfd10b867..1397f71 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java
@@ -19,12 +19,12 @@
  * background with the Activity visible.  One example is {@link BookmarkActivity} and its kin.
  */
 public abstract class SynchronousInitializationActivity extends ChromeBaseAppCompatActivity {
-    private static final String TAG = "SyncInitActivity";
-
     @CallSuper
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
+        // Make sure the native is initialized before calling super.onCreate(), as calling
+        // super.onCreate() will recreate fragments that might depend on the native code.
         ChromeBrowserInitializer.getInstance().handleSynchronousStartup();
+        super.onCreate(savedInstanceState);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabSheetContent.java
index ce25397..0c957e7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabSheetContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabSheetContent.java
@@ -18,6 +18,7 @@
 import androidx.annotation.DrawableRes;
 import androidx.annotation.Nullable;
 
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.UnownedUserDataSupplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.share.ShareDelegate;
@@ -60,6 +61,8 @@
     private final int mToolbarHeightPx;
     private final UnownedUserDataSupplier<ShareDelegate> mShareDelegateSupplier =
             new ShareDelegateSupplier();
+    private final ObservableSupplierImpl<Boolean> mBackPressStateChangedSupplier =
+            new ObservableSupplierImpl<>();
 
     private ViewGroup mToolbarView;
     private ViewGroup mSheetContentView;
@@ -92,6 +95,8 @@
 
         createThinWebView((int) (maxViewHeight * FULL_HEIGHT_RATIO), intentRequestTracker);
         createToolbarView();
+
+        mBackPressStateChangedSupplier.set(true);
     }
 
     /**
@@ -290,6 +295,16 @@
     }
 
     @Override
+    public ObservableSupplierImpl<Boolean> getBackPressStateChangedSupplier() {
+        return mBackPressStateChangedSupplier;
+    }
+
+    @Override
+    public void onBackPressed() {
+        mCloseButtonCallback.run();
+    }
+
+    @Override
     public int getSheetContentDescriptionStringId() {
         return R.string.ephemeral_tab_sheet_description;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImpl.java
index e1ba245f..1a43e0e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImpl.java
@@ -10,7 +10,7 @@
 
 import org.chromium.chrome.browser.translate.TranslateBridge;
 
-import java.util.LinkedHashSet;
+import java.util.List;
 
 /**
  * Controls how Translation triggering is handled for the {@link ContextualSearchManager}.
@@ -51,7 +51,7 @@
     public boolean needsTranslation(@Nullable String sourceLanguage) {
         if (TextUtils.isEmpty(sourceLanguage)) return false;
 
-        LinkedHashSet<String> languages = mTranslateBridgeWrapper.getModelLanguages();
+        List<String> languages = mTranslateBridgeWrapper.getNeverTranslateLanguages();
         for (String language : languages) {
             if (language.equals(sourceLanguage)) return false;
         }
@@ -65,7 +65,7 @@
 
     @Override
     public String getTranslateServiceFluentLanguages() {
-        return TextUtils.join(",", mTranslateBridgeWrapper.getModelLanguages());
+        return TextUtils.join(",", mTranslateBridgeWrapper.getNeverTranslateLanguages());
     }
 
     /**
@@ -82,11 +82,11 @@
         }
 
         /**
-         * @return The {@link LinkedHashSet} of language code strings that the Chrome Language Model
-         *         thinks the user knows, in order of most familiar to least familiar.
+         * @return The {@link List} of languages the user has set to never translate, in
+         *         alphabetical order.
          */
-        public LinkedHashSet<String> getModelLanguages() {
-            return TranslateBridge.getModelLanguages();
+        public List<String> getNeverTranslateLanguages() {
+            return TranslateBridge.getNeverTranslateLanguages();
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java
index 5bed26e..560550f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabRootUiCoordinator.java
@@ -211,6 +211,13 @@
         mCustomTabHeightStrategy.onPostInflationStartup();
     }
 
+    @Override
+    protected void setStatusBarScrimFraction(float scrimFraction) {
+        super.setStatusBarScrimFraction(scrimFraction);
+        // TODO(jinsukkim): Separate CCT scrim update action from status bar scrim stuff.
+        mCustomTabHeightStrategy.setScrimFraction(scrimFraction);
+    }
+
     /**
      * Delegates changing the background color to the {@link CustomTabHeightStrategy}.
      * Returns {@code true} if any action were taken, {@code false} if not.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabHeightStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabHeightStrategy.java
index 9d15aa6..ee5003b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabHeightStrategy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabHeightStrategy.java
@@ -61,4 +61,10 @@
         throw new IllegalStateException(
                 "Custom close animation should be performed only on partial CCT.");
     }
+
+    /**
+     * Set the scrim value to apply to partial CCT UI.
+     * @param scrimFraction Scrim fraction.
+     */
+    public void setScrimFraction(float scrimFraction) {}
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
index ab17b3d..3a64785 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
@@ -194,9 +194,7 @@
     }
 
     @Override
-    public void onClosingStateChanged(Tab tab, boolean closing) {
-        if (!closing) return;
-
+    public void onDestroyed(Tab tab) {
         if (ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_RETAINING_STATE)) {
             TabInteractionRecorder observer = TabInteractionRecorder.getFromTab(tab);
             if (observer != null) observer.onTabClosing();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java
index 06f74612..d2aef1e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java
@@ -128,6 +128,8 @@
     @Nullable
     private Runnable mFinishRunnable;
 
+    private int mToolbarColor;
+
     /** A callback to be called once the Custom Tab has been resized. */
     interface OnResizedCallback {
         /** The Custom Tab has been resized. */
@@ -428,11 +430,11 @@
         background.setCornerRadii(new float[] {toolbarCornerRadius, toolbarCornerRadius,
                 toolbarCornerRadius, toolbarCornerRadius, 0, 0, 0, 0});
         updateShadowOffset();
+        mToolbarColor = toolbar.getBackground().getColor();
         if (mDrawOutlineShadow) {
             int width = mActivity.getResources().getDimensionPixelSize(
                     R.dimen.custom_tabs_outline_width);
-            int color = toolbar.getBackground().getColor();
-            background.setStroke(width, toolbar.getToolbarHairlineColor(color));
+            background.setStroke(width, toolbar.getToolbarHairlineColor(mToolbarColor));
         }
 
         handleView.setBackground(background);
@@ -444,6 +446,23 @@
         mActivity.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
     }
 
+    @Override
+    public void setScrimFraction(float scrimFraction) {
+        int scrimColor = mActivity.getResources().getColor(R.color.default_scrim_color);
+        float scrimColorAlpha = (scrimColor >>> 24) / 255f;
+        int scrimColorOpaque = scrimColor & 0xFF000000;
+        int color = ColorUtils.getColorWithOverlay(
+                mToolbarColor, scrimColorOpaque, scrimFraction * scrimColorAlpha, false);
+
+        // Drag handle view is not part of CoordinatorLayout. As the root UI scrim changes,
+        // the handle view color needs updating to match it. This is a better way than running
+        // PCCT's own scrim coordinator since it can apply shape-aware scrim to the handle view
+        // that has the rounded corner.
+        View handleView = mActivity.findViewById(R.id.custom_tabs_handle_view);
+        GradientDrawable drawable = (GradientDrawable) handleView.getBackground();
+        drawable.setColor(color);
+    }
+
     private void initializeHeight() {
         mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
         mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollector.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollector.java
index 926c277..24cc68fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollector.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollector.java
@@ -38,9 +38,9 @@
 
     public ChromeFeedbackCollector(Activity activity, @Nullable String categoryTag,
             @Nullable String description, @Nullable ScreenshotSource screenshotSource,
-            InitParams initParams, Callback<FeedbackCollector> callback, Profile profile) {
+            InitParams initParams, Callback<FeedbackCollector> callback) {
         super(categoryTag, description, callback);
-        init(activity, screenshotSource, initParams, profile);
+        init(activity, screenshotSource, initParams);
     }
 
     @VisibleForTesting
@@ -75,6 +75,7 @@
         sources.add(new ConnectivityFeedbackSource(initParams.profile));
         sources.add(new SystemInfoFeedbackSource());
         sources.add(new ProcessIdFeedbackSource());
+        sources.add(new FamilyInfoFeedbackSource(initParams.profile));
 
         return sources;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollector.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollector.java
index 9c24f44..2401046 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollector.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollector.java
@@ -37,10 +37,10 @@
 
     public FeedFeedbackCollector(Activity activity, @Nullable String categoryTag,
             @Nullable String description, @Nullable ScreenshotSource screenshotSource,
-            InitParams initParams, Callback<FeedbackCollector> callback, Profile profile) {
+            InitParams initParams, Callback<FeedbackCollector> callback) {
         super(categoryTag, description, callback);
 
-        init(activity, screenshotSource, initParams, profile);
+        init(activity, screenshotSource, initParams);
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherImpl.java
index f3387f5..ccf04eb1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherImpl.java
@@ -91,7 +91,7 @@
         new ChromeFeedbackCollector(activity, null /* categoryTag */, null /* description */,
                 new ScreenshotTask(activity),
                 new ChromeFeedbackCollector.InitParams(profile, url, helpContext),
-                collector -> show(activity, helpContext, collector), profile);
+                collector -> show(activity, helpContext, collector));
     }
 
     /**
@@ -112,7 +112,7 @@
         new ChromeFeedbackCollector(activity, categoryTag, null /* description */,
                 new ScreenshotTask(activity, screenshotMode),
                 new ChromeFeedbackCollector.InitParams(profile, url, feedbackContext),
-                collector -> showFeedback(activity, collector), profile);
+                collector -> showFeedback(activity, collector));
     }
 
     /**
@@ -145,7 +145,7 @@
         new FeedFeedbackCollector(activity, categoryTag, null /* description */,
                 new ScreenshotTask(activity),
                 new FeedFeedbackCollector.InitParams(profile, url, feedContext),
-                collector -> showFeedback(activity, collector), profile);
+                collector -> showFeedback(activity, collector));
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerView.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerView.java
index f742b4a..d8ed302 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerView.java
@@ -12,6 +12,7 @@
 
 import androidx.annotation.Nullable;
 
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.chrome.R;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.content_public.browser.RenderCoordinates;
@@ -29,6 +30,8 @@
     private final View mThinWebView;
     private final WebContents mWebContents;
     private final int mToolbarHeightPx;
+    private final ObservableSupplierImpl<Boolean> mBackPressStateChangedSupplier =
+            new ObservableSupplierImpl<>();
     private Runnable mBackPressCallback;
 
     /**
@@ -51,6 +54,7 @@
         mContentView.setPadding(
                 /*left=*/0, /*top=*/mToolbarHeightPx, /*right=*/0, /*bottom=*/0);
         mContentView.addView(thinWebView, /*index=*/0);
+        mBackPressStateChangedSupplier.set(true);
     }
 
     /**
@@ -133,6 +137,16 @@
     }
 
     @Override
+    public ObservableSupplierImpl<Boolean> getBackPressStateChangedSupplier() {
+        return mBackPressStateChangedSupplier;
+    }
+
+    @Override
+    public void onBackPressed() {
+        mBackPressCallback.run();
+    }
+
+    @Override
     public int getSheetContentDescriptionStringId() {
         return R.string.payment_handler_sheet_description;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
index f4ad1137..2a107a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
@@ -47,7 +47,6 @@
 import org.chromium.chrome.browser.sync.settings.SyncPromoPreference;
 import org.chromium.chrome.browser.sync.settings.SyncPromoPreference.State;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils;
-import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor;
 import org.chromium.chrome.browser.tracing.settings.DeveloperSettings;
 import org.chromium.chrome.browser.ui.signin.TangibleSyncCoordinator;
@@ -212,9 +211,7 @@
 
         new AdaptiveToolbarStatePredictor(null).recomputeUiState(uiState -> {
             // We don't show the toolbar shortcut settings page if disabled from finch.
-            // Note, we can still have the old data collection experiment running for which
-            // |canShowUi| might be true. In that case, just hide the settings page.
-            if (uiState.canShowUi && !AdaptiveToolbarFeatures.isSingleVariantModeEnabled()) return;
+            if (uiState.canShowUi) return;
             getPreferenceScreen().removePreference(findPreference(PREF_TOOLBAR_SHORTCUT));
         });
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareButtonController.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareButtonController.java
index 846b257..aa202ba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareButtonController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareButtonController.java
@@ -16,7 +16,6 @@
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver;
 import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin;
@@ -42,11 +41,6 @@
  * whether NTP is shown).
  */
 public class ShareButtonController implements ButtonDataProvider, ConfigurationChangedObserver {
-    /**
-     * Default minimum width to show the share button.
-     */
-    public static final int MIN_WIDTH_DP = 360;
-
     // Context is used for fetching resources and launching preferences page.
     private final Context mContext;
 
@@ -68,11 +62,8 @@
     private ModalDialogManager mModalDialogManager;
     private ModalDialogManagerObserver mModalDialogManagerObserver;
 
-    private Integer mMinimumWidthDp;
     private int mScreenWidthDp;
 
-    private int mCurrentOrientation;
-
     /**
      * Creates ShareButtonController object.
      * @param context The Context for retrieving resources, etc.
@@ -190,17 +181,13 @@
 
     private void updateButtonVisibility(Tab tab) {
         if (tab == null || tab.getWebContents() == null || mTabProvider == null
-                || mTabProvider.get() == null || !isFeatureEnabled()) {
+                || mTabProvider.get() == null) {
             mButtonData.setCanShow(false);
             return;
         }
 
-        if (mMinimumWidthDp == null) {
-            mMinimumWidthDp = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
-                    ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR, "minimum_width", MIN_WIDTH_DP);
-        }
-
-        final boolean isDeviceWideEnough = mScreenWidthDp >= mMinimumWidthDp;
+        final boolean isDeviceWideEnough =
+                mScreenWidthDp >= AdaptiveToolbarFeatures.getDeviceMinimumWidthForShowingButton();
         if (mShareDelegateSupplier.get() == null || !isDeviceWideEnough) {
             mButtonData.setCanShow(false);
             return;
@@ -209,13 +196,6 @@
         mButtonData.setCanShow(mShareUtils.shouldEnableShare(tab));
     }
 
-    private static boolean isFeatureEnabled() {
-        return (AdaptiveToolbarFeatures.isSingleVariantModeEnabled()
-                       && AdaptiveToolbarFeatures.getSingleVariantMode()
-                               == AdaptiveToolbarButtonVariant.SHARE)
-                || AdaptiveToolbarFeatures.isCustomizationEnabled();
-    }
-
     private void notifyObservers(boolean hint) {
         for (ButtonDataObserver observer : mObservers) {
             observer.buttonDataChanged(hint);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java
index 95a5837..4877a55 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java
@@ -12,8 +12,7 @@
 import androidx.fragment.app.FragmentManager;
 
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeBaseAppCompatActivity;
-import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
+import org.chromium.chrome.browser.SynchronousInitializationActivity;
 import org.chromium.chrome.browser.ui.signin.SyncConsentFragmentBase;
 import org.chromium.components.browser_ui.modaldialog.AppModalPresenter;
 import org.chromium.ui.modaldialog.ModalDialogManager;
@@ -23,16 +22,11 @@
  * Allows the user to pick an account, sign in and enable sync. Started from Settings and various
  * sign-in promos. For more details see {@link SyncConsentFragmentBase}.
  */
-// TODO(https://crbug.com/820491): extend AsyncInitializationActivity.
-public class SyncConsentActivity extends ChromeBaseAppCompatActivity {
+public class SyncConsentActivity extends SynchronousInitializationActivity {
     private static final String ARGUMENT_FRAGMENT_ARGS = "SigninActivity.FragmentArgs";
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        // Make sure the native is initialized before calling super.onCreate(), as it might recreate
-        // SyncConsentFragment that currently depends on native. See https://crbug.com/983730.
-        ChromeBrowserInitializer.getInstance().handleSynchronousStartup();
-
         super.onCreate(savedInstanceState);
         setContentView(R.layout.signin_activity);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/supervised_user/ChildAccountFeedbackReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/supervised_user/ChildAccountFeedbackReporter.java
index 12e8af2..ab127936 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/supervised_user/ChildAccountFeedbackReporter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/supervised_user/ChildAccountFeedbackReporter.java
@@ -31,7 +31,7 @@
         new ChromeFeedbackCollector(activity, null /* categoryTag */, description,
                 new ScreenshotTask(activity),
                 new ChromeFeedbackCollector.InitParams(profile, url, null),
-                collector -> { sFeedbackReporter.reportFeedback(collector); }, profile);
+                collector -> { sFeedbackReporter.reportFeedback(collector); });
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
index 9f06f51..ffde7c2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -640,10 +640,7 @@
         }
 
         mAddToHomescreenIPHController = new AddToHomescreenIPHController(mActivity, mWindowAndroid,
-                mModalDialogManagerSupplier.get(), mAppMenuCoordinator.getAppMenuHandler(),
-                R.id.add_to_homescreen_id, () -> {
-                    return mToolbarManager.getMenuButtonView();
-                }, MessageDispatcherProvider.from(mWindowAndroid));
+                mModalDialogManagerSupplier.get(), MessageDispatcherProvider.from(mWindowAndroid));
         mLinkToTextIPHController = new LinkToTextIPHController(
                 mActivityTabProvider, mTabModelSelectorSupplier.get(), mProfileSupplier);
         mAddToHomescreenMostVisitedTileObserver = new AddToHomescreenMostVisitedTileClickObserver(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/DEPS
index 2cf5231b..183a8072 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/DEPS
@@ -14,6 +14,7 @@
   "+ui/android/java/src/org/chromium/ui",
   "+url/android",
   "+components/browser_ui/bottomsheet/android/java",
+  "+content/public/android/java/src/org/chromium/content_public",
 ]
 
 specific_include_rules = {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 1723169f..5f4f6a8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -36,6 +36,7 @@
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.base.task.PostTask;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.IntentHandler;
@@ -159,6 +160,7 @@
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.NavigationEntry;
 import org.chromium.content_public.browser.NavigationHandle;
+import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.net.NetError;
 import org.chromium.ui.base.DeviceFormFactor;
@@ -301,6 +303,8 @@
     private ObservableSupplierImpl<Boolean> mIsProgressBarVisibleSupplier =
             new ObservableSupplierImpl<>();
 
+    private boolean mIsDestroyed;
+
     private static class TabObscuringCallback implements Callback<Boolean> {
         private final TabObscuringHandler mTabObscuringHandler;
         /** A token held while the toolbar/omnibox is obscuring all visible tabs. */
@@ -733,8 +737,13 @@
             @Override
             public void onLoadStarted(Tab tab, boolean toDifferentDocument) {
                 if (!toDifferentDocument) return;
-                updateButtonStatus();
-                updateTabLoadingState(true);
+                if (ChromeFeatureList.isEnabled(
+                            ChromeFeatureList.DELAY_TOOLBAR_UPDATE_ON_LOAD_STARTED)) {
+                    PostTask.postTask(
+                            UiThreadTaskTraits.USER_BLOCKING, () -> updateTabLoadingState(true));
+                } else {
+                    updateTabLoadingState(true);
+                }
             }
 
             @Override
@@ -1419,6 +1428,8 @@
      * Call to tear down all of the toolbar dependencies.
      */
     public void destroy() {
+        mIsDestroyed = true;
+
         VrModuleProvider.unregisterVrModeObserver(mVrModeObserver);
 
         if (mInitializedWithNative) {
@@ -1943,6 +1954,8 @@
     }
 
     private void updateTabLoadingState(boolean updateUrl) {
+        if (mIsDestroyed) return;
+
         mLocationBarModel.notifySecurityStateChanged();
         if (updateUrl) {
             mLocationBarModel.notifyUrlChanged();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
index 49f5257e..9f794bc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -1163,7 +1163,7 @@
                 new ScrimCoordinator.SystemUiScrimDelegate() {
                     @Override
                     public void setStatusBarScrimFraction(float scrimFraction) {
-                        mStatusBarColorController.setStatusBarScrimFraction(scrimFraction);
+                        RootUiCoordinator.this.setStatusBarScrimFraction(scrimFraction);
                     }
 
                     @Override
@@ -1173,6 +1173,10 @@
                 coordinator.getContext().getColor(R.color.omnibox_focused_fading_background_color));
     }
 
+    protected void setStatusBarScrimFraction(float scrimFraction) {
+        mStatusBarColorController.setStatusBarScrimFraction(scrimFraction);
+    }
+
     protected void setLayoutStateProvider(LayoutStateProvider layoutStateProvider) {
         assert layoutStateProvider != null;
         assert mLayoutStateProvider == null : "The LayoutStateProvider should set at most once.";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java
index d6bbd28..baa2549 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java
@@ -27,6 +27,7 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.test.util.UiRestriction;
 
@@ -36,8 +37,8 @@
 // NOTE: Disable online detection so we we'll default to online on test bots with no network.
 @RunWith(ParameterizedRunner.class)
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@EnableFeatures({ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
 @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
 @Batch(Batch.PER_CLASS)
 public class ContextualSearchCriticalTest extends ContextualSearchInstrumentationBase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationTest.java
index 6fc5c51..fca67e1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationTest.java
@@ -23,6 +23,7 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.ui.test.util.UiRestriction;
 
 /**
@@ -32,9 +33,9 @@
 @RunWith(ParameterizedRunner.class)
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION,
         "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + ","
                 + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION})
+@EnableFeatures({ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
 @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
 @Batch(Batch.PER_CLASS)
 public class ContextualSearchInstrumentationTest extends ContextualSearchInstrumentationBase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
index e77f807..2168686 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -72,6 +72,7 @@
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.chrome.test.util.FullscreenTestUtils;
 import org.chromium.chrome.test.util.MenuUtils;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.external_intents.ExternalNavigationHandler;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
@@ -94,9 +95,9 @@
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 // NOTE: Disable online detection so we we'll default to online on test bots with no network.
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION,
         "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + ","
                 + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION})
+@EnableFeatures({ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
 @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
 @Batch(Batch.PER_CLASS)
 public class ContextualSearchManagerTest extends ContextualSearchInstrumentationBase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchObserverTest.java
index d85109da..d3d0c02 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchObserverTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchObserverTest.java
@@ -24,6 +24,7 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.gsa.GSAContextDisplaySelection;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.test.util.UiRestriction;
 
@@ -34,9 +35,9 @@
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 // NOTE: Disable online detection so we we'll default to online on test bots with no network.
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION,
         "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + ","
                 + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION})
+@EnableFeatures({ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
 @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
 @Batch(Batch.PER_CLASS)
 public class ContextualSearchObserverTest extends ContextualSearchInstrumentationBase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java
index 3a8bde8c..08906b2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java
@@ -15,7 +15,6 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.FeatureList;
-import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
@@ -26,6 +25,8 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.layouts.animation.CompositorAnimationHandler;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.browser_ui.widget.chips.ChipProperties;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
@@ -35,10 +36,10 @@
 /**
  * Tests the Related Searches Feature of Contextual Search using instrumentation tests.
  */
-@RunWith(BaseJUnit4ClassRunner.class)
+@RunWith(ChromeJUnit4ClassRunner.class)
 // NOTE: Disable online detection so we we'll default to online on test bots with no network.
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@EnableFeatures({ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
 @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
 @Batch(Batch.PER_CLASS)
 public class ContextualSearchRelatedSearchesTest extends ContextualSearchInstrumentationBase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java
index e668ed1..c62edc4d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java
@@ -33,6 +33,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.chrome.test.util.ChromeTabUtils;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.test.util.KeyUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -45,9 +46,9 @@
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 // NOTE: Disable online detection so we we'll default to online on test bots with no network.
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION,
         "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + ","
                 + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION})
+@EnableFeatures({ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
 @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
 @Batch(Batch.PER_CLASS)
 public class ContextualSearchSystemTest extends ContextualSearchInstrumentationBase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTriggerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTriggerTest.java
index fd80196..8b9826f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTriggerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTriggerTest.java
@@ -30,6 +30,7 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.content_public.browser.SelectionClient;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.test.util.UiRestriction;
@@ -40,8 +41,8 @@
 @RunWith(ParameterizedRunner.class)
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 // NOTE: Disable online detection so we we'll default to online on test bots with no network.
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@EnableFeatures({ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
 @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
 @Batch(Batch.PER_CLASS)
 public class ContextualSearchTriggerTest extends ContextualSearchInstrumentationBase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUnbatchedTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUnbatchedTest.java
index b69e600..0c5fd65 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUnbatchedTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUnbatchedTest.java
@@ -26,6 +26,7 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
@@ -35,9 +36,9 @@
 @RunWith(ParameterizedRunner.class)
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION,
         "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + ","
                 + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION})
+@EnableFeatures({ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION})
 @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
 // TODO(crbug.com/1338223):update the tests to be batched.
 @DoNotBatch(reason = "Tests cannot runn batched due to RecordHistogram#forgetHistogram method.")
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 1c0a4de..0430fadb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -79,6 +79,7 @@
 import org.chromium.base.test.util.CriteriaNotSatisfiedException;
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.DoNotBatch;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.Restriction;
@@ -158,6 +159,8 @@
  * Instrumentation tests for app menu, context menu, and toolbar of a {@link CustomTabActivity}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
+@DoNotBatch(reason = "Some tests are Testing CCT start up behavior. "
+                + "Unit test conversion tracked in crbug.com/1217031")
 public class CustomTabActivityTest {
     private static final int TIMEOUT_PAGE_LOAD_SECONDS = 10;
     private static final String TEST_PAGE = "/chrome/test/data/android/google.html";
@@ -1368,15 +1371,16 @@
 
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             final CustomTabActivity activity = mCustomTabActivityTestRule.getActivity();
-            activity.getComponent().resolveNavigationController().finish(FinishReason.OTHER);
+            activity.finish();
         });
-        CriteriaHelper.pollUiThread(
-                ()
-                        -> SharedPreferencesManager.getInstance().contains(
-                                   ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION)
-                        && SharedPreferencesManager.getInstance().contains(
-                                ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP));
+        CriteriaHelper.pollUiThread(() -> getActivity().isDestroyed());
 
+        Assert.assertTrue("CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION not recorded.",
+                SharedPreferencesManager.getInstance().contains(
+                        ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION));
+        Assert.assertTrue("CUSTOM_TABS_LAST_CLOSE_TIMESTAMP not recorded.",
+                SharedPreferencesManager.getInstance().contains(
+                        ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP));
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramTotalCountForTesting(
                         "CustomTabs.HadInteractionOnClose"));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsTest.java
index 790790c..fde15a6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsTest.java
@@ -4,10 +4,10 @@
 
 package org.chromium.chrome.browser.dom_distiller;
 
-import android.support.test.InstrumentationRegistry;
-
 import androidx.test.filters.SmallTest;
 
+import com.google.common.util.concurrent.AtomicDouble;
+
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -24,10 +24,14 @@
 import org.chromium.components.dom_distiller.core.DistilledPagePrefs;
 import org.chromium.components.dom_distiller.core.DomDistillerService;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.content_public.browser.test.util.UiUtils;
 import org.chromium.dom_distiller.mojom.FontFamily;
 import org.chromium.dom_distiller.mojom.Theme;
 
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * Test class for {@link DistilledPagePrefs}.
  */
@@ -41,6 +45,9 @@
 
     private static final double EPSILON = 1e-5;
 
+    private static final TimeUnit SEMAPHORE_TIMEOUT_UNIT = TimeUnit.SECONDS;
+    private static final long SEMAPHORE_TIMEOUT_VALUE = 5;
+
     @Before
     public void setUp() {
         getDistilledPagePrefs();
@@ -82,14 +89,13 @@
     @Feature({"DomDistiller"})
     public void testSingleObserverTheme() throws InterruptedException {
         TestingObserver testObserver = new TestingObserver();
-        mDistilledPagePrefs.addObserver(testObserver);
+        addObserver(testObserver);
 
         Assert.assertEquals(Theme.LIGHT, testObserver.getTheme());
         setTheme(Theme.DARK);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
         // Check that testObserver's theme has been updated,
-        Assert.assertEquals(Theme.DARK, testObserver.getTheme());
-        mDistilledPagePrefs.removeObserver(testObserver);
+        Assert.assertEquals(Theme.DARK, testObserver.getThemeAfterWaiting());
+        removeObserver(testObserver);
     }
 
     @Test
@@ -97,22 +103,24 @@
     @Feature({"DomDistiller"})
     public void testMultipleObserversTheme() throws InterruptedException {
         TestingObserver testObserverOne = new TestingObserver();
-        mDistilledPagePrefs.addObserver(testObserverOne);
+        addObserver(testObserverOne);
         TestingObserver testObserverTwo = new TestingObserver();
-        mDistilledPagePrefs.addObserver(testObserverTwo);
+        addObserver(testObserverTwo);
 
         setTheme(Theme.SEPIA);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        Assert.assertEquals(Theme.SEPIA, testObserverOne.getTheme());
-        Assert.assertEquals(Theme.SEPIA, testObserverTwo.getTheme());
-        mDistilledPagePrefs.removeObserver(testObserverOne);
+        Assert.assertEquals(Theme.SEPIA, testObserverOne.getThemeAfterWaiting());
+        Assert.assertEquals(Theme.SEPIA, testObserverTwo.getThemeAfterWaiting());
+        removeObserver(testObserverOne);
 
         setTheme(Theme.DARK);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
         // Check that testObserverOne's theme is not changed but testObserverTwo's is.
+        Assert.assertEquals(Theme.DARK, testObserverTwo.getThemeAfterWaiting());
+        // There is no simple way to safely wait for something not to happen unless we force a timed
+        // wait, which would slow down test runs. Since testObserverTwo has been invoked, we
+        // incorrectly assume that testObserverOne would have been as well to keep the test runtime
+        // short.
         Assert.assertEquals(Theme.SEPIA, testObserverOne.getTheme());
-        Assert.assertEquals(Theme.DARK, testObserverTwo.getTheme());
-        mDistilledPagePrefs.removeObserver(testObserverTwo);
+        removeObserver(testObserverTwo);
     }
 
     @Test
@@ -132,14 +140,13 @@
     @Feature({"DomDistiller"})
     public void testSingleObserverFontFamily() throws InterruptedException {
         TestingObserver testObserver = new TestingObserver();
-        mDistilledPagePrefs.addObserver(testObserver);
+        addObserver(testObserver);
 
         Assert.assertEquals(FontFamily.SANS_SERIF, testObserver.getFontFamily());
         setFontFamily(FontFamily.SERIF);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
         // Check that testObserver's font family has been updated.
-        Assert.assertEquals(FontFamily.SERIF, testObserver.getFontFamily());
-        mDistilledPagePrefs.removeObserver(testObserver);
+        Assert.assertEquals(FontFamily.SERIF, testObserver.getFontFamilyAfterWaiting());
+        removeObserver(testObserver);
     }
 
     @Test
@@ -147,22 +154,24 @@
     @Feature({"DomDistiller"})
     public void testMultipleObserversFontFamily() throws InterruptedException {
         TestingObserver testObserverOne = new TestingObserver();
-        mDistilledPagePrefs.addObserver(testObserverOne);
+        addObserver(testObserverOne);
         TestingObserver testObserverTwo = new TestingObserver();
-        mDistilledPagePrefs.addObserver(testObserverTwo);
+        addObserver(testObserverTwo);
 
         setFontFamily(FontFamily.MONOSPACE);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        Assert.assertEquals(FontFamily.MONOSPACE, testObserverOne.getFontFamily());
-        Assert.assertEquals(FontFamily.MONOSPACE, testObserverTwo.getFontFamily());
-        mDistilledPagePrefs.removeObserver(testObserverOne);
+        Assert.assertEquals(FontFamily.MONOSPACE, testObserverOne.getFontFamilyAfterWaiting());
+        Assert.assertEquals(FontFamily.MONOSPACE, testObserverTwo.getFontFamilyAfterWaiting());
+        removeObserver(testObserverOne);
 
         setFontFamily(FontFamily.SERIF);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
         // Check that testObserverOne's font family is not changed but testObserverTwo's is.
+        Assert.assertEquals(FontFamily.SERIF, testObserverTwo.getFontFamilyAfterWaiting());
+        // There is no simple way to safely wait for something not to happen unless we force a timed
+        // wait, which would slow down test runs. Since testObserverTwo has been invoked, we
+        // incorrectly assume that testObserverOne would have been as well to keep the test runtime
+        // short.
         Assert.assertEquals(FontFamily.MONOSPACE, testObserverOne.getFontFamily());
-        Assert.assertEquals(FontFamily.SERIF, testObserverTwo.getFontFamily());
-        mDistilledPagePrefs.removeObserver(testObserverTwo);
+        removeObserver(testObserverTwo);
     }
 
     @Test
@@ -182,14 +191,13 @@
     @Feature({"DomDistiller"})
     public void testSingleObserverFontScaling() throws InterruptedException {
         TestingObserver testObserver = new TestingObserver();
-        mDistilledPagePrefs.addObserver(testObserver);
+        addObserver(testObserver);
 
         Assert.assertNotEquals(1.1, testObserver.getFontScaling(), EPSILON);
         setFontScaling(1.1f);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
         // Check that testObserver's font scaling has been updated.
-        Assert.assertEquals(1.1, testObserver.getFontScaling(), EPSILON);
-        mDistilledPagePrefs.removeObserver(testObserver);
+        Assert.assertEquals(1.1, testObserver.getFontScalingAfterWaiting(), EPSILON);
+        removeObserver(testObserver);
     }
 
     @Test
@@ -197,22 +205,24 @@
     @Feature({"DomDistiller"})
     public void testMultipleObserversFontScaling() throws InterruptedException {
         TestingObserver testObserverOne = new TestingObserver();
-        mDistilledPagePrefs.addObserver(testObserverOne);
+        addObserver(testObserverOne);
         TestingObserver testObserverTwo = new TestingObserver();
-        mDistilledPagePrefs.addObserver(testObserverTwo);
+        addObserver(testObserverTwo);
 
         setFontScaling(1.3f);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        Assert.assertEquals(1.3, testObserverOne.getFontScaling(), EPSILON);
-        Assert.assertEquals(1.3, testObserverTwo.getFontScaling(), EPSILON);
-        mDistilledPagePrefs.removeObserver(testObserverOne);
+        Assert.assertEquals(1.3, testObserverOne.getFontScalingAfterWaiting(), EPSILON);
+        Assert.assertEquals(1.3, testObserverTwo.getFontScalingAfterWaiting(), EPSILON);
+        removeObserver(testObserverOne);
 
         setFontScaling(0.9f);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
         // Check that testObserverOne's font scaling is not changed but testObserverTwo's is.
+        Assert.assertEquals(0.9, testObserverTwo.getFontScalingAfterWaiting(), EPSILON);
+        // There is no simple way to safely wait for something not to happen unless we force a timed
+        // wait, which would slow down test runs. Since testObserverTwo has been invoked, we
+        // incorrectly assume that testObserverOne would have been as well to keep the test runtime
+        // short.
         Assert.assertEquals(1.3, testObserverOne.getFontScaling(), EPSILON);
-        Assert.assertEquals(0.9, testObserverTwo.getFontScaling(), EPSILON);
-        mDistilledPagePrefs.removeObserver(testObserverTwo);
+        removeObserver(testObserverTwo);
     }
 
     @Test
@@ -222,48 +232,74 @@
         TestingObserver test = new TestingObserver();
 
         // Should successfully add the observer the first time.
-        Assert.assertTrue(mDistilledPagePrefs.addObserver(test));
+        Assert.assertTrue(addObserver(test));
         // Observer cannot be added again, should return false.
-        Assert.assertFalse(mDistilledPagePrefs.addObserver(test));
+        Assert.assertFalse(addObserver(test));
 
         // Delete the observer the first time.
-        Assert.assertTrue(mDistilledPagePrefs.removeObserver(test));
+        Assert.assertTrue(removeObserver(test));
         // Observer cannot be deleted again, should return false.
-        Assert.assertFalse(mDistilledPagePrefs.removeObserver(test));
+        Assert.assertFalse(removeObserver(test));
     }
 
     private static class TestingObserver implements DistilledPagePrefs.Observer {
-        private int mFontFamily;
-        private int mTheme;
-        private float mFontScaling;
+        private final AtomicInteger mFontFamily = new AtomicInteger();
+        private Semaphore mFontFamilySemaphore = new Semaphore(0);
+        private final AtomicInteger mTheme = new AtomicInteger();
+        private Semaphore mThemeSemaphore = new Semaphore(0);
+        private final AtomicDouble mFontScaling = new AtomicDouble();
+        private Semaphore mFontScalingSemaphore = new Semaphore(0);
 
         public TestingObserver() {}
 
         public int getFontFamily() {
-            return mFontFamily;
+            return mFontFamily.get();
+        }
+
+        public int getFontFamilyAfterWaiting() throws InterruptedException {
+            Assert.assertTrue("Did not receive an update for font family",
+                    mFontFamilySemaphore.tryAcquire(
+                            SEMAPHORE_TIMEOUT_VALUE, SEMAPHORE_TIMEOUT_UNIT));
+            return getFontFamily();
         }
 
         @Override
         public void onChangeFontFamily(int font) {
-            mFontFamily = font;
+            mFontFamily.set(font);
+            mFontFamilySemaphore.release();
         }
 
         public int getTheme() {
-            return mTheme;
+            return mTheme.get();
+        }
+
+        public int getThemeAfterWaiting() throws InterruptedException {
+            Assert.assertTrue("Did not receive an update for theme",
+                    mThemeSemaphore.tryAcquire(SEMAPHORE_TIMEOUT_VALUE, SEMAPHORE_TIMEOUT_UNIT));
+            return getTheme();
         }
 
         @Override
         public void onChangeTheme(int theme) {
-            mTheme = theme;
+            mTheme.set(theme);
+            mThemeSemaphore.release();
         }
 
         public float getFontScaling() {
-            return mFontScaling;
+            return (float) mFontScaling.get();
+        }
+
+        public float getFontScalingAfterWaiting() throws InterruptedException {
+            Assert.assertTrue("Did not receive an update for font scaling",
+                    mFontScalingSemaphore.tryAcquire(
+                            SEMAPHORE_TIMEOUT_VALUE, SEMAPHORE_TIMEOUT_UNIT));
+            return getFontScaling();
         }
 
         @Override
         public void onChangeFontScaling(float scaling) {
-            mFontScaling = scaling;
+            mFontScaling.set(scaling);
+            mFontScalingSemaphore.release();
         }
     }
 
@@ -278,4 +314,18 @@
     private void setFontScaling(final float scaling) {
         TestThreadUtils.runOnUiThreadBlocking(() -> mDistilledPagePrefs.setFontScaling(scaling));
     }
+
+    private boolean removeObserver(TestingObserver testObserver) {
+        AtomicBoolean wasRemoved = new AtomicBoolean();
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> wasRemoved.set(mDistilledPagePrefs.removeObserver(testObserver)));
+        return wasRemoved.get();
+    }
+
+    private boolean addObserver(TestingObserver testObserver) {
+        AtomicBoolean wasAdded = new AtomicBoolean();
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> wasAdded.set(mDistilledPagePrefs.addObserver(testObserver)));
+        return wasAdded.get();
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
index 4afe135..594964c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
@@ -14,7 +14,6 @@
 
 import androidx.test.filters.MediumTest;
 
-import org.chromium.base.Callback;
 import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Assert;
@@ -23,6 +22,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import org.chromium.base.Callback;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadDialogIncognitoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadDialogIncognitoTest.java
index c0acdfd2..577faa76 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadDialogIncognitoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadDialogIncognitoTest.java
@@ -122,34 +122,6 @@
 
     @Test
     @LargeTest
-    public void testDangerousDownloadForOffTheRecordProfile() throws Exception {
-        // Showing a dangerous download dialog with an off-the-record profile.
-        showDangerousDialog(/*isOffTheRecord=*/true);
-
-        // Verify the Incognito warning message is shown.
-        waitForWarningVisibilityToBe(VISIBLE);
-
-        // Accept the dialog and verify the callback is called with true.
-        onView(withId(R.id.positive_button)).perform(ViewActions.click());
-        verify(mResultCallback).onResult(true);
-    }
-
-    @Test
-    @LargeTest
-    public void testDangerousDownloadForRegularProfile() throws Exception {
-        // Showing a dangerous download dialog with a regular profile.
-        showDangerousDialog(/*isOffTheRecord=*/false);
-
-        // Verify the Incognito warning message is NOT shown.
-        waitForWarningVisibilityToBe(GONE);
-
-        // Dismiss the dialog and verify the callback is called with false.
-        onView(withId(R.id.negative_button)).perform(ViewActions.click());
-        verify(mResultCallback).onResult(false);
-    }
-
-    @Test
-    @LargeTest
     public void testMixedContentDownloadForOffTheRecordProfile() throws Exception {
         // Showing a mixed content download dialog with an off-the-record profile.
         showMixedContentDialog(/*isOffTheRecord=*/true);
@@ -184,14 +156,6 @@
         });
     }
 
-    private void showDangerousDialog(boolean isOffTheRecord) {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Context mContext = mActivityTestRule.getActivity().getApplicationContext();
-            new DangerousDownloadDialog().show(mContext, mModalDialogManager, FILE_NAME,
-                    TOTAL_BYTES, ICON_ID, isOffTheRecord, mResultCallback);
-        });
-    }
-
     private void showMixedContentDialog(boolean isOffTheRecord) {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             Context mContext = mActivityTestRule.getActivity().getApplicationContext();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareButtonControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareButtonControllerTest.java
index 5d665be..79cc2af 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareButtonControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareButtonControllerTest.java
@@ -19,6 +19,7 @@
 import org.junit.rules.RuleChain;
 import org.junit.runner.RunWith;
 
+import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
@@ -27,6 +28,9 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.layouts.LayoutTestUtils;
 import org.chromium.chrome.browser.layouts.LayoutType;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures.AdaptiveToolbarButtonVariant;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor;
 import org.chromium.chrome.features.start_surface.StartSurfaceState;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
@@ -46,6 +50,7 @@
 /** Tests {@link ShareButtonController}. */
 
 @RunWith(ChromeJUnit4ClassRunner.class)
+@Batch(Batch.PER_CLASS)
 @EnableFeatures(
         {ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR, ChromeFeatureList.START_SURFACE_ANDROID})
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
@@ -67,15 +72,14 @@
 
     @Before
     public void setUp() {
+        AdaptiveToolbarStatePredictor.setToolbarStateForTesting(AdaptiveToolbarButtonVariant.SHARE);
         mActivityTestRule.startMainActivityOnBlankPage();
 
-        int minimumWidthDp = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
-                ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR, "minimum_width",
-                ShareButtonController.MIN_WIDTH_DP);
         int deviceWidth =
                 mActivityTestRule.getActivity().getResources().getConfiguration().screenWidthDp;
 
-        mButtonExpected = deviceWidth >= minimumWidthDp;
+        mButtonExpected =
+                deviceWidth >= AdaptiveToolbarFeatures.getDeviceMinimumWidthForShowingButton();
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtilTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtilTest.java
index a2286e8..a6478a7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtilTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtilTest.java
@@ -8,17 +8,14 @@
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
-import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
 import static org.chromium.chrome.browser.tasks.ReturnToChromeUtil.TAB_SWITCHER_ON_RETURN_MS_PARAM;
 import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.createTabStateFile;
 
 import android.app.Activity;
 import android.content.Intent;
-import android.os.Build.VERSION_CODES;
 import android.support.test.InstrumentationRegistry;
 import android.text.TextUtils;
 
-import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Assert;
@@ -31,7 +28,6 @@
 import org.chromium.base.ApplicationStatus.ActivityStateListener;
 import org.chromium.base.CommandLine;
 import org.chromium.base.library_loader.LibraryLoader;
-import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.params.ParameterAnnotations;
 import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
 import org.chromium.base.test.params.ParameterSet;
@@ -40,8 +36,8 @@
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.DoNotBatch;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.flags.CachedFeatureFlags;
@@ -53,14 +49,12 @@
 import org.chromium.chrome.browser.tabmodel.TestTabModelDirectory;
 import org.chromium.chrome.browser.tasks.ReturnToChromeUtil.ReturnToChromeBackPressHandler;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
-import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeApplicationTestUtils;
 import org.chromium.chrome.test.util.ChromeRenderTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
-import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.net.test.EmbeddedTestServer;
 import org.chromium.ui.test.util.UiDisableIf;
@@ -68,7 +62,6 @@
 
 import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -83,6 +76,7 @@
 // clang-format off
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         "force-fieldtrials=Study/Group"})
+@DoNotBatch(reason = "This test suite tests Clank's startup.")
 public class ReturnToChromeUtilTest {
     // clang-format on
     @ParameterAnnotations.ClassParameter
@@ -135,158 +129,6 @@
     }
 
     /**
-     * Test that overview mode is not triggered if the delay is longer than the interval between
-     * stop and start.
-     */
-    @Test
-    @SmallTest
-    @Feature({"ReturnToChrome"})
-    // clang-format off
-    @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS_PARAM + "/100000"
-            + "/start_surface_variation/single/open_ntp_instead_of_start/true"})
-    @DisableIf.Device(type = {UiDisableIf.TABLET}) // See https://crbug.com/1081754.
-    @DisabledTest(message="https://crbug.com/1130696")
-    public void testTabSwitcherModeNotTriggeredWithinThreshold() throws Exception {
-        // clang-format on
-        createTabStateFile(new int[] {0, 1});
-        startMainActivityWithURLWithoutCurrentTab(null);
-
-        Assert.assertEquals("single", StartSurfaceConfiguration.START_SURFACE_VARIATION.getValue());
-        TestThreadUtils.runOnUiThreadBlocking(
-                ()
-                        -> Assert.assertFalse(
-                                ReturnToChromeUtil.shouldShowStartSurfaceAsTheHomePage(
-                                        mActivityTestRule.getActivity())));
-
-        Assert.assertFalse(mActivityTestRule.getActivity().getLayoutManager().isLayoutVisible(
-                LayoutType.TAB_SWITCHER));
-
-        waitTabModelRestoration();
-        assertEquals(0,
-                RecordHistogram.getHistogramTotalCountForTesting(
-                        ReturnToChromeUtil.UMA_TIME_TO_GTS_FIRST_MEANINGFUL_PAINT));
-        assertEquals(2, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount());
-        Assert.assertFalse(mActivityTestRule.getActivity().getLayoutManager().isLayoutVisible(
-                LayoutType.TAB_SWITCHER));
-    }
-
-    /**
-     * Test that with {@link StartSurfaceConfiguration#START_SURFACE_OPEN_NTP_INSTEAD_OF_START}
-     * variation, overview mode is not triggered in Single-pane variation with NTP intent, even
-     * though the delay is longer than the interval between stop and start. Plus, a NTP should be
-     * created.
-     */
-    @Test
-    @SmallTest
-    @Feature({"ReturnToChrome"})
-    // clang-format off
-    @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS_PARAM + "/100000"
-            + "/start_surface_variation/single/open_ntp_instead_of_start/true"})
-    @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.O_MR1) // See https://crbug.com/1091268.
-    @DisabledTest(message="https://crbug.com/1144184")
-    public void testTabSwitcherModeNotTriggeredWithinThreshold_NTP() throws Exception {
-        // clang-format on
-        createTabStateFile(new int[] {0, 1});
-        startMainActivityWithURLWithoutCurrentTab(UrlConstants.NTP_URL);
-
-        Assert.assertEquals("single", StartSurfaceConfiguration.START_SURFACE_VARIATION.getValue());
-        TestThreadUtils.runOnUiThreadBlocking(
-                ()
-                        -> Assert.assertFalse(
-                                ReturnToChromeUtil.shouldShowStartSurfaceAsTheHomePage(
-                                        mActivityTestRule.getActivity())));
-
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            Assert.assertFalse(mActivityTestRule.getActivity().getLayoutManager().isLayoutVisible(
-                    LayoutType.TAB_SWITCHER));
-        }
-
-        waitTabModelRestoration();
-
-        // 3 tabs since we created NTP in this case.
-        assertEquals(3, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount());
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            Assert.assertFalse(mActivityTestRule.getActivity().getLayoutManager().isLayoutVisible(
-                    LayoutType.TAB_SWITCHER));
-        }
-    }
-
-    /**
-     * Test that overview mode is triggered in Single-pane variation with no tabs, even though
-     * the delay is longer than the interval between stop and start.
-     */
-    @Test
-    @SmallTest
-    @Feature({"ReturnToChrome"})
-    // clang-format off
-    @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS_PARAM + "/100000"
-            + "/start_surface_variation/single/open_ntp_instead_of_start/true"})
-    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) // See crbug.com/1146575.
-    @DisableIf.Device(type = {UiDisableIf.TABLET}) // See https://crbug.com/1081754.
-    public void testTabSwitcherModeTriggeredWithinThreshold_NoTab() throws TimeoutException {
-        // clang-format on
-        startMainActivityWithURLWithoutCurrentTab(null);
-
-        Assert.assertEquals("single", StartSurfaceConfiguration.START_SURFACE_VARIATION.getValue());
-        TestThreadUtils.runOnUiThreadBlocking(
-                ()
-                        -> Assert.assertTrue(ReturnToChromeUtil.isStartSurfaceEnabled(
-                                mActivityTestRule.getActivity())));
-
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            LayoutTestUtils.waitForLayout(
-                    mActivityTestRule.getActivity().getLayoutManager(), LayoutType.TAB_SWITCHER);
-            Assert.assertNotNull(mBackPressHandler.getHandleBackPressChangedSupplier().get());
-            Assert.assertFalse(mBackPressHandler.getHandleBackPressChangedSupplier().get());
-        }
-
-        waitTabModelRestoration();
-        assertEquals(0, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount());
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            LayoutTestUtils.waitForLayout(
-                    mActivityTestRule.getActivity().getLayoutManager(), LayoutType.TAB_SWITCHER);
-        }
-    }
-
-    /**
-     * Test that overview mode is triggered in Single-pane variation with NTP intent, even though
-     * the delay is longer than the interval between stop and start.
-     */
-    @Test
-    @SmallTest
-    @FlakyTest(message = "https://crbug.com/1237369")
-    @Feature({"ReturnToChrome"})
-    // clang-format off
-    @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS_PARAM + "/100000"
-            + "/start_surface_variation/single"})
-    @DisableIf.Device(type = {UiDisableIf.TABLET}) // See https://crbug.com/1081754.
-    @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.O_MR1) // See https://crbug.com/1091268.
-    public void testTabSwitcherModeTriggeredWithinThreshold_NTP() throws Exception {
-        // clang-format on
-        createTabStateFile(new int[] {0, 1});
-        startMainActivityWithURLWithoutCurrentTab(UrlConstants.NTP_URL);
-
-        Assert.assertEquals("single", StartSurfaceConfiguration.START_SURFACE_VARIATION.getValue());
-        TestThreadUtils.runOnUiThreadBlocking(
-                ()
-                        -> Assert.assertTrue(ReturnToChromeUtil.shouldShowStartSurfaceAsTheHomePage(
-                                mActivityTestRule.getActivity())));
-
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            Assert.assertTrue(mActivityTestRule.getActivity().getLayoutManager().isLayoutVisible(
-                    LayoutType.TAB_SWITCHER));
-        }
-
-        waitTabModelRestoration();
-        // Not 3 because we don't create a tab for NTP in this case.
-        assertEquals(2, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount());
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            Assert.assertTrue(mActivityTestRule.getActivity().getLayoutManager().isLayoutVisible(
-                    LayoutType.TAB_SWITCHER));
-        }
-    }
-
-    /**
      * Test that overview mode is triggered in Single-pane non stack tab switcher variation in
      * incognito mode when resuming from incognito mode.
      */
@@ -326,99 +168,6 @@
     }
 
     /**
-     * Test that overview mode is triggered if the delay is shorter than the interval between
-     * stop and start.
-     */
-    @Test
-    @SmallTest
-    @Feature({"ReturnToChrome"})
-    // clang-format off
-    @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS_PARAM + "/0"
-            + "/start_surface_variation/single"})
-    @DisabledTest(message = "https://crbug.com/1130696")
-    public void testTabSwitcherModeTriggeredBeyondThreshold() throws Exception {
-        // clang-format on
-        createTabStateFile(new int[] {0, 1});
-        startMainActivityWithURLWithoutCurrentTab(null);
-
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            LayoutTestUtils.waitForLayout(
-                    mActivityTestRule.getActivity().getLayoutManager(), LayoutType.TAB_SWITCHER);
-        }
-
-        waitTabModelRestoration();
-        assertEquals(2, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount());
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            LayoutTestUtils.waitForLayout(
-                    mActivityTestRule.getActivity().getLayoutManager(), LayoutType.TAB_SWITCHER);
-        }
-    }
-
-    /**
-     * Test that overview mode is triggered if the delay is shorter than the interval between
-     * stop and start.
-     */
-    @Test
-    @MediumTest
-    @Feature({"ReturnToChrome"})
-    // clang-format off
-    @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS_PARAM + "/0"
-            + "/start_surface_variation/single"})
-    @DisableIf.Build(sdk_is_less_than = VERSION_CODES.Q, sdk_is_greater_than = VERSION_CODES.O,
-            message = "crbug.com/1134361")
-    @DisabledTest(message = "https://crbug.com/1130696")
-    public void testTabSwitcherModeTriggeredBeyondThreshold_WarmStart() throws Exception {
-        // clang-format on
-        testTabSwitcherModeTriggeredBeyondThreshold();
-
-        // Redo to trigger warm startup UMA.
-        TabUiTestHelper.finishActivity(mActivityTestRule.getActivity());
-        mActivityTestRule.startMainActivityFromLauncher();
-
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            Assert.assertTrue(mActivityTestRule.getActivity().getLayoutManager().isLayoutVisible(
-                    LayoutType.TAB_SWITCHER));
-        }
-
-        CriteriaHelper.pollUiThread(
-                mActivityTestRule.getActivity().getTabModelSelector()::isTabStateInitialized);
-
-        assertEquals(2, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount());
-    }
-
-    /**
-     * Test that overview mode is triggered if the delay is shorter than the interval between
-     * stop and start.
-     */
-    @Test
-    @SmallTest
-    @Feature({"ReturnToChrome"})
-    // clang-format off
-    @CommandLineFlags.Add({BASE_PARAMS + "/" + TAB_SWITCHER_ON_RETURN_MS_PARAM + "/0"
-            + "/start_surface_variation/single"})
-    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) // See crbug.com/1146575.
-    public void testTabSwitcherModeTriggeredBeyondThreshold_NoTabs() throws TimeoutException {
-        // clang-format on
-        // Cannot use ChromeTabbedActivityTestRule.startMainActivityFromLauncher() because
-        // there's no tab.
-        startMainActivityWithURLWithoutCurrentTab(null);
-
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            LayoutTestUtils.waitForLayout(
-                    mActivityTestRule.getActivity().getLayoutManager(), LayoutType.TAB_SWITCHER);
-            Assert.assertNotNull(mBackPressHandler.getHandleBackPressChangedSupplier().get());
-            Assert.assertFalse(mBackPressHandler.getHandleBackPressChangedSupplier().get());
-        }
-
-        waitTabModelRestoration();
-        assertEquals(0, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount());
-        if (!mActivityTestRule.getActivity().isTablet()) {
-            LayoutTestUtils.waitForLayout(
-                    mActivityTestRule.getActivity().getLayoutManager(), LayoutType.TAB_SWITCHER);
-        }
-    }
-
-    /**
      * Ideally we should use {@link StartSurfaceTestUtils#createTabStateFile} so that we don't need
      * to create tabs with thumbnails and then restart. However, we cannot use stock serialized
      * TabStates like {@link TestTabModelDirectory#M26_GOOGLE_COM} because all of them have URLs
@@ -470,6 +219,23 @@
                 "10_web_tabs-select_last");
     }
 
+    private void testTabSwitcherModeTriggeredBeyondThreshold() throws Exception {
+        createTabStateFile(new int[] {0, 1});
+        startMainActivityWithURLWithoutCurrentTab(null);
+
+        if (!mActivityTestRule.getActivity().isTablet()) {
+            LayoutTestUtils.waitForLayout(
+                    mActivityTestRule.getActivity().getLayoutManager(), LayoutType.TAB_SWITCHER);
+        }
+
+        waitTabModelRestoration();
+        assertEquals(2, mActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount());
+        if (!mActivityTestRule.getActivity().isTablet()) {
+            LayoutTestUtils.waitForLayout(
+                    mActivityTestRule.getActivity().getLayoutManager(), LayoutType.TAB_SWITCHER);
+        }
+    }
+
     /**
      * Similar to {@link ChromeTabbedActivityTestRule#startMainActivityWithURL(String url)}
      * but skip verification and tasks regarding current tab.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonControllerTest.java
index 35b9b5c..44fd115 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonControllerTest.java
@@ -25,7 +25,9 @@
 
 import androidx.test.filters.MediumTest;
 
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
@@ -35,18 +37,17 @@
 import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.util.Batch;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.RequiresRestart;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
 import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler;
 import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler.VoiceInteractionSource;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures.AdaptiveToolbarButtonVariant;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
-import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
@@ -58,10 +59,7 @@
 /** Tests {@link VoiceToolbarButtonController}. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @Batch(Batch.PER_CLASS)
-@DisableFeatures({ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR})
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        "enable-features=" + ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR + "<FakeStudy",
-        "force-fieldtrials=FakeStudy/Enabled"})
+@EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
 public final class VoiceToolbarButtonControllerTest {
     private static final String TEST_PAGE = "/chrome/test/data/android/navigate/simple.html";
 
@@ -82,6 +80,16 @@
     @Mock
     VoiceRecognitionHandler mVoiceRecognitionHandler;
 
+    @BeforeClass
+    public static void setUpBeforeActivityLaunched() {
+        AdaptiveToolbarStatePredictor.setToolbarStateForTesting(AdaptiveToolbarButtonVariant.VOICE);
+    }
+
+    @AfterClass
+    public static void tearDownAfterActivityDestroyed() {
+        AdaptiveToolbarStatePredictor.setToolbarStateForTesting(null);
+    }
+
     @Before
     public void setUp() {
         doReturn(true).when(mVoiceRecognitionHandler).isVoiceSearchEnabled();
@@ -109,7 +117,6 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"force-fieldtrial-params=FakeStudy.Enabled:minimum_width_dp/0"})
     public void testVoiceButtonInToolbarIsDisabledOnNTP() {
         // Ensure the button starts visible.
         onView(isRoot()).check(waitForView(allOf(withId(R.id.optional_toolbar_button),
@@ -122,7 +129,6 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"force-fieldtrial-params=FakeStudy.Enabled:minimum_width_dp/0"})
     public void testVoiceButtonInToolbarIsMissingWhenVoiceDisabled() {
         doReturn(false).when(mVoiceRecognitionHandler).isVoiceSearchEnabled();
 
@@ -134,7 +140,6 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"force-fieldtrial-params=FakeStudy.Enabled:minimum_width_dp/0"})
     public void testVoiceButtonDisabledOnIncognito() {
         // Ensure the button starts visible.
         onView(isRoot()).check(waitForView(allOf(withId(R.id.optional_toolbar_button),
@@ -147,7 +152,6 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"force-fieldtrial-params=FakeStudy.Enabled:minimum_width_dp/0"})
     public void testVoiceButtonInToolbarIsDisabledDuringModal() {
         // Ensure the button starts visible.
         onView(isRoot()).check(waitForView(allOf(withId(R.id.optional_toolbar_button),
@@ -188,7 +192,6 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"force-fieldtrial-params=FakeStudy.Enabled:minimum_width_dp/0"})
     public void testVoiceButtonInToolbarStartsVoiceRecognition() {
         onViewWaiting(allOf(withId(R.id.optional_toolbar_button), isDisplayed(), isEnabled(),
                               withContentDescription(mButtonString)))
@@ -196,12 +199,4 @@
 
         verify(mVoiceRecognitionHandler).startVoiceRecognition(VoiceInteractionSource.TOOLBAR);
     }
-
-    @Test
-    @MediumTest
-    @RequiresRestart
-    @CommandLineFlags.Add({"force-fieldtrial-params=FakeStudy.Enabled:minimum_width_dp/200000"})
-    public void testVoiceButtonInToolbarScreenNotWideEnough() {
-        assertButtonMissingOrNonVoice();
-    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerPhoneTest.java
index 1ab0847b..88eba71 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerPhoneTest.java
@@ -26,7 +26,9 @@
 
 import org.hamcrest.Matchers;
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
@@ -39,6 +41,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
@@ -55,7 +58,8 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @Batch(Batch.PER_CLASS)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        "enable-features=" + ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR + "<Study",
+        "enable-features=" + ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2
+                + "<Study",
         "force-fieldtrials=Study/Group", "force-fieldtrial-params=Study.Group:mode/always-new-tab"})
 @DisableIf.Device(type = {UiDisableIf.TABLET})
 public class OptionalNewTabButtonControllerPhoneTest {
@@ -72,6 +76,17 @@
     private String mTestPageUrl;
     private String mButtonDescription;
 
+    @BeforeClass
+    public static void setUpBeforeActivityLaunched() {
+        AdaptiveToolbarStatePredictor.setToolbarStateForTesting(
+                AdaptiveToolbarButtonVariant.NEW_TAB);
+    }
+
+    @AfterClass
+    public static void tearDownAfterActivityDestroyed() {
+        AdaptiveToolbarStatePredictor.setToolbarStateForTesting(null);
+    }
+
     @Before
     public void setUp() {
         mTestPageUrl = sActivityTestRule.getTestServer().getURL(TEST_PAGE);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerTabletTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerTabletTest.java
index 7fcb1ce9..07731f8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerTabletTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerTabletTest.java
@@ -15,7 +15,9 @@
 import androidx.test.filters.MediumTest;
 
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
@@ -27,6 +29,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
@@ -59,6 +62,17 @@
 
     private String mTestPageUrl;
 
+    @BeforeClass
+    public static void setUpBeforeActivityLaunched() {
+        AdaptiveToolbarStatePredictor.setToolbarStateForTesting(
+                AdaptiveToolbarButtonVariant.NEW_TAB);
+    }
+
+    @AfterClass
+    public static void tearDownAfterActivityDestroyed() {
+        AdaptiveToolbarStatePredictor.setToolbarStateForTesting(null);
+    }
+
     @Before
     public void setUp() {
         mTestPageUrl = sActivityTestRule.getTestServer().getURL(TEST_PAGE);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImplTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImplTest.java
index 0639a2d..380ce6b3 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImplTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslationImplTest.java
@@ -23,7 +23,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchTranslationImpl.TranslateBridgeWrapper;
 
-import java.util.LinkedHashSet;
+import java.util.ArrayList;
 
 /**
  * Tests the {@link ContextualSearchTranslationImpl} class.
@@ -33,18 +33,18 @@
     private static final String ENGLISH = "en";
     private static final String SPANISH = "es";
     private static final String GERMAN = "de";
-    private static final LinkedHashSet<String> ENGLISH_AND_SPANISH;
+    private static final ArrayList<String> ENGLISH_AND_SPANISH;
     static {
-        LinkedHashSet<String> langs = new LinkedHashSet<String>();
+        ArrayList<String> langs = new ArrayList<String>();
         langs.add(ENGLISH);
         langs.add(SPANISH);
         ENGLISH_AND_SPANISH = langs;
     }
-    private static final LinkedHashSet<String> ENGLISH_SET;
+    private static final ArrayList<String> ENGLISH_LIST;
     static {
-        LinkedHashSet<String> langs = new LinkedHashSet<String>();
+        ArrayList<String> langs = new ArrayList<String>();
         langs.add(ENGLISH);
-        ENGLISH_SET = langs;
+        ENGLISH_LIST = langs;
     }
 
     @Mock
@@ -64,36 +64,44 @@
 
     @Test
     @Feature("TranslateUtilities")
-    public void testNeedsTranslationEmptyModelLanguages() {
-        doReturn(new LinkedHashSet<String>()).when(mTranslateBridgeWrapperMock).getModelLanguages();
+    public void testNeedsTranslationEmptyFluentLanguages() {
+        doReturn(new ArrayList<String>())
+                .when(mTranslateBridgeWrapperMock)
+                .getNeverTranslateLanguages();
         assertThat(mImpl.needsTranslation(ENGLISH), is(true));
     }
 
     @Test
     @Feature("TranslateUtilities")
-    public void testNeedsTranslationUserModelLanguages() {
-        doReturn(ENGLISH_SET).when(mTranslateBridgeWrapperMock).getModelLanguages();
+    public void testNeedsTranslationOneFluentLanguage() {
+        doReturn(ENGLISH_LIST).when(mTranslateBridgeWrapperMock).getNeverTranslateLanguages();
         assertThat(mImpl.needsTranslation(ENGLISH), is(false));
     }
 
     @Test
     @Feature("TranslateUtilities")
-    public void testNeedsTranslationMultipleModelLanguages() {
-        doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages();
+    public void testNeedsTranslationMultipleFluentLanguages() {
+        doReturn(ENGLISH_AND_SPANISH)
+                .when(mTranslateBridgeWrapperMock)
+                .getNeverTranslateLanguages();
         assertThat(mImpl.needsTranslation(ENGLISH), is(false));
     }
 
     @Test
     @Feature("TranslateUtilities")
-    public void testNeedsTranslationOtherModelLanguage() {
-        doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages();
+    public void testNeedsTranslationOtherFluentLanguage() {
+        doReturn(ENGLISH_AND_SPANISH)
+                .when(mTranslateBridgeWrapperMock)
+                .getNeverTranslateLanguages();
         assertThat(mImpl.needsTranslation(GERMAN), is(true));
     }
 
     @Test
     @Feature("TranslateUtilities")
     public void testGetFluentLanguages() {
-        doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages();
+        doReturn(ENGLISH_AND_SPANISH)
+                .when(mTranslateBridgeWrapperMock)
+                .getNeverTranslateLanguages();
         assertThat(mImpl.getTranslateServiceFluentLanguages(), is(ENGLISH + "," + SPANISH));
     }
 
@@ -107,26 +115,30 @@
     @Test
     @Feature("TranslateUtilities")
     public void testForceTranslateIfNeededWhenNeeded() {
-        doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages();
+        doReturn(ENGLISH_AND_SPANISH)
+                .when(mTranslateBridgeWrapperMock)
+                .getNeverTranslateLanguages();
         doNothing().when(mRequest).forceTranslation(any(), any());
         when(mRequest.isTranslationForced()).thenReturn(true);
 
         mImpl.forceTranslateIfNeeded(mRequest, GERMAN, true);
 
         assertThat(mRequest.isTranslationForced(), is(true));
-        verify(mTranslateBridgeWrapperMock).getModelLanguages();
+        verify(mTranslateBridgeWrapperMock).getNeverTranslateLanguages();
         verify(mRequest).forceTranslation(GERMAN, null);
     }
 
     @Test
     @Feature("TranslateUtilities")
     public void testForceTranslateIfNeededWhenNotNeeded() {
-        doReturn(ENGLISH_AND_SPANISH).when(mTranslateBridgeWrapperMock).getModelLanguages();
+        doReturn(ENGLISH_AND_SPANISH)
+                .when(mTranslateBridgeWrapperMock)
+                .getNeverTranslateLanguages();
 
         mImpl.forceTranslateIfNeeded(mRequest, ENGLISH, true);
 
         assertThat(mRequest.isTranslationForced(), is(false));
-        verify(mTranslateBridgeWrapperMock).getModelLanguages();
+        verify(mTranslateBridgeWrapperMock).getNeverTranslateLanguages();
         verify(mRequest, never()).forceTranslation(any(), any());
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollectorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollectorTest.java
index 89c58f5..89d59a87 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollectorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollectorTest.java
@@ -10,12 +10,10 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
 
 import android.app.Activity;
 import android.graphics.Bitmap;
@@ -45,9 +43,6 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
-import org.chromium.components.signin.base.CoreAccountInfo;
-import org.chromium.components.signin.identitymanager.IdentityManager;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -67,14 +62,11 @@
     private Activity mActivity;
     @Mock
     private Profile mProfile;
-    @Mock
-    private CoreAccountInfo mAccountInfo;
 
     // Test constants.
     private static final String CATEGORY_TAG = "category_tag";
     private static final String DESCRIPTION = "description";
     private static final String FEEDBACK_CONTEXT = "feedback_context";
-    private static final String ACCOUNT_IN_USE = "foo@gmail.com";
     private static final String KEY_1 = "key1";
     private static final String KEY_2 = "key2";
     private static final String KEY_3 = "key3";
@@ -249,8 +241,8 @@
                 @Nullable String feedbackContext, @Nullable ScreenshotSource screenshotSource,
                 Callback<FeedbackCollector> callback) {
             super(activity, categoryTag, description, screenshotSource,
-                    new ChromeFeedbackCollector.InitParams(profile, url, feedbackContext), callback,
-                    null);
+                    new ChromeFeedbackCollector.InitParams(profile, url, feedbackContext),
+                    callback);
         }
 
         // ChromeFeedbackCollector implementation.
@@ -274,20 +266,11 @@
     @Before
     public void setUp() {
         ThreadUtils.setUiThread(Looper.getMainLooper());
-
-        when(mAccountInfo.getEmail()).thenReturn(ACCOUNT_IN_USE);
-        IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
-        when(IdentityServicesProvider.get().getIdentityManager(any()))
-                .thenReturn(mock(IdentityManager.class));
-        when(IdentityServicesProvider.get().getIdentityManager(any()).getPrimaryAccountInfo(
-                     anyInt()))
-                .thenReturn(mAccountInfo);
     }
 
     @After
     public void tearDown() {
         ThreadUtils.setUiThread(null);
-        IdentityServicesProvider.setInstanceForTests(null);
     }
 
     @Test
@@ -337,7 +320,6 @@
             assertEquals(CATEGORY_TAG, collector.getCategoryTag());
             assertEquals(DESCRIPTION, collector.getDescription());
             assertNull(collector.getScreenshot());
-            assertEquals(ACCOUNT_IN_USE, collector.getAccountInUse());
         });
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollectorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollectorTest.java
index fda5365..1536d85 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollectorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollectorTest.java
@@ -7,12 +7,9 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -38,10 +35,7 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.test.util.browser.Features;
-import org.chromium.components.signin.base.CoreAccountInfo;
-import org.chromium.components.signin.identitymanager.IdentityManager;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -64,8 +58,6 @@
     private Activity mActivity;
     @Mock
     private Profile mProfile;
-    @Mock
-    private CoreAccountInfo mAccountInfo;
 
     // Test constants.
     private static final String CATEGORY_TAG = "category_tag";
@@ -98,8 +90,7 @@
                 @Nullable ScreenshotSource screenshotSource,
                 @Nullable Map<String, String> feedContext, Callback<FeedbackCollector> callback) {
             super(activity, categoryTag, description, screenshotSource,
-                    new FeedFeedbackCollector.InitParams(profile, url, feedContext), callback,
-                    null);
+                    new FeedFeedbackCollector.InitParams(profile, url, feedContext), callback);
         }
 
         // Override the async feedback sources to return an empty list, so we are only testing ths
@@ -114,19 +105,11 @@
     @Before
     public void setUp() {
         ThreadUtils.setUiThread(Looper.getMainLooper());
-        when(mAccountInfo.getEmail()).thenReturn(null);
-        IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
-        when(IdentityServicesProvider.get().getIdentityManager(any()))
-                .thenReturn(mock(IdentityManager.class));
-        when(IdentityServicesProvider.get().getIdentityManager(any()).getPrimaryAccountInfo(
-                     anyInt()))
-                .thenReturn(mAccountInfo);
     }
 
     @After
     public void tearDown() {
         ThreadUtils.setUiThread(null);
-        IdentityServicesProvider.setInstanceForTests(null);
     }
 
     @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/share/ShareButtonControllerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/share/ShareButtonControllerUnitTest.java
index 57e36f2..404a507 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/share/ShareButtonControllerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/share/ShareButtonControllerUnitTest.java
@@ -101,7 +101,7 @@
 
         doReturn(mTab).when(mTabProvider).get();
         doReturn(mContext).when(mTab).getContext();
-        mConfiguration.screenWidthDp = ShareButtonController.MIN_WIDTH_DP + WIDTH_DELTA;
+        mConfiguration.screenWidthDp = AdaptiveToolbarFeatures.DEFAULT_MIN_WIDTH_DP + WIDTH_DELTA;
         doReturn(mConfiguration).when(mResources).getConfiguration();
 
         doReturn(mock(WebContents.class)).when(mTab).getWebContents();
@@ -152,7 +152,7 @@
     @Test
     @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
     public void testDoNotShowWhenTooNarrow() {
-        mConfiguration.screenWidthDp = ShareButtonController.MIN_WIDTH_DP - 1;
+        mConfiguration.screenWidthDp = AdaptiveToolbarFeatures.DEFAULT_MIN_WIDTH_DP - 1;
         mShareButtonController.onConfigurationChanged(mConfiguration);
 
         ButtonData buttonData = mShareButtonController.get(mTab);
@@ -164,7 +164,7 @@
     @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
     public void testDoShowWhenWideEnough() {
         doReturn("https").when(mMockGurl).getScheme();
-        mConfiguration.screenWidthDp = ShareButtonController.MIN_WIDTH_DP;
+        mConfiguration.screenWidthDp = AdaptiveToolbarFeatures.DEFAULT_MIN_WIDTH_DP;
         mShareButtonController.onConfigurationChanged(mConfiguration);
 
         ButtonData buttonData = mShareButtonController.get(mTab);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImplTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImplTest.java
index 79db6842..bd7b952 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImplTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImplTest.java
@@ -5,17 +5,26 @@
 package org.chromium.chrome.browser.tabmodel;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
+import org.robolectric.annotation.LooperMode;
+import org.robolectric.shadows.ShadowLooper;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
@@ -34,6 +43,7 @@
  */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
+@LooperMode(LooperMode.Mode.PAUSED)
 public class TabModelSelectorImplTest {
     // Test activity type that does not restore tab on cold restart.
     // Any type other than ActivityType.TABBED works.
@@ -47,6 +57,10 @@
     TabDelegateFactory mTabDelegateFactory;
     @Mock
     NextTabPolicySupplier mNextTabPolicySupplier;
+    @Mock
+    IncognitoTabModelObserver.IncognitoReauthDialogDelegate mIncognitoReauthDialogDelegateMock;
+    @Mock
+    TabModelSelectorObserver mTabModelSelectorObserverMock;
 
     private TabModelSelectorImpl mTabModelSelector;
     private MockTabCreatorManager mTabCreatorManager;
@@ -104,4 +118,61 @@
         Assert.assertEquals("tab shouldn't be removed while reparenting is in progress", 1,
                 mTabModelSelector.getModel(false).getCount());
     }
+
+    /**
+     * A test method to verify that {@link
+     * IncognitoReauthDialogDelegate#OnBeforeIncognitoTabModelSelected} gets called before any other
+     * {@link TabModelSelectorObserver} listening to {@link
+     * TabModelSelectorObserver#onTabModelSelected}.
+     */
+    @Test
+    @SmallTest
+    public void
+    testIncognitoReauthDialogDelegate_OnBeforeIncognitoTabModelSelected_called_Before() {
+        doNothing().when(mIncognitoReauthDialogDelegateMock).onBeforeIncognitoTabModelSelected();
+        doNothing().when(mTabModelSelectorObserverMock).onTabModelSelected(any(), any());
+        mTabModelSelector.setIncognitoReauthDialogDelegate(mIncognitoReauthDialogDelegateMock);
+        mTabModelSelector.addObserver(mTabModelSelectorObserverMock);
+
+        InOrder order = inOrder(mIncognitoReauthDialogDelegateMock, mTabModelSelectorObserverMock);
+        mTabModelSelector.selectModel(/*incognito=*/true);
+
+        order.verify(mIncognitoReauthDialogDelegateMock, times(1))
+                .onBeforeIncognitoTabModelSelected();
+        order.verify(mTabModelSelectorObserverMock, times(1)).onTabModelSelected(any(), any());
+    }
+
+    /**
+     * A test method to verify that {@link
+     * IncognitoReauthDialogDelegate#onAfterRegularTabModelChanged} gets called after any other
+     * {@link TabModelSelectorObserver} listening to {@link TabModelSelectorObserver#onChange()}.
+     */
+    @Test
+    @SmallTest
+    public void testIncognitoReauthDialogDelegate_onAfterRegularTabModelChanged() {
+        // Start-off with an Incognito tab model. This is needed to set up the environment.
+        mTabModelSelector.selectModel(/*incognito=*/true);
+        // The above calls posts a tasks which can get executed after we add
+        // mTabModelSelectorObserverMock below and interfering with the verify onChange test below.
+        // Therefore execute that task immediately now.
+        ShadowLooper.shadowMainLooper().idle();
+        // Add the observers now to prevent any firing from the previous selectModel which is
+        // separate from the actual test.
+        mTabModelSelector.setIncognitoReauthDialogDelegate(mIncognitoReauthDialogDelegateMock);
+        mTabModelSelector.addObserver(mTabModelSelectorObserverMock);
+
+        doNothing().when(mIncognitoReauthDialogDelegateMock).onAfterRegularTabModelChanged();
+        doNothing().when(mTabModelSelectorObserverMock).onTabModelSelected(any(), any());
+        doNothing().when(mTabModelSelectorObserverMock).onChange();
+
+        InOrder order = inOrder(mTabModelSelectorObserverMock, mIncognitoReauthDialogDelegateMock);
+        mTabModelSelector.selectModel(/*incognito=*/false);
+        verify(mTabModelSelectorObserverMock, times(1)).onTabModelSelected(any(), any());
+
+        // The onChange method below is posted as a task to the main looper, and therefore we need
+        // to wait until it gets executed.
+        ShadowLooper.shadowMainLooper().idle();
+        order.verify(mTabModelSelectorObserverMock, times(1)).onChange();
+        order.verify(mIncognitoReauthDialogDelegateMock, times(1)).onAfterRegularTabModelChanged();
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tasks/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/OWNERS
index c2dc2bc..8240af0 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tasks/OWNERS
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/OWNERS
@@ -1 +1,4 @@
 file://chrome/android/java/src/org/chromium/chrome/browser/tasks/OWNERS
+
+per-file ReturnToChromeUtilUnitTest.java=hanxi@chromium.org
+per-file ReturnToChromeUtilUnitTest.java=spdonghao@chromium.org
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtilUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtilUnitTest.java
new file mode 100644
index 0000000..abad01e
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtilUnitTest.java
@@ -0,0 +1,224 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tasks;
+
+import static org.mockito.Mockito.doReturn;
+
+import static org.chromium.chrome.browser.tasks.ReturnToChromeUtil.TAB_SWITCHER_ON_RETURN_MS;
+import static org.chromium.chrome.features.start_surface.StartSurfaceConfiguration.START_SURFACE_OPEN_NTP_INSTEAD_OF_START;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import org.chromium.base.CommandLine;
+import org.chromium.base.IntentUtils;
+import org.chromium.base.SysUtils;
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.JniMocker;
+import org.chromium.chrome.browser.ChromeInactivityTracker;
+import org.chromium.chrome.browser.flags.CachedFeatureFlags;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.homepage.HomepageManager;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tasks.ReturnToChromeUtilUnitTest.ShadowHomepageManager;
+import org.chromium.chrome.browser.tasks.ReturnToChromeUtilUnitTest.ShadowSysUtils;
+import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
+import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.embedder_support.util.UrlConstants;
+import org.chromium.components.url_formatter.UrlFormatter;
+import org.chromium.components.url_formatter.UrlFormatterJni;
+import org.chromium.ui.base.DeviceFormFactor;
+import org.chromium.url.JUnitTestGURLs;
+
+/** Unit tests for {@link ReturnToChromeUtil} class. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {ShadowHomepageManager.class, ShadowSysUtils.class})
+public class ReturnToChromeUtilUnitTest {
+    /** Shadow for {@link HomepageManager}. */
+    @Implements(HomepageManager.class)
+    static class ShadowHomepageManager {
+        static String sHomepageUrl;
+
+        @Implementation
+        public static boolean isHomepageEnabled() {
+            return true;
+        }
+
+        @Implementation
+        public static String getHomepageUri() {
+            return sHomepageUrl;
+        }
+    }
+
+    @Implements(SysUtils.class)
+    static class ShadowSysUtils {
+        @Implementation
+        public static boolean isLowEndDevice() {
+            return false;
+        }
+    }
+
+    @Rule
+    public TestRule mProcessor = new Features.JUnitProcessor();
+    @Rule
+    public JniMocker mJniMocker = new JniMocker();
+    @Mock
+    private UrlFormatter.Natives mUrlFormatterJniMock;
+    @Mock
+    private Context mContext;
+    @Mock
+    private TabModelSelector mTabModelSelector;
+    @Mock
+    private Intent mIntent;
+    @Mock
+    private ChromeInactivityTracker mInactivityTracker;
+    @Mock
+    private Resources mResources;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mJniMocker.mock(UrlFormatterJni.TEST_HOOKS, mUrlFormatterJniMock);
+        doReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.NTP_URL))
+                .when(mUrlFormatterJniMock)
+                .fixupUrl(UrlConstants.NTP_NON_NATIVE_URL);
+
+        LibraryLoader.getInstance().setLibrariesLoadedForNativeTests();
+        Assert.assertTrue(LibraryLoader.getInstance().isInitialized());
+
+        CachedFeatureFlags.setForTesting(ChromeFeatureList.START_SURFACE_ANDROID, true);
+
+        // HomepageManager:
+        ShadowHomepageManager.sHomepageUrl = UrlConstants.NTP_NON_NATIVE_URL;
+        Assert.assertEquals(UrlConstants.NTP_NON_NATIVE_URL, HomepageManager.getHomepageUri());
+        Assert.assertTrue(HomepageManager.isHomepageEnabled());
+
+        // Low end devices:
+        Assert.assertFalse(SysUtils.isLowEndDevice());
+
+        // Sets accessibility:
+        StartSurfaceConfiguration.SUPPORT_ACCESSIBILITY.setForTesting(true);
+        ChromeAccessibilityUtil.get().setAccessibilityEnabledForTesting(false);
+
+        // Sets for !DeviceFormFactor.isNonMultiDisplayContextOnTablet():
+        doReturn(mResources).when(mContext).getResources();
+        doReturn(DeviceFormFactor.SCREEN_BUCKET_TABLET - 1)
+                .when(mResources)
+                .getInteger(org.chromium.ui.R.integer.min_screen_width_bucket);
+        Assert.assertFalse(DeviceFormFactor.isNonMultiDisplayContextOnTablet(mContext));
+    }
+
+    @After
+    public void tearDown() {
+        CommandLine.reset();
+        SysUtils.resetForTesting();
+    }
+
+    @Test
+    @SmallTest
+    public void testShouldShowTabSwitcher() {
+        // Tests when the background time isn't set.
+        // If tab switcher on return is disabled, returns false:
+        TAB_SWITCHER_ON_RETURN_MS.setForTesting(-1);
+        Assert.assertEquals(-1, TAB_SWITCHER_ON_RETURN_MS.getValue());
+        Assert.assertFalse(ReturnToChromeUtil.shouldShowTabSwitcher(-1));
+        // If tab switcher on return is enabled but NOT immediate, returns false:
+        TAB_SWITCHER_ON_RETURN_MS.setForTesting(60000);
+        Assert.assertEquals(60000, TAB_SWITCHER_ON_RETURN_MS.getValue());
+        Assert.assertFalse(ReturnToChromeUtil.shouldShowTabSwitcher(-1));
+        // If tab switcher on return immediate is enabled, returns true:
+        TAB_SWITCHER_ON_RETURN_MS.setForTesting(0);
+        Assert.assertEquals(0, TAB_SWITCHER_ON_RETURN_MS.getValue());
+        Assert.assertTrue(ReturnToChromeUtil.shouldShowTabSwitcher(-1));
+
+        // Tests the cases when the background time is set.
+        // Tab switcher on return is disabled:
+        TAB_SWITCHER_ON_RETURN_MS.setForTesting(-1);
+        Assert.assertEquals(-1, TAB_SWITCHER_ON_RETURN_MS.getValue());
+        Assert.assertFalse(
+                ReturnToChromeUtil.shouldShowTabSwitcher(System.currentTimeMillis() - 1));
+
+        // Tab switcher on return is enabled immediate:
+        int returnTimeMs = 0;
+        TAB_SWITCHER_ON_RETURN_MS.setForTesting(returnTimeMs);
+        Assert.assertEquals(0, TAB_SWITCHER_ON_RETURN_MS.getValue());
+        Assert.assertTrue(ReturnToChromeUtil.shouldShowTabSwitcher(System.currentTimeMillis() - 1));
+
+        // Tab switcher on return is enabled for 1 min:
+        returnTimeMs = 60000; // One minute
+        TAB_SWITCHER_ON_RETURN_MS.setForTesting(returnTimeMs);
+        // When return time arrives, return true:
+        Assert.assertTrue(ReturnToChromeUtil.shouldShowTabSwitcher(
+                System.currentTimeMillis() - returnTimeMs - 1));
+        // When return times hasn't arrived, return false:
+        Assert.assertFalse(ReturnToChromeUtil.shouldShowTabSwitcher(System.currentTimeMillis()));
+    }
+
+    @Test
+    @SmallTest
+    public void testShouldShowStartSurfaceAsTheHomePage() {
+        START_SURFACE_OPEN_NTP_INSTEAD_OF_START.setForTesting(true);
+        Assert.assertTrue(ReturnToChromeUtil.isStartSurfaceEnabled(mContext));
+
+        // Sets main intent from launcher:
+        doReturn(Intent.ACTION_MAIN).when(mIntent).getAction();
+        doReturn(true).when(mIntent).hasCategory(Intent.CATEGORY_LAUNCHER);
+        Assert.assertTrue(IntentUtils.isMainIntentFromLauncher(mIntent));
+
+        // Sets background time:
+        SharedPreferencesManager.getInstance().addToStringSet(
+                ChromePreferenceKeys.TABBED_ACTIVITY_LAST_BACKGROUNDED_TIME_MS_PREF, "0");
+        TAB_SWITCHER_ON_RETURN_MS.setForTesting(0);
+        Assert.assertTrue(ReturnToChromeUtil.shouldShowTabSwitcher(0));
+
+        // Tests the case when there isn't any Tab:
+        doReturn(true).when(mTabModelSelector).isTabStateInitialized();
+        doReturn(0).when(mTabModelSelector).getTotalTabCount();
+        Assert.assertTrue(ReturnToChromeUtil.shouldShowOverviewPageOnStart(
+                mContext, mIntent, mTabModelSelector, mInactivityTracker));
+
+        // Tests the case when the total tab count > 0:
+        doReturn(true).when(mTabModelSelector).isTabStateInitialized();
+        doReturn(1).when(mTabModelSelector).getTotalTabCount();
+        Assert.assertTrue(ReturnToChromeUtil.shouldShowOverviewPageOnStart(
+                mContext, mIntent, mTabModelSelector, mInactivityTracker));
+
+        SharedPreferencesManager.getInstance().removeKey(
+                ChromePreferenceKeys.TABBED_ACTIVITY_LAST_BACKGROUNDED_TIME_MS_PREF);
+    }
+
+    @Test
+    @SmallTest
+    public void testStartSurfaceIsDisabledOnTablet() {
+        // Sets for !DeviceFormFactor.isNonMultiDisplayContextOnTablet()
+        doReturn(mResources).when(mContext).getResources();
+        doReturn(DeviceFormFactor.SCREEN_BUCKET_TABLET)
+                .when(mResources)
+                .getInteger(org.chromium.ui.R.integer.min_screen_width_bucket);
+        Assert.assertTrue(DeviceFormFactor.isNonMultiDisplayContextOnTablet(mContext));
+
+        Assert.assertFalse(ReturnToChromeUtil.isStartSurfaceEnabled(mContext));
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerActivityTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerActivityTest.java
index 1c032f3..2327ba4 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerActivityTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerActivityTest.java
@@ -13,6 +13,7 @@
 
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.util.Pair;
 
 import androidx.test.core.app.ActivityScenario;
 import androidx.test.filters.MediumTest;
@@ -42,8 +43,10 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.ButtonDataProvider;
 import org.chromium.chrome.browser.toolbar.ButtonDataProvider.ButtonDataObserver;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.browser.toolbar.top.OptionalBrowsingModeButtonController;
 import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator;
+import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.tabmodel.MockTabCreatorManager;
 import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector;
 import org.chromium.content_public.browser.WebContents;
@@ -61,13 +64,19 @@
  * ChromeTabbedActivity}.
  */
 @Config(shadows = {OptionalNewTabButtonControllerActivityTest.ShadowDelegate.class,
-                OptionalNewTabButtonControllerActivityTest.ShadowChromeFeatureList.class,
                 ShadowGURL.class})
 @RunWith(BaseRobolectricTestRunner.class)
+@Features.EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
 @CommandLineFlags.
-Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ChromeSwitches.DISABLE_NATIVE_INITIALIZATION})
+Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ChromeSwitches.DISABLE_NATIVE_INITIALIZATION,
+        "enable-features=" + ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2
+                + "<FakeStudyName",
+        "force-fieldtrials=FakeStudyName/Enabled",
+        "force-fieldtrial-params=FakeStudyName.Enabled:min_version_adaptive/0"})
 public class OptionalNewTabButtonControllerActivityTest {
     @Rule
+    public TestRule mProcessor = new Features.JUnitProcessor();
+    @Rule
     public TestRule mCommandLineFlagsRule = CommandLineFlags.getTestRule();
 
     /**
@@ -108,7 +117,8 @@
 
         @Implementation
         public static boolean isEnabled(String featureName) {
-            return featureName.equals(ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR);
+            return featureName.equals(
+                    ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2);
         }
 
         public static void reset() {
@@ -124,8 +134,12 @@
     public void setUp() {
         // Avoid leaking state from the previous test.
         resetStaticState();
-        ShadowChromeFeatureList.sParamValues.put("mode", AdaptiveToolbarFeatures.ALWAYS_NEW_TAB);
-
+        AdaptiveToolbarStatePredictor.setToolbarStateForTesting(
+                AdaptiveToolbarButtonVariant.NEW_TAB);
+        // To bypass a direct call to AdaptiveToolbarStatePredictor#readFromSegmentationPlatform for
+        // UMA.
+        AdaptiveToolbarStatePredictor.setSegmentationResultsForTesting(
+                new Pair<>(true, AdaptiveToolbarButtonVariant.NEW_TAB));
         MockTabModelSelector tabModelSelector = new MockTabModelSelector(
                 /*tabCount=*/1, /*incognitoTabCount=*/0, (id, incognito) -> {
                     Tab tab = spy(MockTab.createAndInitialize(id, incognito));
@@ -159,6 +173,7 @@
         // AsyncInitializationActivity#applyOverrides to set incorrect smallestWidth.
         DisplayAndroidManager.resetInstanceForTesting();
         TabWindowManagerSingleton.resetTabModelSelectorFactoryForTesting();
+        AdaptiveToolbarStatePredictor.setToolbarStateForTesting(null);
     }
 
     @Test
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 0ac71ba..2653080 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-105.0.5120.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-105.0.5134.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/android/webapk/strings/translations/android_webapk_strings_uk.xtb b/chrome/android/webapk/strings/translations/android_webapk_strings_uk.xtb
index 49c8e02..f8d0f3f 100644
--- a/chrome/android/webapk/strings/translations/android_webapk_strings_uk.xtb
+++ b/chrome/android/webapk/strings/translations/android_webapk_strings_uk.xtb
@@ -5,7 +5,7 @@
 <translation id="1700971771753530690">Щоб запустити <ph name="APP_NAME" />, потрібен такий додаток:</translation>
 <translation id="2697679025356221813">Щоб запустити <ph name="APP_NAME" />, потрібен веб-переглядач</translation>
 <translation id="3858759029325727987">Виберіть веб-переглядач, який підтримує цей додаток:</translation>
-<translation id="4165986682804962316">Налаштування сайту</translation>
+<translation id="4165986682804962316">Налаштування сайтів</translation>
 <translation id="6377677440246641805"><ph name="BROWSER_NAME" />\nНе підтримується</translation>
 <translation id="7671141431838911305">INSTALL</translation>
 <translation id="8252328707312954493">ЗАКРИТИ</translation>
diff --git a/chrome/app/chrome.cml b/chrome/app/chrome.cml
index 4ef8412..f9486a2 100644
--- a/chrome/app/chrome.cml
+++ b/chrome/app/chrome.cml
@@ -67,6 +67,7 @@
                 "fuchsia.net.name.Lookup",
                 "fuchsia.posix.socket.Provider",
                 "fuchsia.process.Launcher",
+                "fuchsia.tracing.perfetto.ProducerConnector",
                 "fuchsia.ui.composition.Allocator",
                 "fuchsia.ui.composition.Flatland",
                 "fuchsia.ui.composition.ScreenCapture",
diff --git a/chrome/app/chrome_v1.cmx b/chrome/app/chrome_v1.cmx
index cd376be..de1dc48 100644
--- a/chrome/app/chrome_v1.cmx
+++ b/chrome/app/chrome_v1.cmx
@@ -31,6 +31,7 @@
       "fuchsia.posix.socket.Provider",
       "fuchsia.process.Launcher",
       "fuchsia.sysmem.Allocator",
+      "fuchsia.tracing.perfetto.ProducerConnector",
       "fuchsia.ui.composition.Allocator",
       "fuchsia.ui.composition.Flatland",
       "fuchsia.ui.input3.Keyboard",
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index c6c70b4..094cd53c 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1361,6 +1361,15 @@
   <message name="IDS_LOGIN_MARKETING_OPT_IN_SCREEN_SUBTITLE" desc="The sub-title of the dialog that allows user to opt-in into several Google marketing options.">
     Get <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> tips, offers, and updates, and share feedback.
   </message>
+  <message name="IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_1" desc="The first line of of an alternate title for  the last dialog the marketing opt-in for cloud gaming devices.">
+    Setup is complete!
+  </message>
+  <message name="IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_2" desc="The second line of of an alternate title for  the last dialog the marketing opt-in for cloud gaming devices.">
+    Get ready to start gaming
+  </message>
+  <message name="IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SUBTITLE" desc="An alternate subtitle for  the last dialog the marketing opt-in for cloud gaming devices.">
+    Open the Explore app after setup to start gaming. Access hundreds of the latest games, see gaming offers, and get an immersive gaming experience.
+  </message>
   <message name="IDS_LOGIN_MARKETING_OPT_IN_SCREEN_UNSUBSCRIBE_SHORT" desc="Disclaimer about being able to unsubscribe">
     Unsubscribe anytime.
   </message>
@@ -1376,6 +1385,9 @@
   <message name="IDS_LOGIN_MARKETING_OPT_IN_SCREEN_GET_CHROMEBOOK_UPDATES_SIGN_ME_UP" desc="A lablel next to the checkbox that controls user subscription to marketing updates and useful information about the user's Chrome device.">
     Sign me up
   </message>
+  <message name="IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SIGN_ME_UP" desc="Alternate the lablel next to the checkbox that controls user subscription to marketing updates and useful information about the user's Chrome device for gaming device.">
+    Sign up for <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> emails
+  </message>
   <message name="IDS_LOGIN_GET_STARTED" desc="A label on the button. Used on the welcome screen (the first one on OOBE) and on the marketing optin screen (the last one in OOBE).">
     Get started
   </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SIGN_ME_UP.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SIGN_ME_UP.png.sha1
new file mode 100644
index 0000000..33911354
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SIGN_ME_UP.png.sha1
@@ -0,0 +1 @@
+2ff47f4e1166beb4ca615162ca9fd8659c15218a
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SUBTITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SUBTITLE.png.sha1
new file mode 100644
index 0000000..33911354
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SUBTITLE.png.sha1
@@ -0,0 +1 @@
+2ff47f4e1166beb4ca615162ca9fd8659c15218a
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_1.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_1.png.sha1
new file mode 100644
index 0000000..33911354
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_1.png.sha1
@@ -0,0 +1 @@
+2ff47f4e1166beb4ca615162ca9fd8659c15218a
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_2.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_2.png.sha1
new file mode 100644
index 0000000..33911354
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_2.png.sha1
@@ -0,0 +1 @@
+2ff47f4e1166beb4ca615162ca9fd8659c15218a
\ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 122383c2..c84cc74 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7119,6 +7119,9 @@
       <message name="IDS_ACCNAME_FULLSCREEN" desc="The accessible name of the fullscreen button in the new merged menu">
         Full screen
       </message>
+      <message name="IDS_ACCNAME_EXIT_FULLSCREEN" desc="The accessible name of the exit fullscreen button in the new merged menu">
+        Exit full screen
+      </message>
       <message name="IDS_ACCNAME_HOME" desc="The accessible name for the home button">
         Home
       </message>
@@ -9609,9 +9612,6 @@
         <message name="IDS_SYNC_CONFIRMATION_TITLE_LACROS_NON_FORCED" desc="Title of the sync confirmation dialog/screen on lacros when sync is not forced.">
           Turn on Chrome browser sync?
         </message>
-        <message name="IDS_SYNC_CONFIRMATION_TITLE_LACROS" desc="Title of the sync confirmation dialog/screen on lacros.">
-          Chrome browser sync is on
-        </message>
         <message name="IDS_SYNC_CONFIRMATION_SYNC_INFO_TITLE_LACROS" desc="Text in the information about sync on the sync confirmation dialog/screen on lacros.">
           Your bookmarks, passwords, history, and more are synced on all your devices
         </message>
diff --git a/chrome/app/generated_resources_grd/IDS_ACCNAME_EXIT_FULLSCREEN.png.sha1 b/chrome/app/generated_resources_grd/IDS_ACCNAME_EXIT_FULLSCREEN.png.sha1
new file mode 100644
index 0000000..1b324b8
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_ACCNAME_EXIT_FULLSCREEN.png.sha1
@@ -0,0 +1 @@
+7256be00d2731efd54d8d876520c30f28fbf2de6
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_SYNC_CONFIRMATION_TITLE_LACROS.png.sha1 b/chrome/app/generated_resources_grd/IDS_SYNC_CONFIRMATION_TITLE_LACROS.png.sha1
deleted file mode 100644
index a98a995..0000000
--- a/chrome/app/generated_resources_grd/IDS_SYNC_CONFIRMATION_TITLE_LACROS.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0256ddab84c8d97a175de1e4d388cfbae91fd1de
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings.grdp b/chrome/app/os_settings_search_tag_strings.grdp
index 50e5723..0777ecd 100644
--- a/chrome/app/os_settings_search_tag_strings.grdp
+++ b/chrome/app/os_settings_search_tag_strings.grdp
@@ -1119,6 +1119,9 @@
   <message name="IDS_OS_SETTINGS_TAG_A11Y_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility (a.k.a. a11y) settings. Alternate phrase for: 'Accessibility settings'">
     A11y
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_ALT2" desc="Text for search result item which, when clicked, navigates the user to accessibility (a.k.a. a11y) settings. Alternate phrase for: 'Accessibility settings'">
+    Assistive technology
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_ALWAYS_SHOW_OPTIONS" desc="Text for search result item which, when clicked, navigates the user to accessibility (a.k.a. a11y) settings, with a toggle to enable/disable always showing accessibility options in the system menu. Alternate phrase for: 'Always show a11y options'">
     Always show accessibility options
   </message>
@@ -1137,21 +1140,42 @@
   <message name="IDS_OS_SETTINGS_TAG_A11y_CHROMEVOX_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable ChromeVox (spoken feedback). Alternate phrase for: 'ChromeVox (spoken feedback)'">
     Screen reader
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11y_CHROMEVOX_ALT2" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable ChromeVox (spoken feedback). Alternate phrase for: 'ChromeVox (spoken feedback)'">
+    Braille
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable custom cursor colors.">
-   Cursor color
+    Cursor color
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable custom cursor colors. Alternate phrase for: 'Cursor color'">
+    Mouse color
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT2" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable custom cursor colors. Alternate phrase for: 'Cursor color'">
+    Pointer color
   </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_SELECT_TO_SPEAK" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable select-to-speak (hearing text read aloud after it is selected).">
     Select-to-speak
   </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH" desc="Text for search result item which, when clicked, navigates the user to text-to-speech voice accessibility settings. Alternate phrase for 'TTS'">
-    Text-to-speech
+    Text-to-speech voice settings
   </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT1" desc="Text for search result item which, when clicked, navigates the user to text-to-speech voice accessibility settings. Alternate phrase for 'Text-to-speech'">
-    TTS
+    Spoken language
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT2" desc="Text for search result item which, when clicked, navigates the user to text-to-speech voice accessibility settings. Alternate phrase for 'Text-to-speech'">
+    Speech engines
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT3" desc="Text for search result item which, when clicked, navigates the user to text-to-speech voice accessibility settings. Alternate phrase for 'Text-to-speech'">
+    eSpeak
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT4" desc="Text for search result item which, when clicked, navigates the user to text-to-speech voice accessibility settings. Alternate phrase for 'Text-to-speech'">
+    Preferred voice
   </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_SPEECH_RATE" desc="Text for search result item which, when clicked, navigates the user to text-to-speech voice accessibility settings, with a slider to set the speech rate.">
     Text-to-speech rate
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_SPEECH_RATE_ALT1" desc="Text for search result item which, when clicked, navigates the user to text-to-speech voice accessibility settings, with a slider to set the speech rate.">
+    Speech speed
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_SPEECH_PITCH" desc="Text for search result item which, when clicked, navigates the user to text-to-speech voice accessibility settings, with a slider to set the speech pitch.">
     Text-to-speech pitch
   </message>
@@ -1168,17 +1192,26 @@
     High contrast mode
   </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_HIGH_CONTRAST_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable high-contrast mode. Alternate phrase for: 'High contrast mode'">
-    Inverted colors
+    Invert colors
   </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable full-screen magnification.">
     Fullscreen magnifier
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable full-screen magnification. Alternate phrase for: 'Fullscreen magnifier'">
+    Zoom
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT2" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable full-screen magnification. Alternate phrase for: 'Fullscreen magnifier'">
+    Magnify screen
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_FOCUS_FOLLOWING" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable full-screen magnification keyboard focus-following.">
     Magnifier follows keyboard focus
   </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_DOCKED_MAGNIFIER" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable docked screen magnification.">
     Docked magnifier
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_DOCKED_MAGNIFIER_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable docked screen magnification. Alternate phrase for: 'Docked magnifier'">
+    Partial magnifier
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_STICKY_KEYS" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable sticky keys.">
     Sticky keys
   </message>
@@ -1191,20 +1224,59 @@
   <message name="IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable dictation (speak-to-type). Alternate phrase for: 'Dictation'">
     Speak-to-type
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT2" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable dictation (speak-to-type). Alternate phrase for: 'Dictation'">
+    Speech-to-text
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT3" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable dictation (speak-to-type). Alternate phrase for: 'Dictation'">
+    Speech recognition
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT4" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable dictation (speak-to-type). Alternate phrase for: 'Dictation'">
+    Voice typing
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_KEYBOARD_FOCUS" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable highlighting the object with keyboard focus when it changes.">
     Highlight keyboard focus
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_KEYBOARD_FOCUS_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable highlighting the object with keyboard focus when it changes. Alternate phrase for: 'Highlight keyboard focus'">
+    Focus ring
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_TEXT_CARET" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable highlighting the text caret when it appears or moves.">
     Highlight text caret
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_TEXT_CARET_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable highlighting the text caret when it appears or moves. Alternate phrase for: 'Highlight text caret'">
+    Text cursor highlighter
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_AUTOMATICALLY_CLICK" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable automatically clicking when the cursor stops.">
     Automatically click when cursor stops
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_AUTOMATICALLY_CLICK_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable automatically clicking when the cursor stops. Alternate phrase for: 'Automatically click when cursor stops'">
+    Auto clicks
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable a large mouse cursor.">
     Large cursor
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable a large mouse cursor. Alternate phrase for: 'Large cursor'">
+    Show large mouse cursor
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT2" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable a large mouse cursor. Alternate phrase for: 'Large cursor'">
+    Big mouse cursor
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT3" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable a large mouse cursor. Alternate phrase for: 'Large cursor'">
+    Big pointer
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT4" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable a large mouse cursor. Alternate phrase for: 'Large cursor'">
+    Mouse size
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable highlighting the mouse cursor when it is moving.">
-    Highlight cursor when moving
+    Highlight mouse cursor when moving
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable highlighting the mouse cursor when it is moving. Alternate phrase for: 'Highlight mouse cursor when moving'">
+    Highlight pointer
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT2" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable highlighting the mouse cursor when it is moving. Alternate phrase for: 'Highlight mouse cursor when moving'">
+    Circle pointer
+  </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT3" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable highlighting the mouse cursor when it is moving. Alternate phrase for: 'Highlight mouse cursor when moving'">
+    Circle cursor
   </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_TABLET_NAVIGATION_BUTTONS" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable showing navigation buttons (launcher, back, overview) in the shelf when the device is in tablet mode.">
     Tablet navigation buttons
@@ -1218,12 +1290,18 @@
   <message name="IDS_OS_SETTINGS_TAG_A11Y_STARTUP_SOUND" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable playing a sound upon device startup.">
     Startup sound
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_STARTUP_SOUND_ALT1" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable playing a sound upon device startup. Alternate phrase for: 'Startup sound'">
+    Play sound on startup
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_CAPTIONS" desc="Text for search result item which, when clicked, navigates the user to accessibility caption preferences.">
     Caption preferences
   </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_LIVE_CAPTION" desc="Text for a search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable Live Caption.">
     Live Caption
   </message>
+  <message name="IDS_OS_SETTINGS_TAG_A11Y_LIVE_CAPTION_ALT1" desc="Text for a search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable Live Caption. Alternate phrase for: 'Live Caption'">
+    Auto captions
+  </message>
   <message name="IDS_OS_SETTINGS_TAG_A11Y_ENABLE_SWITCH_ACCESS" desc="Text for search result item which, when clicked, navigates the user to accessibility settings, with a toggle to enable/disable switch access, which allows users to control the computer with just one or two switches.">
     Switch access
   </message>
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_ALT2.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_ALT2.png.sha1
new file mode 100644
index 0000000..8c7161f
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_ALT2.png.sha1
@@ -0,0 +1 @@
+fc6604df8af1e27e685428ea36a3e00934103d9d
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_AUTOMATICALLY_CLICK_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_AUTOMATICALLY_CLICK_ALT1.png.sha1
new file mode 100644
index 0000000..011e499
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_AUTOMATICALLY_CLICK_ALT1.png.sha1
@@ -0,0 +1 @@
+bd73b3c1ffaf20a76a76462e335d7f284e565b3a
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR.png.sha1
new file mode 100644
index 0000000..a7b4642
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR.png.sha1
@@ -0,0 +1 @@
+32011f9f827f3a48fccc2066433a9e59bb9e11da
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT1.png.sha1
new file mode 100644
index 0000000..e5e20d4
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT1.png.sha1
@@ -0,0 +1 @@
+f3583b8228f921fb3c809c8edb4e90a56d9521d4
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT2.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT2.png.sha1
new file mode 100644
index 0000000..7cfe53bc
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT2.png.sha1
@@ -0,0 +1 @@
+451c3a62ac420b76c950208655045c5c01c76a47
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT2.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT2.png.sha1
new file mode 100644
index 0000000..22e1a736
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT2.png.sha1
@@ -0,0 +1 @@
+13596e8e492f1ea5a57fd936002189f41d1f6caa
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT3.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT3.png.sha1
new file mode 100644
index 0000000..047b53b2
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT3.png.sha1
@@ -0,0 +1 @@
+35ca5bf92208121d57822976d41126a5786d2467
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT4.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT4.png.sha1
new file mode 100644
index 0000000..e8b35284
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT4.png.sha1
@@ -0,0 +1 @@
+96648112ea4597496d1f41a7d92c7c6ccbf1b487
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DOCKED_MAGNIFIER_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DOCKED_MAGNIFIER_ALT1.png.sha1
new file mode 100644
index 0000000..db9d5713
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_DOCKED_MAGNIFIER_ALT1.png.sha1
@@ -0,0 +1 @@
+3e4158ab8b9acce8384d2a02f09722594f65b0f9
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT1.png.sha1
new file mode 100644
index 0000000..2d12003
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT1.png.sha1
@@ -0,0 +1 @@
+724ae41e362369c3e869dad677639d830526e079
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT2.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT2.png.sha1
new file mode 100644
index 0000000..392d0fd
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT2.png.sha1
@@ -0,0 +1 @@
+9b310de761a4a51afe6ed3cfacfc0dd405a8ea03
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR.png.sha1
new file mode 100644
index 0000000..6f3c541
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR.png.sha1
@@ -0,0 +1 @@
+c8c3c5686dc68ff565ecb1716a8d434a44c60f49
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT1.png.sha1
new file mode 100644
index 0000000..8fc695f
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT1.png.sha1
@@ -0,0 +1 @@
+f8804a7de984b23ebad58e057838d420c4d49347
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT2.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT2.png.sha1
new file mode 100644
index 0000000..43470fb
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT2.png.sha1
@@ -0,0 +1 @@
+012323e4d3779d6cb3f41215ad0fc33bce81281e
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT3.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT3.png.sha1
new file mode 100644
index 0000000..641ddac
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT3.png.sha1
@@ -0,0 +1 @@
+0718dbf36ba8688f20aed1d5abcbb464646efe63
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_KEYBOARD_FOCUS_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_KEYBOARD_FOCUS_ALT1.png.sha1
new file mode 100644
index 0000000..99e4d68
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_KEYBOARD_FOCUS_ALT1.png.sha1
@@ -0,0 +1 @@
+3ad748edc1eda4719396788eac6af778ad8bf4c0
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_TEXT_CARET_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_TEXT_CARET_ALT1.png.sha1
new file mode 100644
index 0000000..180fac5
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_TEXT_CARET_ALT1.png.sha1
@@ -0,0 +1 @@
+929e4acfed07aacf1059ffb51340e0719867f7da
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGH_CONTRAST_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGH_CONTRAST_ALT1.png.sha1
new file mode 100644
index 0000000..537ac90
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_HIGH_CONTRAST_ALT1.png.sha1
@@ -0,0 +1 @@
+b49198bfce464a16a69c35b007342e2e3aaf3d86
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT1.png.sha1
new file mode 100644
index 0000000..75ceb85
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT1.png.sha1
@@ -0,0 +1 @@
+8dc0f64abb9d32306541f2ab577df0847adea7da
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT2.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT2.png.sha1
new file mode 100644
index 0000000..143b34c
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT2.png.sha1
@@ -0,0 +1 @@
+cac5b273bb2964cbcd856551ca6329740a95f602
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT3.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT3.png.sha1
new file mode 100644
index 0000000..58ab7f5
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT3.png.sha1
@@ -0,0 +1 @@
+3765f88cc0447feee373ae8bb79deb0c4d7d8794
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT4.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT4.png.sha1
new file mode 100644
index 0000000..1465106
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT4.png.sha1
@@ -0,0 +1 @@
+922e75d62c8ec1e96b4696065e7c5e32749a7f5b
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LIVE_CAPTION_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LIVE_CAPTION_ALT1.png.sha1
new file mode 100644
index 0000000..c6e0955e
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_LIVE_CAPTION_ALT1.png.sha1
@@ -0,0 +1 @@
+d1ffc0a82fc5dcc81f071ce6ae95234ab63bd017
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_SPEECH_RATE_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_SPEECH_RATE_ALT1.png.sha1
new file mode 100644
index 0000000..026b113c0
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_SPEECH_RATE_ALT1.png.sha1
@@ -0,0 +1 @@
+05b91e6a06653f099c71076f68b2300022bcb1e8
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_STARTUP_SOUND_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_STARTUP_SOUND_ALT1.png.sha1
new file mode 100644
index 0000000..f4f905c
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_STARTUP_SOUND_ALT1.png.sha1
@@ -0,0 +1 @@
+de05e6de65bd043b5fc94b4988c2c70b61dec363
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH.png.sha1
new file mode 100644
index 0000000..0ca9a28
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH.png.sha1
@@ -0,0 +1 @@
+dcf111e9fabba83daca2fb3d61022e42f82698b6
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT1.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT1.png.sha1
new file mode 100644
index 0000000..048928a
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT1.png.sha1
@@ -0,0 +1 @@
+62e992a4009ee0b3b38b6ec577a1bf43b95d0959
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT2.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT2.png.sha1
new file mode 100644
index 0000000..5e43145e
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT2.png.sha1
@@ -0,0 +1 @@
+f2b2697b3fe7e1748dfe36df767c265a97c5f35a
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT3.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT3.png.sha1
new file mode 100644
index 0000000..e9deaa21
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT3.png.sha1
@@ -0,0 +1 @@
+7a1b5a19efa3fa890a8ce8c41fdd8c9c49f7a699
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT4.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT4.png.sha1
new file mode 100644
index 0000000..5008a98
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT4.png.sha1
@@ -0,0 +1 @@
+bd3a0b60152530f9eaf1ec686d8152c9849ea80b
\ No newline at end of file
diff --git a/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11y_CHROMEVOX_ALT2.png.sha1 b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11y_CHROMEVOX_ALT2.png.sha1
new file mode 100644
index 0000000..48a05062
--- /dev/null
+++ b/chrome/app/os_settings_search_tag_strings_grdp/IDS_OS_SETTINGS_TAG_A11y_CHROMEVOX_ALT2.png.sha1
@@ -0,0 +1 @@
+57b3bbf8c1da21de1362b6dabd9138439dbf79b5
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index 880775c..bf4f34f 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -2172,6 +2172,9 @@
   <message name="IDS_SETTINGS_BLUETOOTH_DEVICE_DETAILS" desc="Name of the settings page which displays Bluetooth device details.">
     Bluetooth device details
   </message>
+  <message name="IDS_SETTINGS_BLUETOOTH_SAVED_DEVICES" desc="Name of the settings page which displays Bluetooth saved devices.">
+   Devices saved to your account
+  </message>
   <message name="IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE" desc="Title of the settings dialog for adding or pairing Bluetooth a device.">
     Connect to Bluetooth device
   </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_SAVED_DEVICES.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_SAVED_DEVICES.png.sha1
new file mode 100644
index 0000000..02468e1
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_SAVED_DEVICES.png.sha1
@@ -0,0 +1 @@
+24bf53b11b4ecf5fc2ce337b59752c0d7ff6a716
\ No newline at end of file
diff --git a/chrome/app/profiles_strings.grdp b/chrome/app/profiles_strings.grdp
index b928b07..a189d16 100644
--- a/chrome/app/profiles_strings.grdp
+++ b/chrome/app/profiles_strings.grdp
@@ -667,9 +667,6 @@
       <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_SESSION_MANAGED_DESCRIPTION" desc="Disclaimer on the first profile creation screen, informing that the session is managed.">
         Your session is managed by your organization. Administrators can delete your profile and also monitor your network traffic.
       </message>
-      <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_SIGNIN_BUTTON_LABEL_LACROS" desc="Label for a button that prompts user to sign in">
-        Next
-      </message>
       <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_ACCOUNT_SELECTION_LACROS_TITLE" desc="Profile picker, account selection screen title">
         Choose an account
       </message>
diff --git a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_SIGNIN_BUTTON_LABEL_LACROS.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_SIGNIN_BUTTON_LABEL_LACROS.png.sha1
deleted file mode 100644
index ec52cc0..0000000
--- a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_SIGNIN_BUTTON_LABEL_LACROS.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8bdada0527b543f262d0336322e5f1580ed8e15c
\ No newline at end of file
diff --git a/chrome/app/resources/generated_resources_af.xtb b/chrome/app/resources/generated_resources_af.xtb
index 86cbf76..2a342b5 100644
--- a/chrome/app/resources/generated_resources_af.xtb
+++ b/chrome/app/resources/generated_resources_af.xtb
@@ -8440,7 +8440,6 @@
 <translation id="934503638756687833">Items wat nie hier gelys word nie, sal indien nodig ook verwyder word. Kom meer te wete oor &lt;a href="<ph name="URL" />"&gt;ongewenste sagtewarebeskerming&lt;/a&gt; in die witskrif oor Chrome-privaatheid.</translation>
 <translation id="93480724622239549">Fout</translation>
 <translation id="935854577147268200">Smart Lock-foon het verander. Voer jou wagwoord in om Smart Lock op te dateer. Jou foon sal volgende keer jou <ph name="DEVICE_TYPE" /> ontsluit. Jy kan Smart Lock in Instellings afskakel</translation>
-<translation id="93610034168535821">Algehele berging gebruik deur werwe:</translation>
 <translation id="936646668635477464">Kamera en mikrofoon</translation>
 <translation id="936801553271523408">Stelsel se diagnostiese data</translation>
 <translation id="93766956588638423">Herstel uitbreiding</translation>
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index a28f9361..4b88e25e 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -1552,6 +1552,7 @@
 <translation id="2433836460518180625">መሣሪያ ብቻ ክፈት</translation>
 <translation id="2434449159125086437">አታሚን ማቀናበር አልተቻለም። እባክዎ ውቅረትን ይፈትሹ እና እንደገና ይሞክሩ።</translation>
 <translation id="2434758125294431199">ማን ለእርስዎ ሊያጋራ እንደሚችል ይምረጡ</translation>
+<translation id="2434915728183570229">አሁን የስልክዎን መተግበሪያዎች መመልከት ይችላሉ</translation>
 <translation id="2435137177546457207">የGoogle Chrome እና የChromeOS Flex ተጨማሪ ደንቦች</translation>
 <translation id="2435248616906486374">የአውታረ መረብ ግንኙነት ተቋርጧል</translation>
 <translation id="2435457462613246316">የይለፍ ቃል አሳይ</translation>
@@ -1917,6 +1918,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{1 የማይደገፍ መተግበሪያን አስወግድ}one{# የማይደገፉ መተግበሪያዎችን አስወግድ}other{# የማይደገፉ መተግበሪያዎችን አስወግድ}}</translation>
 <translation id="2776560192867872731">ለ<ph name="DEVICE_NAME" /> የመሣሪያውን ስም ይቀይሩ</translation>
 <translation id="2777251078198759550">ይህን መያዣ ይሰርዙ</translation>
+<translation id="2778471504622896352">የርቀት መተግበሪያዎችን በChromeOS ማስጀመሪያ ላይ ያክሉ</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">የLinux መተግበሪያን መጫን ላይ ስህተት</translation>
 <translation id="2783298271312924866">ወርዷል</translation>
@@ -3550,6 +3552,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />፣ <ph name="SECOND_SWITCH" />፣ <ph name="THIRD_SWITCH" /> እና <ph name="NUMBER_OF_OTHER_SWITCHES" /> ተጨማሪ ማብሪያ ማጥፊያዎች</translation>
 <translation id="439266289085815679">የብሉቱዝ ውቅረትን የሚቆጣጠሩት <ph name="USER_EMAIL" /> ናቸው።</translation>
 <translation id="4392896746540753732">የውቅረት ፋይሉን ያርትዑ</translation>
+<translation id="4393713825278446281">የፈጣን ጥምረት መሣሪያዎች <ph name="PRIMARY_EMAIL" /> ላይ ተቀምጠዋል</translation>
 <translation id="4394049700291259645">አሰናክል</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;ሁሉንም ክፈት}=1{&amp;ዕልባት ክፈት}one{&amp;ሁሉንም ({COUNT}) ክፈት}other{&amp;ሁሉንም ({COUNT}) ክፈት}}</translation>
 <translation id="4397372003838952832">ይህን የይለፍ ቃል ማስታወስ አያስፈልግዎትም። ለ<ph name="EMAIL" /> በ<ph name="GOOGLE_PASSWORD_MANAGER" /> ላይ ይቀመጣል።</translation>
@@ -3779,6 +3782,7 @@
 <translation id="4615586811063744755">ምንም ኩኪ አልተመረጠም</translation>
 <translation id="461661862154729886">የኃይል ምንጭ</translation>
 <translation id="4617001782309103936">በጣም አጭር</translation>
+<translation id="4617019240346358451">«<ph name="EXTENSION_NAME" />»ን ለመጠቀም ገጹን ዳግም ይጫኑ</translation>
 <translation id="4617270414136722281">የቅጥያ አማራጮች</translation>
 <translation id="4617880081511131945">ግንኙነትን መመስረት አልተቻለም</translation>
 <translation id="4619564267100705184">እርስዎ መሆንዎን ያረጋግጡ</translation>
@@ -3994,6 +3998,7 @@
 <translation id="4833683849865011483">ከህትመት አገልጋዩ 1 አታሚ ተገኝቷል</translation>
 <translation id="4836504898754963407">የጣት አሻራዎችን ያስተዳድሩ</translation>
 <translation id="4837128290434901661">ወደ Google ፍለጋ መልሰዉ ይቀይሩ?</translation>
+<translation id="4837165100461973682">የእርስዎን ለውጦች ለመተግበር ገጹን ዳግም ይጫኑ</translation>
 <translation id="4837926214103741331">ይህን መሣሪያ ለመጠቀም ስልጣን አልተሰጠዎትም። የመግባት ፍቃድ ለማግኘት የመሣሪያውን ባለቤት ያነጋግሩ።</translation>
 <translation id="4837952862063191349">የእርስዎን የአካባቢ ውሂብ ለማስከፈት እና እንደነበረ ለመመለስ፣ የእርስዎን አሮጌ የ<ph name="DEVICE_TYPE" /> የይለፍ ቃል እባክዎ ያስገቡ።</translation>
 <translation id="4838170306476614339">የስልክዎን ፎቶዎች፣ ሚዲያ እና ማሳወቂያዎች ይመልከቱ</translation>
@@ -4229,6 +4234,7 @@
 <translation id="5072900412896857127">የGoogle Play የአገልግሎት ውልን መጫን አይቻልም። እባክዎ የእርስዎን አውታረ መረብ ይፈትሹ እና እንደገና ይሞክሩ።</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />፣ <ph name="FILE2" />}one{<ph name="FILE1" />፣ <ph name="FILE2" />፣ እና # ተጨማሪ}other{<ph name="FILE1" />፣ <ph name="FILE2" />፣ እና # ተጨማሪ}}</translation>
 <translation id="5074318175948309511">አዲሶቹ ቅንብሮች ከመተግበራቸው በፊት ይህ ገጽ ዳግም መጫን ሊኖርበት ይችላል።</translation>
+<translation id="5074761966806028321">ውቅረትን ለማጠናቀቅ ፈቃድ አሁንም ያስፈልጋል</translation>
 <translation id="5075910247684008552">ደህንነታቸው በተጠበቁ ጣቢያዎች ላይ በነባሪነት ደህንነቱ ያልተጠበቀ ይዘት ይታገዳል</translation>
 <translation id="5078638979202084724">ለሁሉም ትሮች ዕልባት ያብጁ</translation>
 <translation id="5078796286268621944">የተሳሳተ ፒን</translation>
@@ -4303,6 +4309,7 @@
 <translation id="5150254825601720210">የNetscape ሰርቲፊኬት SSL አገልጋይ ስም</translation>
 <translation id="5151354047782775295">የዲስክ ቦታ ያስለቅቁ፣ አለበለዚያ የተመረጠ ውሂብ በራስ-ሰር ሊሰርዝ ይችላል</translation>
 <translation id="5153234146675181447">ስልክን እርሳ</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">የላቁ የ<ph name="PRINTING_DESTINATION" /> ቅንብሮች</translation>
 <translation id="5154702632169343078">ርዕሰ ጉዳይ</translation>
 <translation id="5155327081870541046">በአድራሻ አሞሌው ላይ ሊፈልጉት ለሚፈልጉት ጣቢያ እንደ «@bookmarks» ያለ አቋራጭ ያስገቡ። ከዚያ የመረጡትን የቁልፍ ሰሌዳ አቋራጭ ይጫኑ እና የፍለጋ ቃልዎን ያስገቡ።</translation>
@@ -4591,6 +4598,7 @@
 <translation id="5449551289610225147">ልክ ያልኾነ የይለፍ ቃል</translation>
 <translation id="5449588825071916739">ለሁሉም ትሮች ዕልባት አብጅ</translation>
 <translation id="5449716055534515760">&amp;መስኮት ዝጋ</translation>
+<translation id="5452446625764825792">አሁን የስልክዎን የቅርብ ጊዜ ፎቶዎች፣ ሚዲያ እና መተግበሪያዎች መመልከት ይችላሉ</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (ከመስመር ውጪ ይሰራል)</translation>
 <translation id="5454166040603940656">ከ<ph name="PROVIDER" /> ጋር</translation>
 <translation id="545484289444831485">ተጨማሪ የፍለጋ ውጤቶችን ይመልከቱ</translation>
@@ -4651,6 +4659,7 @@
 <translation id="5499211612787418966">ይህ መገናኛ በአሁኑ ጊዜ ያተኮረ አይደለም። ይህ መገናኛ ላይ ለማተኮር Alt-Shift Aን ይጫኑ።</translation>
 <translation id="5499313591153584299">ይህ ፋይል ለኮምፒዩተርዎ ጎጂ ሊሆን ይችላል።</translation>
 <translation id="5499453227627332024">ለእርስዎ Linux Container ደረጃ ማሻሻያ ይገኛል። እንዲሁም ከቅንብሮች መተግበሪያ በኋላ ማሻሻል ይችላሉ።</translation>
+<translation id="5499476581866658341">አሁን የስልክዎን የቅርብ ጊዜ ፎቶዎች እና ሚዲያ መመልከት ይችላሉ</translation>
 <translation id="549957179819296104">አዲስ አዶ</translation>
 <translation id="5500168250243071806">በመለያ ሲገቡ <ph name="BEGIN_LINK_SEARCH" />የፍለጋ ታሪክ<ph name="END_LINK_SEARCH" /> እና <ph name="BEGIN_LINK_GOOGLE" />ሌሎች የእንቅስቃሴ ዓይነቶች<ph name="END_LINK_GOOGLE" /> በGoogle መለያዎ ውስጥ ሊቀመጡ ይችላሉ። በማንኛውም ጊዜ ሊሰርዟቸው ይችላሉ።</translation>
 <translation id="5500709606820808700">ዛሬ የደህንነት ፍተሻ ተካሂዷል።</translation>
@@ -5940,6 +5949,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> በርቀት ታክሏል</translation>
 <translation id="6790820461102226165">ሰው አክል...</translation>
 <translation id="6793604637258913070">የጽሑፍ ድፋቱ ሲታይ ወይም ሲንቀሳቀስ አድምቀው</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">ራስ-ቅኝት በማያ ገጹ ላይ ባሉ ንጥሎች ውስጥ በራስ-ሰር እንዲንቀሳቀሱ ያስችልዎታል። አንድ ንጥል ሲደምቅ እሱን ለማግበር «ምረጥ»ን ይጫኑ።</translation>
 <translation id="6795884519221689054">ፓንዳ</translation>
 <translation id="6797493596609571643">ውይ፣ የሆነ ችግር ተፈጥሯል።</translation>
@@ -6316,6 +6326,7 @@
 <translation id="7152478047064750137">ይህ ቅጥያ ምንም ልዩ ፈቃዶችን አይፈልግም</translation>
 <translation id="7154130902455071009">የመጀመሪያ ገጽዎን ወደሚከተለው ይቀይሩ፦ <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">ነባር ፎቶ ከካሜራ ወይም ከፋይል</translation>
+<translation id="7160182524506337403">አሁን የስልክዎን ማሳወቂያዎች መመልከት ይችላሉ</translation>
 <translation id="7163202347044721291">የማግበሪያ ኮድን በማረጋገጥ ላይ...</translation>
 <translation id="716640248772308851">«<ph name="EXTENSION" />» ምልክት በተደረገባቸው አካባቢዎች ውስጥ ምስሎችን፣ ቪዲዮ እና የድምጽ ፋይሎችን ማንበብ ይችላል።</translation>
 <translation id="7167486101654761064">&amp;ሁልጊዜ እንዲህ አይነት ፋይሎችን ክፈት</translation>
@@ -7336,6 +7347,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> ሁኔታ</translation>
 <translation id="8139447493436036221">የGoogle Drive ፋይሎች</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />፣ <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">በስልክ ሃብ ቅንብሮች ውስጥ ተጨማሪ ባህሪያትን ማዋቀር ይችላሉ</translation>
 <translation id="8141584439523427891">በአማራጭ አሳሽ ውስጥ አሁን በመክፈት ላይ</translation>
 <translation id="8141725884565838206">የይለፍ ቃልዎችዎን ያስተዳድሩ</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{አንድ ቪዲዮ}one{# ቪዲዮዎች}other{# ቪዲዮዎች}}</translation>
@@ -7543,6 +7555,7 @@
 <translation id="833986336429795709">ይህን አገናኝ ለመክፈት አንድ መተግበሪያ ይምረጡ</translation>
 <translation id="8342221978608739536">አልሞከርኩትም</translation>
 <translation id="8342861492835240085">አንድ ስብስብ ይምረጡ</translation>
+<translation id="8345848587667658367">አሁን የስልክዎን የቅርብ ጊዜ ፎቶዎች፣ ሚዲያ፣ ማሳወቂያዎች እና መተግበሪያዎች መመልከት ይችላሉ</translation>
 <translation id="8347227221149377169">የኅትመት ሥራዎች</translation>
 <translation id="834785183489258869">ማንነት በማያሳውቅ ሁኔታ ላይ ሳሉ ጣቢያዎች ለምሳሌ ማስታወቂያዎችን ግላዊነት ለማላበስ ብለው የእርስዎን ኩኪዎች በመጠቀም በተለያዩ ጣቢያዎች ላይ ያለዎትን የአሰሳ እንቅስቃሴ መመልከት አይችሉም። በአንዳንድ ጣቢያዎች ላይ ያሉ ባህሪያት ላይሰሩ ይችላሉ።</translation>
 <translation id="8350789879725387295">የስታይለስ መሣሪያዎች በመትከያ ላይ</translation>
@@ -7818,6 +7831,7 @@
 <translation id="8642947597466641025">ጽሑፍ አተልቅ</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> አደገኛ ሊሆን ይችላል። እንዲቃኝ ወደ Google የላቀ ጥበቃ ይላክ?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{ምንም ኩኪዎች የሉም}=1{1 ኩኪ ታግዷል}one{# ኩኪዎች ታግደዋል}other{# ኩኪዎች ታግደዋል}}</translation>
+<translation id="864423554496711319">በእርስዎ መለያ ላይ የተቀመጡ መሣሪያዎች</translation>
 <translation id="8644655801811752511">ይህን የደህንነት ቁልፍ ዳግም ማቀናበር አይቻልም። ካስገቡት በኋላ ወዲያውኑ ቁልፉን ዳግም ለማቀናበር ይሞክሩ።</translation>
 <translation id="8645354835496065562">የዳሳሽ መዳረሻን መፍቀዱን ቀጥል</translation>
 <translation id="8645920082661222035">አደገኛ ክስተቶች ከመፈጠራቸው በፊት ይገምት እና እርስዎን ያስጠነቅቀዎታል</translation>
@@ -8148,6 +8162,7 @@
 <translation id="8957757410289731985">መገለጫን አብጅ</translation>
 <translation id="895944840846194039">የJavaScript ማህደረ ትውስታ</translation>
 <translation id="8960208913905765425">የፈጣን መልሶች አሃድ ልወጣ</translation>
+<translation id="8960638196855923532">አሁን የስልክዎን ማሳወቂያዎች እና መተግበሪያዎች መመልከት ይችላሉ</translation>
 <translation id="8962051932294470566">በአንድ ጊዜ አንድ ፋይል ብቻ ማጋራት ነው ማጋራት የሚችሉት። የአሁኑ ማስተላለፍ ሲጠናቀቅ እንደገና ይሞክሩ።</translation>
 <translation id="8962083179518285172">ዝርዝሮችን ደብቅ</translation>
 <translation id="8962918469425892674">ይህ ጣቢያ የእንቅስቃሴ ወይም የብርሃን ዳሳሾችን እየተጠቀመ ነው።</translation>
@@ -8299,6 +8314,7 @@
 <translation id="9103868373786083162">ለመመለስ ይጫኑ፣ ታሪክን ለማየት የአውድ ምናሌ</translation>
 <translation id="9108035152087032312">&amp;መስኮትን ሰይም...</translation>
 <translation id="9108072915170399168">የአሁኑ የውሂብ አጠቃቀም ቅንብር ያለበይነመረብ ነው</translation>
+<translation id="9108294543511800041">አሁን የስልክዎን የቅርብ ጊዜ ፎቶዎች፣ ሚዲያ እና ማሳወቂያዎች መመልከት ይችላሉ</translation>
 <translation id="9108674852930645435">በእርስዎ <ph name="DEVICE_TYPE" /> ላይ ምን አዲስ ነገር እንዳለ ያስሱ</translation>
 <translation id="9108808586816295166">ደህንነቱ የተጠበቀ ዲኤንኤስ ሁልጊዜ ሊገኝ የሚችል ላይሆን ይችላል</translation>
 <translation id="9109122242323516435">ባዶ ቦታ ለማስለቀቅ ከመሣሪያ ማከማቻ ፋይሎችን ይሰርዙ።</translation>
@@ -8423,7 +8439,6 @@
 <translation id="934503638756687833">ካስፈለገ እንዲሁም እዚህ ያልተዘረዘሩ ንጥሎች ሊወገዱ ይችላሉ። በChrome የግላዊነት ነጭ ወረቀት ላይ ስለ&lt;a href="<ph name="URL" />"&gt;የማይፈለግ ሶፍትዌር ጥበቃ&lt;/a&gt; የበለጠ ይረዱ።</translation>
 <translation id="93480724622239549">ሳንካ ወይም ስህተት</translation>
 <translation id="935854577147268200">Smart Lock ስልክ ተቀይሯል። Smart Lockን ለማዘመን የይለፍ ቃልዎን ያስገቡ። በሚቀጥለው ጊዜ ስልክዎ የእርስዎን <ph name="DEVICE_TYPE" /> ይከፍታል። በቅንብሮች ውስጥ Smart Lock ማጥፋት ይችላሉ</translation>
-<translation id="93610034168535821">በጣቢያዎች ጥቅም ላይ የዋለ ድምር ማከማቻ፦</translation>
 <translation id="936646668635477464">ካሜራ እና ማይክራፎን</translation>
 <translation id="936801553271523408">የስርዓት ምርመራ ውሂብ</translation>
 <translation id="93766956588638423">ቅጥያ ይጠግኑ</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index 535bf22..d67deb1a 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -1546,6 +1546,7 @@
 <translation id="2433836460518180625">فتح قفل الجهاز فقط</translation>
 <translation id="2434449159125086437">تعذّر إعداد الطابعة. يُرجى التحقّق من الإعداد وإعادة المحاولة.</translation>
 <translation id="2434758125294431199">اختَر من يمكنه مشاركة الملفات مع جهازك.</translation>
+<translation id="2434915728183570229">يمكنك الآن الاطّلاع على تطبيقات هاتفك</translation>
 <translation id="2435137177546457207">‏الأحكام الإضافية لكلٍّ من متصفِّح Google Chrome ونظام التشغيل ChromeOS Flex</translation>
 <translation id="2435248616906486374">تم قطع الاتصال بالشبكة</translation>
 <translation id="2435457462613246316">عرض كلمة المرور</translation>
@@ -4228,6 +4229,7 @@
 <translation id="5072900412896857127">‏يتعذّر تحميل بنود خدمة Google Play. يُرجى التحقُّق من الاتصال بالشبكة وإعادة المحاولة.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" /> و<ph name="FILE2" />}zero{<ph name="FILE1" /> و<ph name="FILE2" /> و# آخر}few{<ph name="FILE1" /> و<ph name="FILE2" /> و# أخرى}many{<ph name="FILE1" /> و<ph name="FILE2" /> و# آخر}other{<ph name="FILE1" /> و<ph name="FILE2" /> و# آخر}}</translation>
 <translation id="5074318175948309511">قد تحتاج هذه الصفحة إلى إعادة التحميل قبل تنفيذ الإعدادات الجديدة.</translation>
+<translation id="5074761966806028321">لا يزال مطلوب منح الإذن لإكمال عملية الإعداد</translation>
 <translation id="5075910247684008552">محتوى غير آمن محظور تلقائيًا على مواقع إلكترونية آمنة</translation>
 <translation id="5078638979202084724">وضع إشارات على كل علامات التبويب</translation>
 <translation id="5078796286268621944">رقم التعريف الشخصي غير صحيح</translation>
@@ -4591,6 +4593,7 @@
 <translation id="5449551289610225147">كلمة المرور غير صالحة</translation>
 <translation id="5449588825071916739">وضع إشارة على جميع علامات التبويب</translation>
 <translation id="5449716055534515760">إغلاق &amp;النافذة</translation>
+<translation id="5452446625764825792">يمكنك الآن الاطّلاع على أحدث الصور والوسائط والتطبيقات المتوفّرة على هاتفك</translation>
 <translation id="5452976525201205853">اللغة <ph name="LANGUAGE" /> متاحة بدون اتصال بالإنترنت.</translation>
 <translation id="5454166040603940656">مع <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">الاطّلاع على المزيد من نتائج البحث</translation>
@@ -4651,6 +4654,7 @@
 <translation id="5499211612787418966">‏مربّع الحوار هذا ليس محل التركيز حاليًا. اضغط على Alt+Shift+A لجعل مربّع الحوار هذا محل التركيز.</translation>
 <translation id="5499313591153584299">قد يلحق هذا الملف الضرر بجهاز الكمبيوتر.</translation>
 <translation id="5499453227627332024">‏هناك ترقية متاحة لحاوية نظام التشغيل Linux. يمكنك أيضًا الترقية لاحقًا من تطبيق "الإعدادات".</translation>
+<translation id="5499476581866658341">يمكنك الآن الاطّلاع على أحدث الصور والوسائط المتوفّرة على هاتفك</translation>
 <translation id="549957179819296104">رمز جديد</translation>
 <translation id="5500168250243071806">‏قد يتم حفظ <ph name="BEGIN_LINK_SEARCH" />سجلّ البحث<ph name="END_LINK_SEARCH" /> و<ph name="BEGIN_LINK_GOOGLE" />بيانات الأنشطة الأخرى<ph name="END_LINK_GOOGLE" /> في حسابك على Google عند تسجيل الدخول إليه. ويمكنك حذفها في أي وقت.</translation>
 <translation id="5500709606820808700">تم تفعيل ميزة "تأكيد السلامة" اليوم.</translation>
@@ -6324,6 +6328,7 @@
 <translation id="7152478047064750137">لا تتطلب هذه الإضافة أذونات خاصة</translation>
 <translation id="7154130902455071009">تغيير الصفحة الرئيسية إلى: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">صورة حالية من الكاميرا أو الملف</translation>
+<translation id="7160182524506337403">يمكنك الآن الاطّلاع على إشعارات هاتفك</translation>
 <translation id="7163202347044721291">جارٍ التحقّق من رمز التفعيل...</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" يمكنها قراءة ملفات الصور والفيديو والصوت في المواقع المحددة.</translation>
 <translation id="7167486101654761064">فت&amp;ح هذا النوع من الملفّات دائمًا</translation>
@@ -7339,6 +7344,7 @@
 <translation id="8138997515734480534">حالة <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">‏ملفات Google Drive</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" /> و<ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">يمكنك إعداد المزيد من الميزات في إعدادات "مركز التحكُّم بالهاتف".</translation>
 <translation id="8141584439523427891">جارٍ الفتح في متصفِّح بديل الآن</translation>
 <translation id="8141725884565838206">إدارة كلمات المرور</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{فيديو واحد}zero{# فيديو}two{فيديوهان}few{# فيديوهات}many{# فيديو}other{# فيديو}}</translation>
@@ -7547,6 +7553,7 @@
 <translation id="833986336429795709">لفتح هذا الرابط، اختر أحد التطبيقات.</translation>
 <translation id="8342221978608739536">لم أحاول</translation>
 <translation id="8342861492835240085">اختيار مجموعة</translation>
+<translation id="8345848587667658367">يمكنك الآن الاطّلاع على أحدث الصور والوسائط والإشعارات والتطبيقات المتوفّرة على هاتفك</translation>
 <translation id="8347227221149377169">مهام الطباعة</translation>
 <translation id="834785183489258869">في وضع التصفُّح المتخفي، لا يمكن للمواقع الإلكترونية استخدام ملفات تعريف الارتباط للاطّلاع على نشاط التصفُّح على المواقع الإلكترونية المختلفة، بهدف تقديم إعلانات مخصّصة لك مثلاً. قد لا تعمل الميزات على بعض المواقع الإلكترونية.</translation>
 <translation id="8350789879725387295">أدوات قلم الشاشة في لوحة الأدوات</translation>
@@ -8156,6 +8163,7 @@
 <translation id="8957757410289731985">تخصيص الملف الشخصي</translation>
 <translation id="895944840846194039">‏ذاكرة JavaScript</translation>
 <translation id="8960208913905765425">تحويل الوحدات باستخدام ميزة "معلومات سريعة"</translation>
+<translation id="8960638196855923532">يمكنك الآن الاطّلاع على الإشعارات والتطبيقات المتوفّرة على هاتفك</translation>
 <translation id="8962051932294470566">لا يمكنك مشاركة أكثر من ملف واحد في كل مرة. أعِد المحاولة عند انتهاء عملية النقل الحالية.</translation>
 <translation id="8962083179518285172">إخفاء التفاصيل</translation>
 <translation id="8962918469425892674">تم السماح لهذا الموقع باستخدام أجهزة استشعار الإضاءة أو الحركة.</translation>
@@ -8307,6 +8315,7 @@
 <translation id="9103868373786083162">اضغط للرجوع، وقائمة السياقات لمشاهدة السجلّ.</translation>
 <translation id="9108035152087032312">‏تسمية &amp;window...</translation>
 <translation id="9108072915170399168">إعداد استخدام البيانات الحالي هو "بدون إنترنت"</translation>
+<translation id="9108294543511800041">يمكنك الآن الاطّلاع على أحدث الصور والوسائط والإشعارات المتوفّرة على هاتفك</translation>
 <translation id="9108674852930645435">الاطّلاع على الميزات الجديدة على جهاز <ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">قد لا يكون نظام أسماء النطاقات الآمن متاحًا طوال الوقت.</translation>
 <translation id="9109122242323516435">لتفريغ مساحة، احذف الملفات من مساحة تخزين الجهاز.</translation>
@@ -8431,7 +8440,6 @@
 <translation id="934503638756687833">‏ستتم أيضًا إزالة العناصر غير المدرجة هنا إذا لزم الأمر. يمكنك الاطلاع على مزيد من المعلومات عن &lt;a href="<ph name="URL" />"&gt;الحماية من البرامج غير المرغوب فيها&lt;/a&gt; في المستند التقني لخصوصية Chrome.</translation>
 <translation id="93480724622239549">خلل أو خطأ</translation>
 <translation id="935854577147268200">‏تم تعديل إعدادات Smart Lock على هاتفك. يمكنك إدخال كلمة مرورك لتحديث هذه الإعدادات. وفي المرة القادمة، سيفتح هاتفك قفل جهاز <ph name="DEVICE_TYPE" />. ويمكنك إيقاف Smart Lock في "الإعدادات".</translation>
-<translation id="93610034168535821">مساحة التخزين المستخدمة من قِبل المواقع الإلكترونية:</translation>
 <translation id="936646668635477464">الكاميرا والميكروفون</translation>
 <translation id="936801553271523408">بيانات تشخيص النظام</translation>
 <translation id="93766956588638423">إصلاح الإضافة</translation>
diff --git a/chrome/app/resources/generated_resources_as.xtb b/chrome/app/resources/generated_resources_as.xtb
index 8a03d0e5..a0003ca 100644
--- a/chrome/app/resources/generated_resources_as.xtb
+++ b/chrome/app/resources/generated_resources_as.xtb
@@ -8428,7 +8428,6 @@
 <translation id="934503638756687833">এই সূচীত নথকা বস্তুবোৰো প্ৰয়োজন হ’লে আঁতৰোৱা হ’ব। &lt;a href="<ph name="URL" />"&gt;অনাকাংক্ষিত ছফ্‌টৱেৰ পৰা সুৰক্ষা&lt;/a&gt;ৰ বিষয়ে Chrome গোপনীয়তা শ্বেতপত্ৰৰ পৰা অধিক জানক।</translation>
 <translation id="93480724622239549">বাগ অথবা আসোঁৱাহ</translation>
 <translation id="935854577147268200">স্মাৰ্ট লকৰ বাবে ব্যৱহৃত ফ’ন সলনি কৰা হ’ল। স্মাৰ্ট লক আপডে’ট কৰিবলৈ নিজৰ পাছৱৰ্ড দিয়ক। আগলৈ আপোনাৰ ফ’নটোৱে আপোনাৰ <ph name="DEVICE_TYPE" /> আনলক কৰিব। আপুনি ছেটিংসমূহ-লৈ গৈ স্মাৰ্ট লক অফ কৰিব পাৰে</translation>
-<translation id="93610034168535821">ছাইটসমূহে ব্যৱহাৰ কৰা মুঠ ষ্ট’ৰেজ:</translation>
 <translation id="936646668635477464">কেমেৰা আৰু মাইক্ৰ’ফ’ন</translation>
 <translation id="936801553271523408">ছিষ্টেমৰ ডায়েগন’ষ্টিক ডেটা</translation>
 <translation id="93766956588638423">এক্সটেনশ্বন মেৰামতি কৰক</translation>
diff --git a/chrome/app/resources/generated_resources_az.xtb b/chrome/app/resources/generated_resources_az.xtb
index 7f51d3c..761ed32b 100644
--- a/chrome/app/resources/generated_resources_az.xtb
+++ b/chrome/app/resources/generated_resources_az.xtb
@@ -2223,6 +2223,7 @@
 <translation id="3067198360141518313">Bu plagini işə salın</translation>
 <translation id="3071624960923923138">Yeni pəncərə açmaq üçün bura klikləyin</translation>
 <translation id="3072775339180057696">Sayta <ph name="FILE_NAME" /> faylına baxmaq üçün icazə verilsin?</translation>
+<translation id="3074499504015191586">Tam Səhifəni Tərcümə edin</translation>
 <translation id="3075874217500066906">Sıfırlama prosesinə başlamaq üçün yenidən başlanma tələb olunur. Yenidən başlanmadan sonra davam etdiyinizi təsdiq etməyiniz istəniləcək.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">Yalnız bu cihazda saxlayın</translation>
@@ -5074,6 +5075,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> kameranızı və mikrofonunuzu istifadə edir</translation>
 <translation id="5935158534896975820">Sertifikat giriş sorğusu hazırlanır (serverdə gözlənilir)</translation>
 <translation id="5935656526031444304">Təhlükəsiz Baxışı idarə edin</translation>
+<translation id="5936065461722368675">Tam səhifəni tərcümə edin</translation>
 <translation id="5938002010494270685">Təhülkəsizlik yeniləməsi əlçatandır</translation>
 <translation id="5939518447894949180">Sıfırlayın</translation>
 <translation id="5939719276406088041">Qısayol yaratmaq olmur</translation>
@@ -8414,7 +8416,6 @@
 <translation id="934503638756687833">Burada göstərilməyən elementlər lazım gələrsə silinə bilər. Chrome məxfilik səhifəsində &lt;a href="<ph name="URL" />"&gt;lazımsız proqram qoruması&lt;/a&gt; haqqında ətraflı məlumat əldə edin.</translation>
 <translation id="93480724622239549">Baq və ya Xəta</translation>
 <translation id="935854577147268200">Smart Lock telefonu dəyişdirildi. Smart Lock'u yeniləmək üçün parolu daxil edin. Növbəti dəfə telefon <ph name="DEVICE_TYPE" /> cihazını kiliddən çıxaracaq. Ayarlardan Smart Lock'u deaktiv edə bilərsiniz</translation>
-<translation id="93610034168535821">Saytlar tərəfindən istifadə olunan cəmi yaddaş:</translation>
 <translation id="936646668635477464">Kamera və mikrofon</translation>
 <translation id="936801553271523408">Sistem diaqnostika datası</translation>
 <translation id="93766956588638423">Artırmanı bərpa edin</translation>
diff --git a/chrome/app/resources/generated_resources_be.xtb b/chrome/app/resources/generated_resources_be.xtb
index aab48f5..dfc4d8e 100644
--- a/chrome/app/resources/generated_resources_be.xtb
+++ b/chrome/app/resources/generated_resources_be.xtb
@@ -8421,7 +8421,6 @@
 <translation id="934503638756687833">Элементы, якіх няма ў гэтым спісе, будуць таксама выдалены пры неабходнасці. Даведайцеся больш пра &lt;a href="<ph name="URL" />"&gt;абарону ад непажаданага праграмнага забеспячэння&lt;/a&gt; з дакумента аб прыватнасці Chrome.</translation>
 <translation id="93480724622239549">Памылка</translation>
 <translation id="935854577147268200">Тэлефон са Smart Lock зменены. Каб абнавіць Smart Lock, увядзіце пароль. Наступны раз прылада <ph name="DEVICE_TYPE" /> будзе разблакіравана з дапамогай вашага тэлефона. Вы можаце выключыць Smart Lock у Наладах</translation>
-<translation id="93610034168535821">Агульнае выкарыстанне сховішча сайтамі:</translation>
 <translation id="936646668635477464">Камера і мікрафон</translation>
 <translation id="936801553271523408">Даныя дыягностыкі сістэмы</translation>
 <translation id="93766956588638423">Выправіць пашырэнне</translation>
diff --git a/chrome/app/resources/generated_resources_bg.xtb b/chrome/app/resources/generated_resources_bg.xtb
index d027b16..d5ebf11f 100644
--- a/chrome/app/resources/generated_resources_bg.xtb
+++ b/chrome/app/resources/generated_resources_bg.xtb
@@ -8431,7 +8431,6 @@
 <translation id="934503638756687833">При необходимост ще бъдат премахнати и елементи, които не са посочени тук. Научете повече за &lt;a href="<ph name="URL" />"&gt;защитата от нежелан софтуер&lt;/a&gt; в информационния бюлетин за поверителността на Chrome.</translation>
 <translation id="93480724622239549">Програмен дефект или грешка</translation>
 <translation id="935854577147268200">Телефонът за Smart Lock е променен. Въведете паролата си, за да актуализирате функцията. Следващия път телефонът ви ще отключи устройството ви <ph name="DEVICE_TYPE" />. Можете да изключите Smart Lock от настройките.</translation>
-<translation id="93610034168535821">Общо място за съхранение, използвано от сайтове:</translation>
 <translation id="936646668635477464">Камера и микрофон</translation>
 <translation id="936801553271523408">Диагностични данни за системата</translation>
 <translation id="93766956588638423">Поправяне на разширението</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index 185282f..3c96731 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -8445,7 +8445,6 @@
 <translation id="934503638756687833">কোনও আইটেম এখানে উল্লেখ করা না থাকলেও সেটি প্রয়োজন অনুযায়ী সরিয়ে দেওয়া হবে। &lt;a href="<ph name="URL" />"&gt;অবাঞ্ছিত সফ্টওয়্যার থেকে সুরক্ষার&lt;/a&gt; বিষয়ে আরও জানতে Chrome-এর গোপনীয়তা বিষয়ক শ্বেতপত্র পড়ুন।</translation>
 <translation id="93480724622239549">ত্রুটি বা সমস্যা</translation>
 <translation id="935854577147268200">ফোনে Smart Lock ডেটা পরিবর্তিত হয়েছে। Smart Lock আপডেট করতে আপনার পাসওয়ার্ড লিখুন। পরের বার, আপনার ফোন <ph name="DEVICE_TYPE" /> আনলক করতে পারবে। সেটিংসে গিয়ে Smart Lock বন্ধ করতে পারেন।</translation>
-<translation id="93610034168535821">সাইটগুলির ব্যবহার করা মোট স্টোরেজ:</translation>
 <translation id="936646668635477464">ক্যামেরা ও মাইক্রোফোন</translation>
 <translation id="936801553271523408">সিস্টেম ডায়াগনোস্টিক ডেটা</translation>
 <translation id="93766956588638423">এক্সটেনশন মেরামত করুন</translation>
diff --git a/chrome/app/resources/generated_resources_bs.xtb b/chrome/app/resources/generated_resources_bs.xtb
index bd17a45c..1b7a1cb 100644
--- a/chrome/app/resources/generated_resources_bs.xtb
+++ b/chrome/app/resources/generated_resources_bs.xtb
@@ -8446,7 +8446,6 @@
 <translation id="934503638756687833">Stavke koje ovdje nisu navedene također će se po potrebi ukloniti. Saznajte više o &lt;a href="<ph name="URL" />"&gt;zaštiti od neželjenog softvera&lt;/a&gt; u Chromeovoj bijeloj knjizi o privatnosti.</translation>
 <translation id="93480724622239549">Propust ili greška</translation>
 <translation id="935854577147268200">Telefon za Smart Lock je promijenjen. Unesite lozinku da ažurirate Smart Lock. Sljedeći put će vaš telefon otključati vaš uređaj <ph name="DEVICE_TYPE" />. Možete isključiti Smart Lock u Postavkama</translation>
-<translation id="93610034168535821">Ukupna pohrana koju koriste web lokacije:</translation>
 <translation id="936646668635477464">Kamera i mikrofon</translation>
 <translation id="936801553271523408">Dijagnostički podaci sistema</translation>
 <translation id="93766956588638423">Popravi ekstenziju</translation>
diff --git a/chrome/app/resources/generated_resources_ca.xtb b/chrome/app/resources/generated_resources_ca.xtb
index 1906a13e..c94b664 100644
--- a/chrome/app/resources/generated_resources_ca.xtb
+++ b/chrome/app/resources/generated_resources_ca.xtb
@@ -1908,6 +1908,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Suprimeix 1 aplicació no admesa}other{Suprimeix # aplicacions no admeses}}</translation>
 <translation id="2776560192867872731">Canvia el nom del dispositiu <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Suprimeix aquest contenidor</translation>
+<translation id="2778471504622896352">Afegeix aplicacions remotes al menú d'aplicacions de ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">S'ha produït un error en instal·lar l'aplicació per a Linux</translation>
 <translation id="2783298271312924866">Baixat</translation>
@@ -2223,6 +2224,7 @@
 <translation id="3067198360141518313">Executa aquest connector</translation>
 <translation id="3071624960923923138">Pots fer clic aquí per obrir una pestanya nova</translation>
 <translation id="3072775339180057696">Vols permetre que el lloc web vegi <ph name="FILE_NAME" />?</translation>
+<translation id="3074499504015191586">Tradueix la pàgina completa</translation>
 <translation id="3075874217500066906">Per començar el procés de Powerwash, cal que reinicieu el dispositiu. Després de fer-ho, haureu de confirmar que voleu continuar.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">Desa-la només en aquest dispositiu</translation>
@@ -3542,6 +3544,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> i <ph name="NUMBER_OF_OTHER_SWITCHES" /> interruptors més</translation>
 <translation id="439266289085815679"><ph name="USER_EMAIL" /> controla la configuració del Bluetooth.</translation>
 <translation id="4392896746540753732">Edita el fitxer de configuració</translation>
+<translation id="4393713825278446281">Dispositius amb Vinculació ràpida desats a <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Desactiva</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Obre-les totes}=1{&amp;Obre l'adreça d'interès}other{&amp;Obre-les totes ({COUNT})}}</translation>
 <translation id="4397372003838952832">No caldrà que recordis aquesta contrasenya. Es desarà a <ph name="GOOGLE_PASSWORD_MANAGER" /> per a <ph name="EMAIL" />.</translation>
@@ -3771,6 +3774,7 @@
 <translation id="4615586811063744755">cap galeta seleccionada</translation>
 <translation id="461661862154729886">Font d'energia</translation>
 <translation id="4617001782309103936">És massa curt</translation>
+<translation id="4617019240346358451">Torna a carregar la pàgina per utilitzar <ph name="EXTENSION_NAME" /></translation>
 <translation id="4617270414136722281">Opcions d'extensió</translation>
 <translation id="4617880081511131945">No es pot establir la connexió</translation>
 <translation id="4619564267100705184">Verifica la teva identitat</translation>
@@ -3986,6 +3990,7 @@
 <translation id="4833683849865011483">S'ha trobat 1 impressora al servidor d'impressió</translation>
 <translation id="4836504898754963407">Gestiona les empremtes digitals</translation>
 <translation id="4837128290434901661">Vols tornar a utilitzar la Cerca de Google?</translation>
+<translation id="4837165100461973682">Torna a carregar la pàgina perquè s'apliquin els canvis</translation>
 <translation id="4837926214103741331">No teniu autorització per fer servir aquest dispositiu. Contacteu amb el propietari del dispositiu per obtenir el permís d'inici de sessió.</translation>
 <translation id="4837952862063191349">Per desbloquejar i restaurar les dades locals, introduïu la contrasenya antiga de: <ph name="DEVICE_TYPE" /></translation>
 <translation id="4838170306476614339">Mostra les fotos, els fitxers multimèdia i les notificacions del telèfon</translation>
@@ -4295,6 +4300,7 @@
 <translation id="5150254825601720210">Nom del servidor SSL de certificats de Netscape</translation>
 <translation id="5151354047782775295">Si no alliberes espai de disc pot ser que algunes dades se suprimeixin automàticament</translation>
 <translation id="5153234146675181447">Oblida el telèfon</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Configuració avançada de <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Assumpte</translation>
 <translation id="5155327081870541046">A la barra d'adreces, introdueix la drecera del lloc web que vulguis cercar, com ara "@bookmarks". A continuació, prem la tecla de drecera que prefereixis i introdueix el terme de cerca.</translation>
@@ -5070,6 +5076,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> està utilitzant la càmera i el micròfon</translation>
 <translation id="5935158534896975820">S'està preparant la sol·licitud de signatura del certificat (en espera del servidor)</translation>
 <translation id="5935656526031444304">Gestiona Navegació segura</translation>
+<translation id="5936065461722368675">Tradueix la pàgina completa</translation>
 <translation id="5938002010494270685">Hi ha una actualització de seguretat disponible</translation>
 <translation id="5939518447894949180">Restableix</translation>
 <translation id="5939719276406088041">No es pot crear la drecera</translation>
@@ -5929,6 +5936,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> s'ha afegit de manera remota</translation>
 <translation id="6790820461102226165">Afegeix una persona...</translation>
 <translation id="6793604637258913070">Ressalta la marca d'inserció de text quan es mostri o es mogui</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">La cerca automàtica et permet moure't pels elements de la pantalla automàticament. Quan un element es marqui, prem Selecciona per activar-lo.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">S'ha produït un error.</translation>
@@ -7803,6 +7811,7 @@
 <translation id="8642947597466641025">Fa el text més gran</translation>
 <translation id="8643443571868262066">El fitxer <ph name="FILE_NAME" /> pot ser perillós. Vols enviar-lo a la Protecció avançada de Google perquè l'analitzi?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{No hi ha cap galeta}=1{S'ha bloquejat 1 galeta}other{S'han bloquejat # galetes}}</translation>
+<translation id="864423554496711319">Dispositius desats al teu compte</translation>
 <translation id="8644655801811752511">Aquesta clau de seguretat no es pot restablir. Prova de restablir la clau immediatament després d'inserir-la.</translation>
 <translation id="8645354835496065562">Continua permetent l'accés als sensors</translation>
 <translation id="8645920082661222035">Prediu esdeveniments perillosos abans que es produeixin i t'avisa</translation>
@@ -8407,7 +8416,6 @@
 <translation id="934503638756687833">Si cal, també se suprimiran elements no inclosos en aquesta llista. Obtén més informació sobre la &lt;a href="<ph name="URL" />"&gt;protecció contra programari no desitjat&lt;/a&gt; a l'informe de privadesa de Chrome.</translation>
 <translation id="93480724622239549">Error</translation>
 <translation id="935854577147268200">El telèfon Smart Lock ha canviat. Introdueix la contrasenya per actualitzar Smart Lock. La propera vegada, <ph name="DEVICE_TYPE" /> es desbloquejarà amb el telèfon. Pots desactivar Smart Lock a Configuració.</translation>
-<translation id="93610034168535821">Emmagatzematge total utilitzat pels llocs web:</translation>
 <translation id="936646668635477464">Càmera i micròfon</translation>
 <translation id="936801553271523408">Dades de diagnòstic del sistema</translation>
 <translation id="93766956588638423">Repara l'extensió</translation>
diff --git a/chrome/app/resources/generated_resources_cs.xtb b/chrome/app/resources/generated_resources_cs.xtb
index 4135265..2dac77a 100644
--- a/chrome/app/resources/generated_resources_cs.xtb
+++ b/chrome/app/resources/generated_resources_cs.xtb
@@ -8419,7 +8419,6 @@
 <translation id="934503638756687833">V případě potřeby budou odstraněny i položky, které zde nejsou uvedeny. Další informace o &lt;a href="<ph name="URL" />"&gt;ochraně před nežádoucím softwarem&lt;/a&gt; najdete v informační brožuře o ochraně soukromí v Chromu.</translation>
 <translation id="93480724622239549">Chyba</translation>
 <translation id="935854577147268200">Telefon pro Smart Lock se změnil. Chcete-li funkci Smart Lock aktualizovat, zadejte heslo. Příště váš telefon zařízení <ph name="DEVICE_TYPE" /> odemkne. Funkci Smart Lock můžete vypnout v Nastavení.</translation>
-<translation id="93610034168535821">Celkové úložiště využité weby:</translation>
 <translation id="936646668635477464">Kamera a mikrofon</translation>
 <translation id="936801553271523408">Diagnostická data o systému</translation>
 <translation id="93766956588638423">Opravit rozšíření</translation>
diff --git a/chrome/app/resources/generated_resources_cy.xtb b/chrome/app/resources/generated_resources_cy.xtb
index 073d387..0a88298 100644
--- a/chrome/app/resources/generated_resources_cy.xtb
+++ b/chrome/app/resources/generated_resources_cy.xtb
@@ -8445,7 +8445,6 @@
 <translation id="934503638756687833">Bydd eitemau nad ydynt wedi'u rhestru yma hefyd yn cael eu tynnu, os oes angen. Dysgu rhagor am &lt;a href="<ph name="URL" />"&gt;amddiffyn rhag meddalwedd digroeso/a&gt; ym mhapur gwyn preifatrwydd Chrome.</translation>
 <translation id="93480724622239549">Byg neu Wall</translation>
 <translation id="935854577147268200">Cafodd y ffôn Smart Lock ei newid. Rhowch eich cyfrinair i ddiweddaru Smart Lock. Y tro nesaf, bydd eich ffôn yn datgloi'ch <ph name="DEVICE_TYPE" />. Gallwch ddiffodd Smart Lock yn y gosodiadau</translation>
-<translation id="93610034168535821">Cyfanswm y storfa sy'n cael ei defnyddio gan wefannau:</translation>
 <translation id="936646668635477464">Camera a meicroffon</translation>
 <translation id="936801553271523408">Data diagnosteg system</translation>
 <translation id="93766956588638423">Trwsio'r estyniad</translation>
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb
index b7d6d9cb..0ea8513e 100644
--- a/chrome/app/resources/generated_resources_da.xtb
+++ b/chrome/app/resources/generated_resources_da.xtb
@@ -8444,7 +8444,6 @@
 <translation id="934503638756687833">Elementer, der ikke er angivet her, fjernes også om nødvendigt. Få flere oplysninger om &lt;a href="<ph name="URL" />"&gt;beskyttelse mod uønsket software&lt;/a&gt; i rapporten om beskyttelse af personlige oplysninger i Chrome.</translation>
 <translation id="93480724622239549">Fejl</translation>
 <translation id="935854577147268200">Smart Lock-telefonen er blevet ændret. Angiv din adgangskode for at opdatere Smart Lock. Næste gang låser din telefon din <ph name="DEVICE_TYPE" /> op. Du kan deaktivere Smart Lock i Indstillinger</translation>
-<translation id="93610034168535821">Samlet lagerplads, der anvendes af websites:</translation>
 <translation id="936646668635477464">Kamera og mikrofon</translation>
 <translation id="936801553271523408">Data til systemdiagnosticering</translation>
 <translation id="93766956588638423">Reparer udvidelsen</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index 7b587e16..f66d3e43 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -8417,7 +8417,6 @@
 <translation id="934503638756687833">Elemente, die hier nicht aufgeführt sind, werden bei Bedarf ebenfalls entfernt. Weitere Informationen zum &lt;a href="<ph name="URL" />"&gt;Schutz vor unerwünschter Software&lt;/a&gt; findest du im Whitepaper zum Datenschutz in Chrome.</translation>
 <translation id="93480724622239549">Programmfehler oder sonstiger Fehler</translation>
 <translation id="935854577147268200">Das Smartphone für Smart Lock wurde geändert. Gib dein Passwort ein, um Smart Lock zu aktualisieren. Das nächste Mal wird dein <ph name="DEVICE_TYPE" /> von deinem Smartphone entsperrt. Du kannst Smart Lock in den Einstellungen deaktivieren.</translation>
-<translation id="93610034168535821">Von Websites belegter Speicherplatz insgesamt:</translation>
 <translation id="936646668635477464">Kamera &amp; Mikrofon</translation>
 <translation id="936801553271523408">Fehlerberichte des Systems</translation>
 <translation id="93766956588638423">Erweiterung reparieren</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index ac8fbd9..8e337be 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -8439,7 +8439,6 @@
 <translation id="934503638756687833">Θα διαγραφούν και όσα στοιχεία δεν αναφέρονται εδώ, αν χρειαστεί. Μάθετε περισσότερα σχετικά με &lt;a href="<ph name="URL" />"&gt;την προστασία από ανεπιθύμητο λογισμικό&lt;/a&gt; στη λευκή βίβλο απορρήτου του Chrome.</translation>
 <translation id="93480724622239549">Σφάλμα ή λάθος</translation>
 <translation id="935854577147268200">Το τηλέφωνο στο οποίο χρησιμοποιείται το Smart Lock άλλαξε. Καταχωρίστε τον κωδικό πρόσβασης, για να ενημερώσετε το Smart Lock. Την επόμενη φορά, το τηλέφωνό σας θα ξεκλειδώσει τη συσκευή <ph name="DEVICE_TYPE" />. Μπορείτε να απενεργοποιήσετε το Smart Lock στις Ρυθμίσεις.</translation>
-<translation id="93610034168535821">Συνολικός αποθηκευτικός χώρος που χρησιμοποιείται από ιστοτόπους:</translation>
 <translation id="936646668635477464">Κάμερα και μικρόφωνο</translation>
 <translation id="936801553271523408">Διαγνωστικά δεδομένα συστήματος</translation>
 <translation id="93766956588638423">Επιδιόρθωση επέκτασης</translation>
diff --git a/chrome/app/resources/generated_resources_en-GB.xtb b/chrome/app/resources/generated_resources_en-GB.xtb
index ffb1f78c..9c96a93 100644
--- a/chrome/app/resources/generated_resources_en-GB.xtb
+++ b/chrome/app/resources/generated_resources_en-GB.xtb
@@ -8442,7 +8442,6 @@
 <translation id="934503638756687833">Items not listed here will also be removed, if needed. Learn more about &lt;a href="<ph name="URL" />"&gt;unwanted software protection&lt;/a&gt; in the Chrome privacy white paper.</translation>
 <translation id="93480724622239549">Bug or error</translation>
 <translation id="935854577147268200">Smart Lock phone changed. Enter your password to update Smart Lock. Next time, your phone will unlock your <ph name="DEVICE_TYPE" />. You can turn off Smart Lock in Settings</translation>
-<translation id="93610034168535821">Total storage used by sites:</translation>
 <translation id="936646668635477464">Camera and microphone</translation>
 <translation id="936801553271523408">System diagnostic data</translation>
 <translation id="93766956588638423">Repair extension</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index cb3b455..8123d86 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -1905,6 +1905,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Quitar 1 app no compatible}other{Quitar # apps no compatibles}}</translation>
 <translation id="2776560192867872731">Cambiar el nombre de dispositivo de <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Borrar este contenedor</translation>
+<translation id="2778471504622896352">Agregar apps remotas al selector de ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Se produjo un error al instalar la app de Linux</translation>
 <translation id="2783298271312924866">Descargado</translation>
@@ -3540,6 +3541,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> y <ph name="NUMBER_OF_OTHER_SWITCHES" /> interruptores más</translation>
 <translation id="439266289085815679"><ph name="USER_EMAIL" /> controla la configuración de Bluetooth.</translation>
 <translation id="4392896746540753732">Edita el archivo de configuración</translation>
+<translation id="4393713825278446281">Los dispositivos de Vinculación rápida se guardaron en <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Inhabilitar</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Abrir todo}=1{&amp;Abrir favorito}other{&amp;Abrir todo ({COUNT})}}</translation>
 <translation id="4397372003838952832">No es necesario que recuerdes esta contraseña. Se guardará en <ph name="GOOGLE_PASSWORD_MANAGER" /> para <ph name="EMAIL" />.</translation>
@@ -3769,6 +3771,7 @@
 <translation id="4615586811063744755">no se seleccionaron cookies</translation>
 <translation id="461661862154729886">Fuente de energía</translation>
 <translation id="4617001782309103936">Demasiado corto</translation>
+<translation id="4617019240346358451">Vuelve a cargar la página para usar "<ph name="EXTENSION_NAME" />"</translation>
 <translation id="4617270414136722281">Opciones de las extensiones</translation>
 <translation id="4617880081511131945">No se puede establecer la conexión</translation>
 <translation id="4619564267100705184">Verificar tu identidad</translation>
@@ -3984,6 +3987,7 @@
 <translation id="4833683849865011483">Se encontró 1 impresora en el servidor de impresión</translation>
 <translation id="4836504898754963407">Administrar huellas dactilares</translation>
 <translation id="4837128290434901661">¿Deseas volver a usar la Búsqueda de Google?</translation>
+<translation id="4837165100461973682">Vuelve a cargar la página para aplicar los cambios</translation>
 <translation id="4837926214103741331">No tienes autorización para utilizar este dispositivo. Para obtener permiso de acceso, comunícate con el propietario del dispositivo.</translation>
 <translation id="4837952862063191349">Para desbloquear y restaurar los datos locales, ingresa la contraseña anterior de <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Ve las fotos, el contenido multimedia y las notificaciones del teléfono</translation>
@@ -4293,6 +4297,7 @@
 <translation id="5150254825601720210">Nombre del servidor SSL para el certificado de Microsoft</translation>
 <translation id="5151354047782775295">Libera espacio en el disco o selecciona los datos que se pueden borrar de forma automática.</translation>
 <translation id="5153234146675181447">Olvidar el teléfono</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Configuración avanzada para <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Asunto</translation>
 <translation id="5155327081870541046">En la barra de direcciones, ingresa el atajo para el sitio donde quieres realizar la búsqueda, como "@favoritos". Luego, presiona la combinación de teclas que hayas elegido y escribe un término de búsqueda.</translation>
@@ -5928,6 +5933,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> se agregó de forma remota</translation>
 <translation id="6790820461102226165">Agregar una persona…</translation>
 <translation id="6793604637258913070">Destacar el símbolo de intercalación de texto cuando aparece o se mueve</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">El escaneo automático permite pasar de forma automática de un elemento a otro de la pantalla. Cuando hay un elemento destacado, presiona "Seleccionar" para activarlo.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Se produjo un error.</translation>
@@ -7801,6 +7807,7 @@
 <translation id="8642947597466641025">Aumentar el tamaño del texto</translation>
 <translation id="8643443571868262066">Es posible que el archivo <ph name="FILE_NAME" /> sea peligroso. ¿Quieres enviarlo al Programa de protección avanzada de Google para que lo analicemos?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{No hay cookies}=1{Se bloqueó 1 cookie}other{Se bloquearon # cookies}}</translation>
+<translation id="864423554496711319">Dispositivos guardados en tu cuenta</translation>
 <translation id="8644655801811752511">No se puede restablecer esta llave de seguridad. Intenta restablecerla inmediatamente después de insertarla.</translation>
 <translation id="8645354835496065562">Seguir permitiendo el acceso a los sensores</translation>
 <translation id="8645920082661222035">Predice y te advierte sobre eventos peligrosos antes de que ocurran.</translation>
@@ -8405,7 +8412,6 @@
 <translation id="934503638756687833">Los elementos que no se muestran aquí también se quitarán si es necesario. Obtén más información sobre &lt;a href="<ph name="URL" />"&gt;la protección contra software no deseado&lt;/a&gt; en el informe de privacidad de Chrome.</translation>
 <translation id="93480724622239549">Fallo o error</translation>
 <translation id="935854577147268200">Se cambió el número de Smart Lock. Ingresa tu contraseña para actualizar Smart Lock. La próxima vez, tu teléfono desbloqueará tu <ph name="DEVICE_TYPE" />. Puedes desactivar Smart Lock en la configuración</translation>
-<translation id="93610034168535821">Almacenamiento total que usan los sitios:</translation>
 <translation id="936646668635477464">Cámara y micrófono</translation>
 <translation id="936801553271523408">Datos de diagnóstico del sistema</translation>
 <translation id="93766956588638423">Reparar extensión</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index 43a8f10f..a874c74 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -1909,6 +1909,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Quitar 1 aplicación no admitida}other{Quitar # aplicaciones no admitidas}}</translation>
 <translation id="2776560192867872731">Cambia el nombre del dispositivo <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Eliminar este contenedor</translation>
+<translation id="2778471504622896352">Añadir aplicaciones remotas al menú de aplicaciones de ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Error al instalar la aplicación de Linux</translation>
 <translation id="2783298271312924866">Descargado</translation>
@@ -3543,6 +3544,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> y <ph name="NUMBER_OF_OTHER_SWITCHES" /> interruptores más</translation>
 <translation id="439266289085815679">El usuario <ph name="USER_EMAIL" /> controla la configuración del Bluetooth.</translation>
 <translation id="4392896746540753732">Edita el archivo de configuración.</translation>
+<translation id="4393713825278446281">Los dispositivos de Emparejamiento rápido se guardan en <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Inhabilitar</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Abrir todas}=1{&amp;Abrir marcador}other{&amp;Abrir todas ({COUNT})}}</translation>
 <translation id="4397372003838952832">No tendrás que recordar esta contraseña. Se guardará en el <ph name="GOOGLE_PASSWORD_MANAGER" /> de <ph name="EMAIL" />.</translation>
@@ -3772,6 +3774,7 @@
 <translation id="4615586811063744755">no se ha seleccionado ninguna cookie</translation>
 <translation id="461661862154729886">Fuente de energía</translation>
 <translation id="4617001782309103936">Demasiado corto</translation>
+<translation id="4617019240346358451">Vuelve a cargar la página para usar <ph name="EXTENSION_NAME" /></translation>
 <translation id="4617270414136722281">Opciones de extensión</translation>
 <translation id="4617880081511131945">No se puede establecer conexión</translation>
 <translation id="4619564267100705184">Verificar mi identidad</translation>
@@ -3987,6 +3990,7 @@
 <translation id="4833683849865011483">Se ha encontrado 1 impresora en el servidor de impresión</translation>
 <translation id="4836504898754963407">Gestionar huellas dactilares</translation>
 <translation id="4837128290434901661">¿Cambiar de nuevo a la Búsqueda de Google?</translation>
+<translation id="4837165100461973682">Vuelve a cargar la página para aplicar los cambios</translation>
 <translation id="4837926214103741331">No tienes autorización para utilizar este dispositivo. Ponte en contacto con su propietario para obtener permiso de inicio de sesión.</translation>
 <translation id="4837952862063191349">Para desbloquear y restaurar tus datos locales, introduce la antigua contraseña de tu <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Consulta las fotos, el contenido multimedia y las notificaciones de tu teléfono</translation>
@@ -4297,6 +4301,7 @@
 <translation id="5150254825601720210">Nombre de servidor SSL de certificado de Netscape</translation>
 <translation id="5151354047782775295">Libera espacio en el disco o puede que se eliminen automáticamente ciertos datos</translation>
 <translation id="5153234146675181447">Olvidar teléfono</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Configuración avanzada para <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Asunto</translation>
 <translation id="5155327081870541046">En la barra de direcciones, escribe el atajo del sitio en el que quieras buscar, como "@bookmarks". A continuación, pulsa tu atajo preferido y escribe el término de búsqueda.</translation>
@@ -5934,6 +5939,7 @@
 <translation id="6790497603648687708">Se ha añadido <ph name="EXTENSION_NAME" /> de forma remota</translation>
 <translation id="6790820461102226165">Añadir perfil...</translation>
 <translation id="6793604637258913070">Resaltar el símbolo de intercalación de texto cuando aparezca o se mueva</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">La búsqueda automática te permite pasar de un elemento a otro en la pantalla de forma automática. Cuando haya un elemento resaltado, pulsa "Seleccionar" para activarlo.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Vaya, algo ha salido mal...</translation>
@@ -7810,6 +7816,7 @@
 <translation id="8642947597466641025">Ampliar el tamaño del texto</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> podría ser peligroso. ¿Quieres enviarlo a Protección Avanzada de Google para que lo analice?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{No hay cookies}=1{1 cookie bloqueada}other{# cookies bloqueadas}}</translation>
+<translation id="864423554496711319">Dispositivos guardados en tu cuenta</translation>
 <translation id="8644655801811752511">No se puede restablecer esta llave de seguridad. Intenta restablecer la llave de seguridad inmediatamente después de introducirla.</translation>
 <translation id="8645354835496065562">Seguir permitiendo el acceso a los sensores</translation>
 <translation id="8645920082661222035">Predice y te advierte de eventos peligrosos antes de que se produzcan</translation>
@@ -8416,7 +8423,6 @@
 <translation id="934503638756687833">Si es necesario, también se eliminarán elementos que no se incluyan aquí. Consulta más información sobre la &lt;a href="<ph name="URL" />"&gt;protección contra software no deseado&lt;/a&gt; en el informe de privacidad de Chrome.</translation>
 <translation id="93480724622239549">Fallo o error</translation>
 <translation id="935854577147268200">El teléfono de Smart Lock ha cambiado. Introduce tu contraseña para actualizar Smart Lock. La próxima vez, el teléfono desbloqueará tu <ph name="DEVICE_TYPE" />. Puedes desactivar Smart Lock en la configuración.</translation>
-<translation id="93610034168535821">Almacenamiento total usado por sitios:</translation>
 <translation id="936646668635477464">Cámara y micrófono</translation>
 <translation id="936801553271523408">Datos de diagnóstico del sistema</translation>
 <translation id="93766956588638423">Reparar extensión</translation>
diff --git a/chrome/app/resources/generated_resources_et.xtb b/chrome/app/resources/generated_resources_et.xtb
index a08099f..29d7ac1 100644
--- a/chrome/app/resources/generated_resources_et.xtb
+++ b/chrome/app/resources/generated_resources_et.xtb
@@ -8421,7 +8421,6 @@
 <translation id="934503638756687833">Siinsest loendist puuduvad üksused võib vajaduse korral ka eemaldada. Vaadake lisateavet &lt;a href="<ph name="URL" />"&gt;soovimatu tarkvara vastase kaitse&lt;/a&gt; kohta Chrome'i privaatsusjuhendist.</translation>
 <translation id="93480724622239549">Tõrge või viga</translation>
 <translation id="935854577147268200">Smart Locki telefoni muudeti. Funktsiooni Smart Lock värskendamiseks sisestage oma parool. Järgmisel korral avab seadme <ph name="DEVICE_TYPE" /> teie telefon. Funktsiooni Smart Lock saab välja lülitada menüüs Seaded.</translation>
-<translation id="93610034168535821">Saitide kasutatav salvestusruum kokku:</translation>
 <translation id="936646668635477464">Kaamera ja mikrofon</translation>
 <translation id="936801553271523408">Süsteemidiagnostika andmed</translation>
 <translation id="93766956588638423">Laiendi parandamine</translation>
diff --git a/chrome/app/resources/generated_resources_eu.xtb b/chrome/app/resources/generated_resources_eu.xtb
index e08e58613..7a1de41 100644
--- a/chrome/app/resources/generated_resources_eu.xtb
+++ b/chrome/app/resources/generated_resources_eu.xtb
@@ -1543,6 +1543,7 @@
 <translation id="2433836460518180625">Desblokeatu gailua bakarrik</translation>
 <translation id="2434449159125086437">Ezin da konfiguratu inprimagailua. Egiaztatu konfigurazioa eta saiatu berriro.</translation>
 <translation id="2434758125294431199">Hautatu nork parteka dezakeen zurekin edukia</translation>
+<translation id="2434915728183570229">Orain, telefonoko aplikazioak ikus ditzakezu</translation>
 <translation id="2435137177546457207">Google Chrome-ren eta ChromeOS Flex-en baldintza gehigarriak</translation>
 <translation id="2435248616906486374">Sarea deskonektatu da</translation>
 <translation id="2435457462613246316">Erakutsi pasahitza</translation>
@@ -2223,6 +2224,7 @@
 <translation id="3067198360141518313">Abiarazi plugin hau</translation>
 <translation id="3071624960923923138">Egin klik hemen beste fitxa bat irekitzeko</translation>
 <translation id="3072775339180057696"><ph name="FILE_NAME" /> ikusteko baimena eman nahi diozu webguneari?</translation>
+<translation id="3074499504015191586">Itzuli orri osoa</translation>
 <translation id="3075874217500066906">Fabrikako ezarpenak Powerwash bidez berrezartzeko prozesua hasteko, gailua berrabiarazi egin behar da. Berrabiarazi ondoren, jarraitu egin nahi duzun galdetuko dizugu.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" /> / <ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">Gorde gailu honetan bakarrik</translation>
@@ -4225,6 +4227,7 @@
 <translation id="5072900412896857127">Ezin dira kargatu Google Play-ren Zerbitzu-baldintzak. Egiaztatu sarera konektatuta zaudela eta saiatu berriro.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" /> eta beste #}}</translation>
 <translation id="5074318175948309511">Orria berriro kargatu beharko da ezarpen berriek eragina izan dezaten.</translation>
+<translation id="5074761966806028321">Oraindik baimena behar da konfigurazio-prozesua osatzeko</translation>
 <translation id="5075910247684008552">Segurua ez den edukia modu lehenetsian blokeatzen da webgune seguruetan</translation>
 <translation id="5078638979202084724">Egin fitxa guztien laster-marka</translation>
 <translation id="5078796286268621944">Okerra da PINa</translation>
@@ -4588,6 +4591,7 @@
 <translation id="5449551289610225147">Pasahitzak ez du balio</translation>
 <translation id="5449588825071916739">Ezarri laster-marka fitxa guztiei</translation>
 <translation id="5449716055534515760">Itxi l&amp;eihoa</translation>
+<translation id="5452446625764825792">Orain, telefonoko azken argazki, multimedia-eduki eta aplikazioak ikus ditzakezu</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (Interneteko konexiorik gabe funtzionatzen du)</translation>
 <translation id="5454166040603940656">Hornitzailea: <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Ikusi bilaketa-emaitza gehiago</translation>
@@ -4648,6 +4652,7 @@
 <translation id="5499211612787418966">Une honetan, leihoa ez dago fokuratuta. Leihoa fokuratzeko, sakatu Alt + Maius + A.</translation>
 <translation id="5499313591153584299">Fitxategiak ordenagailua kalte dezake.</translation>
 <translation id="5499453227627332024">Linux Container-en bertsio berri bat dago erabilgarri. Geroago ere berri dezakezu bertsioa Ezarpenak aplikazioan.</translation>
+<translation id="5499476581866658341">Orain, telefonoko azken argazki eta multimedia-edukiak ikus ditzakezu</translation>
 <translation id="549957179819296104">Ikono berria</translation>
 <translation id="5500168250243071806">Litekeena da <ph name="BEGIN_LINK_SEARCH" />bilaketa-historia<ph name="END_LINK_SEARCH" /> eta <ph name="BEGIN_LINK_GOOGLE" />beste jarduera batzuk<ph name="END_LINK_GOOGLE" /> Google-ko kontuan gordetzea saioa hasita daukazun bitartean. Nahi duzunean ezaba ditzakezu.</translation>
 <translation id="5500709606820808700">Gaur egin da segurtasun-egiaztapena</translation>
@@ -5073,6 +5078,7 @@
 <translation id="5933522550144185133">Kamera eta mikrofonoa erabiltzen ari da <ph name="APP_NAME" /></translation>
 <translation id="5935158534896975820">Ziurtagiria sinatzeko eskaera prestatzen (zerbitzariaren zain)</translation>
 <translation id="5935656526031444304">Kudeatu arakatze segurua</translation>
+<translation id="5936065461722368675">Itzuli orri osoa</translation>
 <translation id="5938002010494270685">Segurtasun-eguneratze bat dago</translation>
 <translation id="5939518447894949180">Berrezarri</translation>
 <translation id="5939719276406088041">Ezin da sortu lasterbidea</translation>
@@ -6309,6 +6315,7 @@
 <translation id="7152478047064750137">Luzapen honek ez du baimen berezirik behar</translation>
 <translation id="7154130902455071009">Aldatu hasiera-orria hau izan dadin: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Lehendik duzun kamerako argazkia edo fitxategia</translation>
+<translation id="7160182524506337403">Orain, telefonoko jakinarazpenak ikus ditzakezu</translation>
 <translation id="7163202347044721291">Aktibazio-kodea egiaztatzen…</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" luzapenak markatutako kokapenetako irudiak, bideoak eta soinu-fitxategiak irakur ditzake.</translation>
 <translation id="7167486101654761064">Ireki &amp;beti mota honetako fitxategiak</translation>
@@ -7152,7 +7159,7 @@
 <translation id="7974936243149753750">Bilatu gainetik</translation>
 <translation id="7975504106303186033">Chrome Education-eko gailu hau G Suite for Education-eko kontu batekin erregistratu behar duzu. Beste kontu bat erregistratzeko, joan g.co/workspace/edusignup helbidera.</translation>
 <translation id="7978412674231730200">Gako pribatua</translation>
-<translation id="7978450511781612192">Zure Google-ko kontuen saioa amaituko da. Aurrerantzean, ez dira sinkronizatuko laster-markak, historia, pasahitzak eta beste.</translation>
+<translation id="7978450511781612192">Zure Google-ko kontuetako saioa amaituko da. Aurrerantzean, ez dira sinkronizatuko laster-markak, historia, pasahitzak eta beste.</translation>
 <translation id="7980084013673500153">Erreproduzigai IDa: <ph name="ASSET_ID" /></translation>
 <translation id="7981313251711023384">Aurrekargatu orriak azkarrago arakatzeko eta bilatzeko</translation>
 <translation id="798145602633458219">Erantsi <ph name="SUGGESTION_NAME" /> iradokizuna bilaketa-koadroan</translation>
@@ -7322,6 +7329,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> makina birtualaren egoera</translation>
 <translation id="8139447493436036221">Google Drive-ko fitxategiak</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Eginbide gehiago konfiguratzeko, joan Phone Hub-en ezarpenetara</translation>
 <translation id="8141584439523427891">Beste arakatzaile batean irekitzen</translation>
 <translation id="8141725884565838206">Kudeatu pasahitzak</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{bideo bat}other{# bideo}}</translation>
@@ -7529,6 +7537,7 @@
 <translation id="833986336429795709">Esteka hau irekitzeko, aukeratu aplikazio bat</translation>
 <translation id="8342221978608739536">Ez naiz saiatu</translation>
 <translation id="8342861492835240085">Hautatu bilduma bat</translation>
+<translation id="8345848587667658367">Orain, telefonoko azken argazki, multimedia-eduki, jakinarazpen eta aplikazioak ikus ditzakezu</translation>
 <translation id="8347227221149377169">Inprimatze-lanak</translation>
 <translation id="834785183489258869">Ezkutuko moduan zaudenean, webguneek ezin dituzte erabili cookieak beste webguneetan egiten dituzun arakatze-jarduerak ikusteko, hala nola iragarkiak pertsonalizatzeko. Baliteke webgune batzuetako eginbideek ez funtzionatzea.</translation>
 <translation id="8350789879725387295">Arkatzaren tresnak oinarrian</translation>
@@ -8134,6 +8143,7 @@
 <translation id="8957757410289731985">Pertsonalizatu profila</translation>
 <translation id="895944840846194039">JavaScript memoria</translation>
 <translation id="8960208913905765425">Erantzun bizkorrak, unitate-bihurketa</translation>
+<translation id="8960638196855923532">Orain, telefonoko jakinarazpen eta aplikazioak ikus ditzakezu</translation>
 <translation id="8962051932294470566">Fitxategi bakarra parteka dezakezu aldiko. Saiatu berriro oraingo transferentzia osatu denean.</translation>
 <translation id="8962083179518285172">Ezkutatu xehetasunak</translation>
 <translation id="8962918469425892674">Mugimenduaren edo argiaren sentsoreak erabiltzen ari da webgune hau.</translation>
@@ -8285,6 +8295,7 @@
 <translation id="9103868373786083162">Sakatu itzultzeko, laster-menua historia ikusteko</translation>
 <translation id="9108035152087032312">Eman izena &amp;leihoari…</translation>
 <translation id="9108072915170399168">Oraingo datu-erabileraren ezarpena "Internetera konektatu gabe" da</translation>
+<translation id="9108294543511800041">Orain, telefonoko azken argazki, multimedia-eduki eta jakinarazpenak ikus ditzakezu</translation>
 <translation id="9108674852930645435">Arakatu <ph name="DEVICE_TYPE" /> gailuaren berritasunak</translation>
 <translation id="9108808586816295166">Baliteke DNS segurua beti erabilgarri ez egotea</translation>
 <translation id="9109122242323516435">Tokia egiteko, ezabatu gailuko memorian dauden fitxategiak.</translation>
@@ -8409,7 +8420,6 @@
 <translation id="934503638756687833">Hemen agertzen ez diren zenbait elementu ere kenduko dira, hala behar izanez gero. Lortu informazio gehiago &lt;a href="<ph name="URL" />"&gt;nahi ez den softwarearekiko babesari&lt;/a&gt; buruz Chrome-ren pribatutasunaren liburu zurian.</translation>
 <translation id="93480724622239549">Akatsa edo errorea</translation>
 <translation id="935854577147268200">Aldatu da Smart Lock telefonoa. Smart Lock eguneratzeko, idatzi pasahitza. Hurrengoan, telefonoak desblokeatuko du <ph name="DEVICE_TYPE" /> gailua. Smart Lock desaktibatzeko, joan ezarpenetara.</translation>
-<translation id="93610034168535821">Webguneek erabilitako memoria, guztira:</translation>
 <translation id="936646668635477464">Kamera eta mikrofonoa</translation>
 <translation id="936801553271523408">Sistemaren diagnostikoaren datuak</translation>
 <translation id="93766956588638423">Konpondu luzapena</translation>
diff --git a/chrome/app/resources/generated_resources_fa.xtb b/chrome/app/resources/generated_resources_fa.xtb
index 3dda714..27d3d68 100644
--- a/chrome/app/resources/generated_resources_fa.xtb
+++ b/chrome/app/resources/generated_resources_fa.xtb
@@ -8439,7 +8439,6 @@
 <translation id="934503638756687833">‏درصورت لزوم، موارد فهرست‌نشده نیز حذف خواهند شد. در گزارش جامع و دقیق حریم‌ خصوصی Chrome، درباره &lt;a href="<ph name="URL" />"&gt;حفاظت دربرابر نرم‌افزار ناخواسته&lt;/a&gt; اطلاعات بیشتری کسب کنید.</translation>
 <translation id="93480724622239549">اشکال یا خطا</translation>
 <translation id="935854577147268200">‏تلفن Smart Lock تغییر کرد. برای به‌روزرسانی Smart Lock، گذرواژه‌تان را وارد کنید. دفعه بعد، تلفنتان قفل <ph name="DEVICE_TYPE" /> را باز می‌کند. می‌توانید Smart Lock را در «تنظیمات» خاموش کنید.</translation>
-<translation id="93610034168535821">مجموع فضای ذخیره‌سازی که سایت‌ها استفاده کرده‌اند:</translation>
 <translation id="936646668635477464">دوربین و میکروفون</translation>
 <translation id="936801553271523408">داده‌های تشخیص خطای سیستم</translation>
 <translation id="93766956588638423">تعمیر افزونه</translation>
diff --git a/chrome/app/resources/generated_resources_fi.xtb b/chrome/app/resources/generated_resources_fi.xtb
index 6a27441c..ac89651 100644
--- a/chrome/app/resources/generated_resources_fi.xtb
+++ b/chrome/app/resources/generated_resources_fi.xtb
@@ -1557,6 +1557,7 @@
 <translation id="2433836460518180625">Avaa vain laitteen lukitus</translation>
 <translation id="2434449159125086437">Tulostimen määritys epäonnistui Tarkista määritykset ja yritä uudelleen.</translation>
 <translation id="2434758125294431199">Valitse, kuka voi jakaa sinulle</translation>
+<translation id="2434915728183570229">Voit nyt nähdä puhelimen sovellukset</translation>
 <translation id="2435137177546457207">Google Chromen ja ChromeOS Flexin lisäehdot</translation>
 <translation id="2435248616906486374">Verkkoyhteys katkaistu</translation>
 <translation id="2435457462613246316">Näytä salasana</translation>
@@ -4238,6 +4239,7 @@
 <translation id="5072900412896857127">Google Playn käyttöehtojen lataaminen ei onnistunut. Tarkista verkkoyhteys ja yritä uudelleen.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" /> ja # muuta}}</translation>
 <translation id="5074318175948309511">Tämä sivu on ehkä ladattava uudelleen, ennen kuin uudet asetukset tulevat voimaan.</translation>
+<translation id="5074761966806028321">Käyttöönoton viimeistely edellyttää lupaa</translation>
 <translation id="5075910247684008552">Suojaamaton sisältö estetään oletuksena suojatuilla sivustoilla</translation>
 <translation id="5078638979202084724">Lisää kaikki välilehdet kirjanmerkkeihin</translation>
 <translation id="5078796286268621944">Väärä PIN-koodi</translation>
@@ -4601,6 +4603,7 @@
 <translation id="5449551289610225147">Virheellinen salasana</translation>
 <translation id="5449588825071916739">Lisää kaikki välilehdet kirjanmerkkeihin</translation>
 <translation id="5449716055534515760">&amp;Sulje ikkuna</translation>
+<translation id="5452446625764825792">Voit nyt nähdä puhelimen viimeaikaiset kuvat, median ja sovellukset</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (toimii offline-tilassa)</translation>
 <translation id="5454166040603940656">palvelulla <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Katso lisää hakutuloksia</translation>
@@ -4661,6 +4664,7 @@
 <translation id="5499211612787418966">Valintaikkuna ei ole tällä hetkellä kohdistettuna. Kohdista valintaikkunaan painamalla Alt Vaihto A.</translation>
 <translation id="5499313591153584299">Tämä tiedosto voi olla haitallinen tietokoneellesi.</translation>
 <translation id="5499453227627332024">Linux-säiliöösi on saatavilla päivitys. Voit myös päivittää myöhemmin Asetukset-sovelluksesta.</translation>
+<translation id="5499476581866658341">Voit nyt nähdä puhelimen viimeaikaiset kuvat ja median</translation>
 <translation id="549957179819296104">Uusi kuvake</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />Hakuhistoriaa<ph name="END_LINK_SEARCH" /> ja <ph name="BEGIN_LINK_GOOGLE" />muita toimintoja<ph name="END_LINK_GOOGLE" /> voidaan tallentaa Google-tilillesi, kun olet kirjautuneena sisään. Voit poistaa niitä koska vain.</translation>
 <translation id="5500709606820808700">Turvatarkistus tehtiin tänään</translation>
@@ -6325,6 +6329,7 @@
 <translation id="7152478047064750137">Tämä laajennus ei vaadi erityisiä käyttöoikeuksia.</translation>
 <translation id="7154130902455071009">Vaihda aloitussivuksi <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Olemassa oleva kuva kamerasta tai tiedostosta</translation>
+<translation id="7160182524506337403">Voit nyt nähdä puhelimen ilmoitukset</translation>
 <translation id="7163202347044721291">Aktivointikoodia vahvistetaan…</translation>
 <translation id="716640248772308851"><ph name="EXTENSION" /> voi lukea kuva-, video- ja äänitiedostoja valituissa sijainneissa.</translation>
 <translation id="7167486101654761064">&amp;Avaa aina tämäntyyppiset tiedostot</translation>
@@ -7339,6 +7344,7 @@
 <translation id="8138997515734480534">Tila: <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">Google Drive -tiedostot</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Voit ottaa lisää ominaisuuksia käyttöön puhelinhubin asetuksissa</translation>
 <translation id="8141584439523427891">Avataan pian toisessa selaimessa</translation>
 <translation id="8141725884565838206">Hallinnoi salasanoja</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{video}other{# videota}}</translation>
@@ -7546,6 +7552,7 @@
 <translation id="833986336429795709">Valitse sovellus tämän linkin avaamista varten</translation>
 <translation id="8342221978608739536">En kokeillut</translation>
 <translation id="8342861492835240085">Valitse kokoelma</translation>
+<translation id="8345848587667658367">Voit nyt nähdä puhelimen viimeaikaiset kuvat, median, ilmoitukset ja sovellukset</translation>
 <translation id="8347227221149377169">Tulostustyöt</translation>
 <translation id="834785183489258869">Kun olet incognito-tilassa, sivustot eivät näe selaustoimintaasi eri sivustoilla evästeiden kautta esim. personoidakseen mainoksia. Joidenkin sivustojen ominaisuudet eivät välttämättä toimi.</translation>
 <translation id="8350789879725387295">Näyttökynätyökalut alapalkissa</translation>
@@ -8151,6 +8158,7 @@
 <translation id="8957757410289731985">Muokkaa profiilia</translation>
 <translation id="895944840846194039">JavaScriptin käyttämä muisti</translation>
 <translation id="8960208913905765425">Pikavastaukset: yksikkömuunnos</translation>
+<translation id="8960638196855923532">Voit nyt nähdä puhelimen ilmoitukset ja sovellukset</translation>
 <translation id="8962051932294470566">Voit jakaa vain yhden tiedoston kerrallaan. Yritä uudelleen, kun tämänhetkinen siirto on valmis.</translation>
 <translation id="8962083179518285172">Piilota tiedot</translation>
 <translation id="8962918469425892674">Tämä sivusto käyttää liikkeen- tai valontunnistimia.</translation>
@@ -8302,6 +8310,7 @@
 <translation id="9103868373786083162">Siirry taaksepäin painamalla tai avaa historia kontekstivalikon kautta.</translation>
 <translation id="9108035152087032312">Nimeä &amp;ikkuna…</translation>
 <translation id="9108072915170399168">Nykyinen datankäyttöasetus on Ilman internetyhteyttä</translation>
+<translation id="9108294543511800041">Voit nyt nähdä puhelimen viimeaikaiset kuvat, median ja ilmoitukset</translation>
 <translation id="9108674852930645435">Tutustu uusiin ominaisuuksiin: <ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">Suojattu DNS ei välttämättä ole koko ajan käytettävissä</translation>
 <translation id="9109122242323516435">Vapauta tilaa poistamalla laitteeseen tallennettuja tiedostoja.</translation>
@@ -8426,7 +8435,6 @@
 <translation id="934503638756687833">Myös tämän luettelon ulkopuolisia kohteita voidaan poistaa tarvittaessa. Lue lisää &lt;a href="<ph name="URL" />"&gt;ei-toivotuilta ohjelmilta suojautumisesta&lt;/a&gt; Chromen tietosuojailmoituksesta.</translation>
 <translation id="93480724622239549">Bugi tai virhe</translation>
 <translation id="935854577147268200">Smart Lock ‑puhelin on vaihtunut. Kirjoita salasana, jotta Smart Lock voidaan päivittää. Seuraavalla kerralla puhelimesi avaa laitteen <ph name="DEVICE_TYPE" /> lukituksen. Voit poistaa Smart Lockin käytöstä asetuksissa.</translation>
-<translation id="93610034168535821">Sivustojen yhteensä käyttämä tallennustila:</translation>
 <translation id="936646668635477464">Kamera ja mikrofoni</translation>
 <translation id="936801553271523408">Järjestelmän diagnostiikkatiedot</translation>
 <translation id="93766956588638423">Korjaa laajennus</translation>
diff --git a/chrome/app/resources/generated_resources_fil.xtb b/chrome/app/resources/generated_resources_fil.xtb
index 6c2d4bf..3ed450f7 100644
--- a/chrome/app/resources/generated_resources_fil.xtb
+++ b/chrome/app/resources/generated_resources_fil.xtb
@@ -2241,6 +2241,7 @@
 <translation id="3067198360141518313">Patakbuhin ang plugin na ito</translation>
 <translation id="3071624960923923138">Maaari kang mag-click dito upang magbukas ng bagong tab</translation>
 <translation id="3072775339180057696">Payagan ang site na tingnan ang <ph name="FILE_NAME" />?</translation>
+<translation id="3074499504015191586">Isalin ang Buong Page</translation>
 <translation id="3075874217500066906">Kailangang mag-restart upang masimulan ang proseso ng Powerwash. Pagkatapos mag-restart, hihilingin sa iyo na kumpirmahing gusto mong magpatuloy.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">I-save lang sa device na ito</translation>
@@ -5097,6 +5098,7 @@
 <translation id="5933522550144185133">Ginagamit ng <ph name="APP_NAME" /> ang iyong camera at mikropono</translation>
 <translation id="5935158534896975820">Inihahanda ang certificate signing request (hinihintay sa server)</translation>
 <translation id="5935656526031444304">Pamahalaan ang Ligtas na Pag-browse</translation>
+<translation id="5936065461722368675">Isalin ang buong page</translation>
 <translation id="5938002010494270685">May available na upgrade sa seguridad</translation>
 <translation id="5939518447894949180">I-reset</translation>
 <translation id="5939719276406088041">Hindi makagawa ng shortcut</translation>
@@ -8446,7 +8448,6 @@
 <translation id="934503638756687833">Aalisin din ang mga item na hindi nakalista rito kung kinakailangan. Matuto pa tungkol sa &lt;a href="<ph name="URL" />"&gt;proteksyon laban sa hindi gustong software&lt;/a&gt; sa puting papel ukol sa privacy ng Chrome.</translation>
 <translation id="93480724622239549">Bug o Error</translation>
 <translation id="935854577147268200">Pinalitan ang telepono ng Smart Lock. Ilagay ang iyong password para i-update ang Smart Lock. Sa susunod, ia-unlock ng iyong telepono ang <ph name="DEVICE_TYPE" /> mo. Puwede mong i-off ang Smart Lock sa Mga Setting</translation>
-<translation id="93610034168535821">Kabuuang storage na ginamit ng mga site:</translation>
 <translation id="936646668635477464">Camera at mikropono</translation>
 <translation id="936801553271523408">Diagnostic data ng system</translation>
 <translation id="93766956588638423">Ayusin ang extension</translation>
diff --git a/chrome/app/resources/generated_resources_fr-CA.xtb b/chrome/app/resources/generated_resources_fr-CA.xtb
index d2033d7f..49483afef 100644
--- a/chrome/app/resources/generated_resources_fr-CA.xtb
+++ b/chrome/app/resources/generated_resources_fr-CA.xtb
@@ -1910,6 +1910,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Retirer 1 application non prise en charge}one{Retirer # application non prise en charge}other{Retirer # applications non prises en charge}}</translation>
 <translation id="2776560192867872731">Modifier le nom de l'appareil pour <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Supprimer ce conteneur</translation>
+<translation id="2778471504622896352">Ajouter des applications distantes au lanceur ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Erreur lors de l'installation de l'application Linux</translation>
 <translation id="2783298271312924866">Téléchargé</translation>
@@ -3545,6 +3546,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> et <ph name="NUMBER_OF_OTHER_SWITCHES" /> autres commutateurs</translation>
 <translation id="439266289085815679">La configuration du Bluetooth est contrôlée par <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Modifier le fichier de configuration</translation>
+<translation id="4393713825278446281">Appareils avec Association rapide enregistrés dans <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Désactiver</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Tout ouvrir}=1{&amp;Ouvrir le favori}one{&amp;Tout ouvrir ({COUNT})}other{&amp;Tout ouvrir ({COUNT})}}</translation>
 <translation id="4397372003838952832">Vous n'aurez pas à mémoriser ce mot de passe. Il sera enregistré dans le <ph name="GOOGLE_PASSWORD_MANAGER" /> pour <ph name="EMAIL" />.</translation>
@@ -3774,6 +3776,7 @@
 <translation id="4615586811063744755">aucun témoin sélectionné</translation>
 <translation id="461661862154729886">Source d'alimentation</translation>
 <translation id="4617001782309103936">Trop court</translation>
+<translation id="4617019240346358451">Actualisez la page pour utiliser « <ph name="EXTENSION_NAME" /> »</translation>
 <translation id="4617270414136722281">Options de l'extension</translation>
 <translation id="4617880081511131945">Impossible d'établir la connexion</translation>
 <translation id="4619564267100705184">Confirmer que c'est bien vous</translation>
@@ -3989,6 +3992,7 @@
 <translation id="4833683849865011483">1 imprimante a été trouvée sur le serveur d'impression</translation>
 <translation id="4836504898754963407">Gérer les empreintes digitales</translation>
 <translation id="4837128290434901661">Rétablir la recherche Google?</translation>
+<translation id="4837165100461973682">Actualisez la page pour appliquer vos modifications</translation>
 <translation id="4837926214103741331">Vous n'êtes pas autorisé(e) à utiliser cet appareil. Pour obtenir l'autorisation de vous y connecter, veuillez communiquer avec son propriétaire.</translation>
 <translation id="4837952862063191349">Pour déverrouiller et restaurer vos données locales, veuillez entrer votre ancien mot de passe <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Affichez les photos, les fichiers multimédias et les notifications de votre téléphone</translation>
@@ -4298,6 +4302,7 @@
 <translation id="5150254825601720210">Nom du serveur SSL du certificat Netscape</translation>
 <translation id="5151354047782775295">Libérez de l'espace disque ou certaines données pourront être supprimées automatiquement</translation>
 <translation id="5153234146675181447">Oublier le téléphone</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Paramètres avancés pour <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Destinataire</translation>
 <translation id="5155327081870541046">Dans la barre d'adresse, entrez le raccourci pour le site que vous voulez rechercher comme « @favoris ». Ensuite, appuyez sur votre raccourci-clavier favori et entrez votre terme de recherche.</translation>
@@ -5935,6 +5940,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> a été ajoutée à distance</translation>
 <translation id="6790820461102226165">Ajouter un personne...</translation>
 <translation id="6793604637258913070">Mettre le point d'insertion de texte en surbrillance lorsqu'il s'affiche ou se déplace</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">La recherche automatique vous permet de vous déplacer automatiquement entre les éléments affichés à l'écran. Lorsqu'un élément est mis en évidence, appuyez sur le commutateur « Sélectionner » pour l'activer.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Une erreur s'est produite.</translation>
@@ -7807,6 +7813,7 @@
 <translation id="8642947597466641025">Augmenter la taille du texte</translation>
 <translation id="8643443571868262066">Le fichier <ph name="FILE_NAME" /> pourrait être dangereux. Voulez-vous l'envoyer à la protection avancée de Google afin de le faire analyser?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Aucun témoin}=1{1 témoin est bloqué}one{# témoin est bloqué}other{# témoins sont bloqués}}</translation>
+<translation id="864423554496711319">Appareils enregistrés dans votre compte</translation>
 <translation id="8644655801811752511">Impossible de réinitialiser cette clé de sécurité. Essayez de réinitialiser la clé immédiatement après l'avoir insérée.</translation>
 <translation id="8645354835496065562">Continuer à autoriser l'accès aux capteurs</translation>
 <translation id="8645920082661222035">Il prédit les événements dangereux et vous en informe avant qu'ils ne surviennent</translation>
@@ -8412,7 +8419,6 @@
 <translation id="934503638756687833">Les éléments qui ne sont pas affichés ici seront également supprimés si nécessaire. Pour en savoir plus sur la &lt;a href="<ph name="URL" />"&gt;protection contre les logiciels indésirables&lt;/a&gt;, consultez le livre blanc sur la confidentialité de Chrome.</translation>
 <translation id="93480724622239549">Bogue ou erreur</translation>
 <translation id="935854577147268200">Changement de téléphone Smart Lock. Entrez votre mot de passe pour mettre à jour Smart Lock. La prochaine fois, votre téléphone pourra déverrouiller votre <ph name="DEVICE_TYPE" />. Vous pouvez désactiver Smart Lock dans le menu Paramètres.</translation>
-<translation id="93610034168535821">Espace de stockage total utilisé par les sites :</translation>
 <translation id="936646668635477464">Caméra et microphone</translation>
 <translation id="936801553271523408">Données de diagnostic système</translation>
 <translation id="93766956588638423">Réparer l'extension</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb
index 61999c70..5446970 100644
--- a/chrome/app/resources/generated_resources_fr.xtb
+++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -1544,6 +1544,7 @@
 <translation id="2433836460518180625">Déverrouiller l'appareil uniquement</translation>
 <translation id="2434449159125086437">Échec de la configuration de l'imprimante. Veuillez vérifier la configuration, puis réessayer.</translation>
 <translation id="2434758125294431199">Sélectionnez qui peut partager des fichiers avec vous</translation>
+<translation id="2434915728183570229">Vous pouvez désormais afficher les applis de votre téléphone</translation>
 <translation id="2435137177546457207">Conditions d'utilisation supplémentaires de Google Chrome et Chrome OS Flex</translation>
 <translation id="2435248616906486374">Réseau déconnecté.</translation>
 <translation id="2435457462613246316">Afficher le mot de passe</translation>
@@ -1909,6 +1910,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Supprimer 1 appli non compatible}one{Supprimer # appli non compatible}other{Supprimer # applis non compatibles}}</translation>
 <translation id="2776560192867872731">Modifier le nom de l'appareil <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Supprimer ce conteneur</translation>
+<translation id="2778471504622896352">Ajouter des applications distantes au lanceur d'applications Chrome OS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Erreur pendant l'installation de l'application Linux</translation>
 <translation id="2783298271312924866">Téléchargé</translation>
@@ -3544,6 +3546,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> et <ph name="NUMBER_OF_OTHER_SWITCHES" /> autres touches</translation>
 <translation id="439266289085815679">La configuration Bluetooth est contrôlée par <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Modifier le fichier de configuration</translation>
+<translation id="4393713825278446281">Appareils avec Association express enregistrés dans <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Désactiver</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{Tout &amp;ouvrir}=1{&amp;Ouvrir le favori}one{Tout &amp;ouvrir ({COUNT})}other{Tout &amp;ouvrir ({COUNT})}}</translation>
 <translation id="4397372003838952832">Vous n'aurez pas besoin de mémoriser ce mot de passe. Il sera enregistré dans le <ph name="GOOGLE_PASSWORD_MANAGER" /> pour <ph name="EMAIL" />.</translation>
@@ -3773,6 +3776,7 @@
 <translation id="4615586811063744755">aucun cookie sélectionné</translation>
 <translation id="461661862154729886">Source d'énergie</translation>
 <translation id="4617001782309103936">Trop court</translation>
+<translation id="4617019240346358451">Actualisez la page pour utiliser <ph name="EXTENSION_NAME" /></translation>
 <translation id="4617270414136722281">Options d'extension</translation>
 <translation id="4617880081511131945">Impossible d'établir la connexion</translation>
 <translation id="4619564267100705184">Confirmer votre identité</translation>
@@ -3988,6 +3992,7 @@
 <translation id="4833683849865011483">1 imprimante trouvée sur le serveur d'impression</translation>
 <translation id="4836504898754963407">Gérer les empreintes digitales</translation>
 <translation id="4837128290434901661">Revenir à la recherche Google ?</translation>
+<translation id="4837165100461973682">Actualisez la page pour appliquer vos modifications</translation>
 <translation id="4837926214103741331">Vous n'êtes pas autorisé à utiliser cet appareil. Pour obtenir l'autorisation de vous y connecter, veuillez contacter son propriétaire.</translation>
 <translation id="4837952862063191349">Pour déverrouiller et restaurer vos données locales, veuillez saisir l'ancien mot de passe de votre <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Afficher les photos, contenus multimédias et notifications de votre téléphone</translation>
@@ -4223,6 +4228,7 @@
 <translation id="5072900412896857127">Impossible de charger les conditions d'utilisation de Google Play. Veuillez vérifier votre connexion réseau et réessayer.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}one{<ph name="FILE1" />, <ph name="FILE2" /> et # autre}other{<ph name="FILE1" />, <ph name="FILE2" /> et # autres}}</translation>
 <translation id="5074318175948309511">Vous devrez peut-être actualiser cette page pour que les nouveaux paramètres soient appliqués.</translation>
+<translation id="5074761966806028321">Une autorisation est encore nécessaire pour terminer l'installation</translation>
 <translation id="5075910247684008552">Le contenu non sécurisé est bloqué par défaut sur les sites sécurisés</translation>
 <translation id="5078638979202084724">Ajouter tous les onglets aux favoris</translation>
 <translation id="5078796286268621944">Code PIN incorrect</translation>
@@ -4297,6 +4303,7 @@
 <translation id="5150254825601720210">Nom du serveur SSL du certificat Netscape</translation>
 <translation id="5151354047782775295">Libérez de l'espace disque, car certaines informations risquent d'être supprimées automatiquement.</translation>
 <translation id="5153234146675181447">Oublier le téléphone</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Paramètres avancés pour <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Objet</translation>
 <translation id="5155327081870541046">Dans la barre d'adresse, saisissez le raccourci associé au site sur lequel vous voulez effectuer une recherche, par exemple "@favoris". Ensuite, utilisez le raccourci clavier de votre choix, puis saisissez votre terme de recherche.</translation>
@@ -4585,6 +4592,7 @@
 <translation id="5449551289610225147">Mot de passe incorrect</translation>
 <translation id="5449588825071916739">Ajouter tous les onglets aux favoris…</translation>
 <translation id="5449716055534515760">Fe&amp;rmer la fenêtre</translation>
+<translation id="5452446625764825792">Vous pouvez désormais afficher les photos, applis et contenus multimédias récents de votre téléphone</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (fonctionne hors connexion)</translation>
 <translation id="5454166040603940656">avec <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Afficher plus de résultats de recherche</translation>
@@ -4645,6 +4653,7 @@
 <translation id="5499211612787418966">Cette boîte de dialogue n'est actuellement pas sélectionnée. Appuyez sur Alt+Maj A pour sélectionner cette boîte de dialogue.</translation>
 <translation id="5499313591153584299">Ce fichier peut être néfaste pour votre ordinateur.</translation>
 <translation id="5499453227627332024">Une mise à niveau est disponible pour le conteneur Linux. Sachez que vous pouvez également effectuer cette mise à niveau plus tard depuis l'application "Paramètres".</translation>
+<translation id="5499476581866658341">Vous pouvez désormais afficher les photos et contenus multimédias récents de votre téléphone</translation>
 <translation id="549957179819296104">Nouvelle icône</translation>
 <translation id="5500168250243071806">L'<ph name="BEGIN_LINK_SEARCH" />historique des recherches<ph name="END_LINK_SEARCH" /> et d'<ph name="BEGIN_LINK_GOOGLE" />autres formes d'activité<ph name="END_LINK_GOOGLE" /> peuvent être enregistrés dans votre compte Google lorsque vous êtes connecté. Vous pouvez les supprimer à tout moment.</translation>
 <translation id="5500709606820808700">Contrôle de sécurité effectué aujourd'hui</translation>
@@ -5935,6 +5944,7 @@
 <translation id="6790497603648687708">Ajout de l'extension <ph name="EXTENSION_NAME" /> effectué à distance</translation>
 <translation id="6790820461102226165">Ajouter un profil utilisateur…</translation>
 <translation id="6793604637258913070">Mettre en surbrillance le curseur lorsqu'il apparaît ou se déplace dans le texte</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">L'exploration automatique permet de se déplacer automatiquement entre les éléments affichés. Quand un élément est en surbrillance, appuyez sur "Sélectionner" pour l'activer.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Une erreur s'est produite.</translation>
@@ -6311,6 +6321,7 @@
 <translation id="7152478047064750137">Cette extension ne nécessite aucune autorisation spéciale</translation>
 <translation id="7154130902455071009">Utiliser l'adresse <ph name="START_PAGE" /> comme page de démarrage ?</translation>
 <translation id="7155171745945906037">Photo existante au niveau de l'appareil photo ou dans les fichiers</translation>
+<translation id="7160182524506337403">Vous pouvez désormais afficher les notifications de votre téléphone</translation>
 <translation id="7163202347044721291">Vérification du code d'activation…</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" dispose d'un droit d'accès en lecture sur les images, les vidéos et les fichiers audio figurant dans les lieux contrôlés.</translation>
 <translation id="7167486101654761064">&amp;Toujours ouvrir les fichiers de ce type</translation>
@@ -7326,6 +7337,7 @@
 <translation id="8138997515734480534">État de <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">fichiers Google Drive</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Vous pouvez configurer d'autres fonctionnalités dans les paramètres de Phone Hub</translation>
 <translation id="8141584439523427891">Ouverture dans le navigateur secondaire…</translation>
 <translation id="8141725884565838206">Gérer les mots de passe</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{une vidéo}one{# vidéo}other{# vidéos}}</translation>
@@ -7533,6 +7545,7 @@
 <translation id="833986336429795709">Pour ouvrir ce lien, sélectionner une application</translation>
 <translation id="8342221978608739536">Je n'ai pas essayé.</translation>
 <translation id="8342861492835240085">Sélectionner une collection</translation>
+<translation id="8345848587667658367">Vous pouvez désormais afficher les photos, notifications, applis et contenus multimédias récents de votre téléphone</translation>
 <translation id="8347227221149377169">Tâches d'impression</translation>
 <translation id="834785183489258869">Lorsque vous êtes en navigation privée, les sites ne peuvent pas utiliser vos cookies pour voir votre activité de navigation sur différents sites (par exemple, pour personnaliser les annonces). Les fonctionnalités de certains sites peuvent ne pas fonctionner.</translation>
 <translation id="8350789879725387295">Outils de stylet dans le panneau d'ancrage</translation>
@@ -7808,6 +7821,7 @@
 <translation id="8642947597466641025">Augmente la taille du texte</translation>
 <translation id="8643443571868262066">Le fichier <ph name="FILE_NAME" /> est peut-être dangereux. Souhaitez-vous l'envoyer au service Protection Avancée de Google pour analyse ?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Aucun cookie}=1{1 cookie a été bloqué}one{# cookie a été bloqué}other{# cookies ont été bloqués}}</translation>
+<translation id="864423554496711319">Appareils enregistrés dans votre compte</translation>
 <translation id="8644655801811752511">Impossible de réinitialiser cette clé de sécurité. Essayez de la réinitialiser immédiatement après l’avoir insérée.</translation>
 <translation id="8645354835496065562">Continuer d'autoriser l'accès aux capteurs</translation>
 <translation id="8645920082661222035">Prédit les événements dangereux et vous en informe avant qu'ils ne surviennent</translation>
@@ -8138,6 +8152,7 @@
 <translation id="8957757410289731985">Personnaliser le profil</translation>
 <translation id="895944840846194039">Mémoire JavaScript</translation>
 <translation id="8960208913905765425">Conversion d'unité pour Réponses rapides</translation>
+<translation id="8960638196855923532">Vous pouvez désormais afficher les notifications et applis de votre téléphone</translation>
 <translation id="8962051932294470566">Vous ne pouvez partager qu'un seul fichier à la fois. Réessayez une fois le transfert en cours terminé.</translation>
 <translation id="8962083179518285172">Masquer les détails</translation>
 <translation id="8962918469425892674">Ce site utilise des capteurs de mouvement ou de lumière.</translation>
@@ -8289,6 +8304,7 @@
 <translation id="9103868373786083162">Appuyer pour revenir en arrière, menu contextuel pour afficher l'historique</translation>
 <translation id="9108035152087032312">Nommer la &amp;fenêtre</translation>
 <translation id="9108072915170399168">Le paramètre de consommation des données est actuellement défini sur "Sans Internet"</translation>
+<translation id="9108294543511800041">Vous pouvez désormais afficher les photos, notifications et contenus multimédias récents de votre téléphone</translation>
 <translation id="9108674852930645435">Découvrez les nouveautés sur votre <ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">Il est possible que le DNS sécurisé ne soit pas disponible à tout moment</translation>
 <translation id="9109122242323516435">Pour libérer de l'espace, supprimez des fichiers de l'espace de stockage de l'appareil.</translation>
@@ -8413,7 +8429,6 @@
 <translation id="934503638756687833">Au besoin, les éléments non indiqués ici seront également supprimés. Pour en savoir plus sur la &lt;a href="<ph name="URL" />"&gt;protection contre les logiciels malveillants&lt;/a&gt;, consultez le livre blanc sur les règles de confidentialité de Chrome.</translation>
 <translation id="93480724622239549">Bug ou erreur</translation>
 <translation id="935854577147268200">Le téléphone Smart Lock a changé. Saisissez votre mot de passe pour activer Smart Lock. La prochaine fois, votre téléphone déverrouillera votre <ph name="DEVICE_TYPE" />. Vous pouvez désactiver Smart Lock dans les paramètres.</translation>
-<translation id="93610034168535821">Espace de stockage total utilisé par les sites :</translation>
 <translation id="936646668635477464">Caméra et micro</translation>
 <translation id="936801553271523408">Données de diagnostic système</translation>
 <translation id="93766956588638423">Réparer l'extension</translation>
diff --git a/chrome/app/resources/generated_resources_gl.xtb b/chrome/app/resources/generated_resources_gl.xtb
index b525a0e..bd7bf3d5 100644
--- a/chrome/app/resources/generated_resources_gl.xtb
+++ b/chrome/app/resources/generated_resources_gl.xtb
@@ -1542,6 +1542,7 @@
 <translation id="2433836460518180625">Desbloquear só o dispositivo</translation>
 <translation id="2434449159125086437">Non se puido configurar a impresora. Comproba a configuración e téntao de novo.</translation>
 <translation id="2434758125294431199">Selecciona quen pode compartir contido contigo</translation>
+<translation id="2434915728183570229">Xa podes acceder ás aplicacións do teu teléfono</translation>
 <translation id="2435137177546457207">Condicións adicionais de Google Chrome e Chrome OS Flex</translation>
 <translation id="2435248616906486374">Rede desconectada</translation>
 <translation id="2435457462613246316">Mostrar contrasinal</translation>
@@ -1906,6 +1907,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Quitar 1 aplicación non compatible}other{Quitar # aplicacións non compatibles}}</translation>
 <translation id="2776560192867872731">Cambiar nome de dispositivo por <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Eliminar este contedor</translation>
+<translation id="2778471504622896352">Engadir aplicacións remotas ao menú de aplicacións de ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Produciuse un erro ao instalar a aplicación Linux</translation>
 <translation id="2783298271312924866">Descargado</translation>
@@ -3541,6 +3543,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> e <ph name="NUMBER_OF_OTHER_SWITCHES" /> interruptores máis</translation>
 <translation id="439266289085815679">A configuración de Bluetooth contrólaa <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Edita o ficheiro de configuración</translation>
+<translation id="4393713825278446281">Dispositivos compatibles coa función Vinculación rápida gardados en <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Desactivar</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Abrir todos}=1{&amp;Abrir marcador}other{&amp;Abrir todos ({COUNT})}}</translation>
 <translation id="4397372003838952832">Non terás que lembrar este contrasinal. Gardarase no <ph name="GOOGLE_PASSWORD_MANAGER" /> para <ph name="EMAIL" />.</translation>
@@ -3770,6 +3773,7 @@
 <translation id="4615586811063744755">Non se seleccionou ningunha cookie</translation>
 <translation id="461661862154729886">Fonte de alimentación</translation>
 <translation id="4617001782309103936">PIN demasiado curto</translation>
+<translation id="4617019240346358451">Para usar "<ph name="EXTENSION_NAME" />", volve cargar a páxina</translation>
 <translation id="4617270414136722281">Opcións de extensión</translation>
 <translation id="4617880081511131945">Non se puido establecer conexión</translation>
 <translation id="4619564267100705184">Verificar a túa identidade</translation>
@@ -3985,6 +3989,7 @@
 <translation id="4833683849865011483">Atopouse 1 impresora no servidor de impresión</translation>
 <translation id="4836504898754963407">Xestionar impresións dixitais</translation>
 <translation id="4837128290434901661">Queres volver cambiar á Busca de Google?</translation>
+<translation id="4837165100461973682">Para aplicar os cambios, volve cargar a páxina</translation>
 <translation id="4837926214103741331">Non estás autorizado a usar este dispositivo. Para obter permiso para iniciar sesión, ponte en contacto co propietario do dispositivo.</translation>
 <translation id="4837952862063191349">Para desbloquear e restaurar os teus datos locais, introduce o teu contrasinal de <ph name="DEVICE_TYPE" /> antigo.</translation>
 <translation id="4838170306476614339">Accede ás fotos, ao contido multimedia e ás notificacións do teu teléfono</translation>
@@ -4220,6 +4225,7 @@
 <translation id="5072900412896857127">Non se puideron cargar as Condicións de servizo de Google Play. Comproba a conexión de rede e téntao de novo.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" /> e <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" /> e # máis}}</translation>
 <translation id="5074318175948309511">É posible que precises volver cargar esta páxina para que a configuración nova se faga efectiva.</translation>
+<translation id="5074761966806028321">Aínda se necesita un permiso para completar a configuración</translation>
 <translation id="5075910247684008552">O contido que non é seguro bloquéase de forma predeterminada en sitios seguros</translation>
 <translation id="5078638979202084724">Establecer todas as pestanas como marcadores</translation>
 <translation id="5078796286268621944">PIN incorrecto</translation>
@@ -4294,6 +4300,7 @@
 <translation id="5150254825601720210">Nome do servidor SSL de certificados Netscape</translation>
 <translation id="5151354047782775295">Libera espazo en disco para que non se eliminen automaticamente datos seleccionados</translation>
 <translation id="5153234146675181447">Esquecer o teléfono</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Configuración avanzada para <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Entidade</translation>
 <translation id="5155327081870541046">Na barra de enderezos, escribe o atallo do sitio no que queres realizar buscas (por exemplo: "@marcadores"). Despois preme o atallo de teclado que prefiras e escribe o termo de busca.</translation>
@@ -4582,6 +4589,7 @@
 <translation id="5449551289610225147">Contrasinal non válido</translation>
 <translation id="5449588825071916739">Engadir todas as pestanas aos marcadores</translation>
 <translation id="5449716055534515760">Pechar &amp;ventá</translation>
+<translation id="5452446625764825792">Xa podes acceder ás aplicacións, ao contido multimedia e ás fotos recentes do teu teléfono</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (funciona sen conexión)</translation>
 <translation id="5454166040603940656">con <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Ver máis resultados da busca</translation>
@@ -4642,6 +4650,7 @@
 <translation id="5499211612787418966">Este cadro de diálogo non está enfocado nestes momentos. Para enfocalo, preme Alt + Maiúsculas + A.</translation>
 <translation id="5499313591153584299">É posible que este ficheiro sexa daniño para o teu ordenador.</translation>
 <translation id="5499453227627332024">Hai dispoñible unha actualización para o teu contedor de Linux. Tamén podes instalar a actualización máis adiante desde a aplicación Configuración.</translation>
+<translation id="5499476581866658341">Xa podes acceder ao contido multimedia e ás fotos recentes do teu teléfono</translation>
 <translation id="549957179819296104">Icona nova</translation>
 <translation id="5500168250243071806">Cando teñas a sesión iniciada, é posible que se garden na túa Conta de Google o <ph name="BEGIN_LINK_SEARCH" />historial de busca<ph name="END_LINK_SEARCH" /> e <ph name="BEGIN_LINK_GOOGLE" />outros datos da túa actividade<ph name="END_LINK_GOOGLE" />. Podes eliminalos en calquera momento.</translation>
 <translation id="5500709606820808700">A comprobación de seguranza executouse hoxe</translation>
@@ -5926,6 +5935,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> engadiuse de forma remota</translation>
 <translation id="6790820461102226165">Engadir persoa...</translation>
 <translation id="6793604637258913070">Destacar o cursor de texto cando apareza ou se mova</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">A exploración automática permíteche desprazarte polos elementos da pantalla automaticamente. Cando se destaque un elemento que queiras activar, preme Seleccionar.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Produciuse un erro.</translation>
@@ -6302,6 +6312,7 @@
 <translation id="7152478047064750137">Esta extensión non necesita permisos especiais</translation>
 <translation id="7154130902455071009">Cambiar a páxina de inicio a: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Foto existente da cámara ou do ficheiro</translation>
+<translation id="7160182524506337403">Xa podes acceder ás notificacións do teu teléfono</translation>
 <translation id="7163202347044721291">Verificando código de activación…</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" pode ler ficheiros de imaxes, vídeo e son nas localizacións marcadas.</translation>
 <translation id="7167486101654761064">&amp;Abrir sempre ficheiros deste tipo</translation>
@@ -7315,6 +7326,7 @@
 <translation id="8138997515734480534">Estado de <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">Ficheiros de Google Drive</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" /> e <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Podes configurar máis opcións na configuración da función O meu teléfono</translation>
 <translation id="8141584439523427891">Abrindo nun navegador alternativo</translation>
 <translation id="8141725884565838206">Xestionar os teus contrasinais</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{1 vídeo}other{# vídeos}}</translation>
@@ -7522,6 +7534,7 @@
 <translation id="833986336429795709">Para abrir esta ligazón, escoller unha aplicación</translation>
 <translation id="8342221978608739536">Non se intentou</translation>
 <translation id="8342861492835240085">Seleccionar unha colección</translation>
+<translation id="8345848587667658367">Xa podes acceder ás aplicacións, ás notificacións, ao contido multimedia e ás fotos recentes do teu teléfono</translation>
 <translation id="8347227221149377169">Traballos de impresión</translation>
 <translation id="834785183489258869">Co modo de incógnito activado, os sitios web non poden utilizar cookies para ver a túa actividade de navegación en distintos sitios (por exemplo, para personalizar os anuncios). As funcións dalgúns sitios poden deixar de funcionar.</translation>
 <translation id="8350789879725387295">Ferramentas do lapis óptico na base</translation>
@@ -7797,6 +7810,7 @@
 <translation id="8642947597466641025">Aumentar o tamaño do texto</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> pode ser perigoso. Queres envialo á Protección avanzada de Google para analizalo?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Non se utiliza ningunha cookie}=1{Bloqueouse 1 cookie}other{Bloqueáronse # cookies}}</translation>
+<translation id="864423554496711319">Dispositivos gardados na túa conta</translation>
 <translation id="8644655801811752511">Non se puido restablecer esta chave de seguranza. Proba a restablecela inmediatamente tras introducila.</translation>
 <translation id="8645354835496065562">Continuar permitindo o acceso aos sensores</translation>
 <translation id="8645920082661222035">Predí eventos perigosos antes de que se produzan e móstrache unha advertencia</translation>
@@ -8126,6 +8140,7 @@
 <translation id="8957757410289731985">Personalizar perfil</translation>
 <translation id="895944840846194039">Memoria JavaScript</translation>
 <translation id="8960208913905765425">Conversión de unidades de Respostas rápidas</translation>
+<translation id="8960638196855923532">Xa podes acceder ás notificacións e ás aplicacións do teu teléfono</translation>
 <translation id="8962051932294470566">Só podes compartir os ficheiros un por un. Téntao de novo cando finalice a transferencia en curso.</translation>
 <translation id="8962083179518285172">Ocultar detalles</translation>
 <translation id="8962918469425892674">Este sitio usa sensores de movemento ou de luz.</translation>
@@ -8277,6 +8292,7 @@
 <translation id="9103868373786083162">Preme para retroceder e acceder ao menú contextual para ver o historial</translation>
 <translation id="9108035152087032312">Nome da &amp;ventá...</translation>
 <translation id="9108072915170399168">A configuración de uso de datos actual é Sen Internet</translation>
+<translation id="9108294543511800041">Xa podes acceder ás notificacións, ao contido multimedia e ás fotos recentes do teu teléfono</translation>
 <translation id="9108674852930645435">Descubre as novidades do dispositivo (<ph name="DEVICE_TYPE" />)</translation>
 <translation id="9108808586816295166">O DNS seguro pode non estar dispoñible continuamente</translation>
 <translation id="9109122242323516435">Para liberar espazo, elimina ficheiros do almacenamento do dispositivo.</translation>
@@ -8401,7 +8417,6 @@
 <translation id="934503638756687833">Se é necesario, tamén se quitarán elementos que non se indican aquí. Consulta máis información acerca da &lt;a href="<ph name="URL" />"&gt;protección contra software non desexado&lt;/a&gt; no libro branco de privacidade de Chrome.</translation>
 <translation id="93480724622239549">Erro</translation>
 <translation id="935854577147268200">Modificouse o teléfono que ten activada a función Smart Lock. Introduce o teu contrasinal para actualizar a función. A próxima vez, o teléfono desbloqueará o dispositivo <ph name="DEVICE_TYPE" />. Podes desactivar Smart Lock en Configuración</translation>
-<translation id="93610034168535821">Almacenamento total usado polos sitios:</translation>
 <translation id="936646668635477464">Cámara e micrófono</translation>
 <translation id="936801553271523408">Datos de diagnóstico do sistema</translation>
 <translation id="93766956588638423">Reparar extensión</translation>
diff --git a/chrome/app/resources/generated_resources_gu.xtb b/chrome/app/resources/generated_resources_gu.xtb
index 57d53d2..d5936e4 100644
--- a/chrome/app/resources/generated_resources_gu.xtb
+++ b/chrome/app/resources/generated_resources_gu.xtb
@@ -1541,6 +1541,7 @@
 <translation id="2433836460518180625">માત્ર ઉપકરણને અનલૉક કરો</translation>
 <translation id="2434449159125086437">પ્રિન્ટર સેટ કરી શકાતું નથી. કૃપા કરીને ગોઠવણી ચેક કરો અને ફરી પ્રયાસ કરો.</translation>
 <translation id="2434758125294431199">કોણ તમારી સાથે શેર કરી શકે, તે પસંદ કરો</translation>
+<translation id="2434915728183570229">હવે તમે તમારા ફોનની ઍપ જોઈ શકો છો</translation>
 <translation id="2435137177546457207">Google Chrome અને ChromeOS Flexની વધારાની શરતો</translation>
 <translation id="2435248616906486374">નેટવર્ક ડિસ્કનેક્ટ થયું</translation>
 <translation id="2435457462613246316">પાસવર્ડ બતાવો</translation>
@@ -2222,6 +2223,7 @@
 <translation id="3067198360141518313">આ પ્લગિન ચલાવો</translation>
 <translation id="3071624960923923138">એક નવું ટૅબ ખોલવા માટે તમે અહીં ક્લિક કરી શકો છો</translation>
 <translation id="3072775339180057696">સાઇટને <ph name="FILE_NAME" /> જોવાની મંજૂરી આપીએ?</translation>
+<translation id="3074499504015191586">આખા પેજનો અનુવાદ કરો</translation>
 <translation id="3075874217500066906">Powerwash પ્રક્રિયા શરૂ કરવા માટે પુનઃપ્રારંભ જરૂરી છે. પુનઃપ્રારંભ પછી તમે આગળ વધવા માંગો છો કે કેમ તે તમને પૂછવામાં આવશે.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">માત્ર આ ડિવાઇસ પર સાચવો</translation>
@@ -4224,6 +4226,7 @@
 <translation id="5072900412896857127">Google Playની સેવાની શરતો લોડ કરી શકાઈ નથી. કૃપા કરીને તમારું નેટવર્ક કનેક્શન ચેક કરો અને ફરી પ્રયાસ કરો.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}one{<ph name="FILE1" />, <ph name="FILE2" /> અને વધુ #}other{<ph name="FILE1" />, <ph name="FILE2" /> અને વધુ #}}</translation>
 <translation id="5074318175948309511">નવા સેટિંગ પ્રભાવમાં આવે તે પહેલાં આ પેજને ફરીથી લોડ કરવાની જરૂર પડી શકે છે.</translation>
+<translation id="5074761966806028321">સેટઅપ પૂર્ણ કરવા માટે હજી પણ પરવાનગી જરૂરી છે</translation>
 <translation id="5075910247684008552">સુરક્ષિત સાઇટ પર અસુરક્ષિત કન્ટેન્ટને બ્લૉક કરેલું હોય છે</translation>
 <translation id="5078638979202084724">બધા ટૅબ્સ બુકમાર્ક કરો</translation>
 <translation id="5078796286268621944">ખોટો PIN</translation>
@@ -4587,6 +4590,7 @@
 <translation id="5449551289610225147">અમાન્ય પાસવર્ડ</translation>
 <translation id="5449588825071916739">તમામ ટૅબ્સ બુકમાર્ક કરો</translation>
 <translation id="5449716055534515760">Close Win&amp;dow</translation>
+<translation id="5452446625764825792">હવે તમે તમારા ફોનના તાજેતરના ફોટા, મીડિયા અને ઍપ જોઈ શકો છો</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (ઑફલાઇન કાર્ય કરે છે)</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" /> સાથે</translation>
 <translation id="545484289444831485">વધુ શોધ પરિણામો જુઓ</translation>
@@ -4647,6 +4651,7 @@
 <translation id="5499211612787418966">હાલમાં આ સંવાદ ફોકસમાં નથી. આ સંવાદને ફોકસમાં લાવવા માટે Alt-Shift A દબાવો.</translation>
 <translation id="5499313591153584299">આ ફાઇલ તમારા કમ્પ્યુટર માટે હાનિકારક હોઇ શકે છે.</translation>
 <translation id="5499453227627332024">તમારા Linux Container માટે કોઈ અપગ્રેડ ઉપલબ્ધ છે. તમે થોડા સમય પછી સેટિંગ ઍપમાંથી પણ અપગ્રેડ કરી શકશો.</translation>
+<translation id="5499476581866658341">હવે તમે તમારા ફોનના તાજેતરના ફોટા અને મીડિયા જોઈ શકો છો</translation>
 <translation id="549957179819296104">નવું આઇકન</translation>
 <translation id="5500168250243071806">જ્યારે તમે સાઇન ઇન કર્યુ હોય, ત્યારે તમારા Google એકાઉન્ટમાં <ph name="BEGIN_LINK_SEARCH" />શોધ ઇતિહાસ<ph name="END_LINK_SEARCH" /> અને <ph name="BEGIN_LINK_GOOGLE" />પ્રવૃત્તિના અન્ય પ્રકારો<ph name="END_LINK_GOOGLE" /> સાચવવામાં આવી શકે છે. તમે તેમને કોઈપણ સમયે ડિલીટ કરી શકો છો.</translation>
 <translation id="5500709606820808700">સલામતી માટે તપાસ આજે કરવામાં આવી</translation>
@@ -5076,6 +5081,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> દ્વારા તમારા કૅમેરા અને માઇક્રોફોનનો ઉપયોગ કરવામાં આવી રહ્યો છે</translation>
 <translation id="5935158534896975820">પ્રમાણપત્ર પર સહી કરવાની વિનંતી તૈયાર કરી રહ્યાં છીએ (સર્વર પર રાહ જુએ છે)</translation>
 <translation id="5935656526031444304">Safe Browsingને મેનેજ કરો</translation>
+<translation id="5936065461722368675">આખા પેજનો અનુવાદ કરો</translation>
 <translation id="5938002010494270685">સુરક્ષા અપગ્રેડ ઉપલબ્ધ</translation>
 <translation id="5939518447894949180">રીસેટ કરો</translation>
 <translation id="5939719276406088041">શૉર્ટકટ બનાવી શકતા નથી</translation>
@@ -6315,6 +6321,7 @@
 <translation id="7152478047064750137">આ એક્સટેન્શનને કોઈ વિશિષ્ટ પરવાનગીઓની જરૂર નથી</translation>
 <translation id="7154130902455071009">તમારા શરૂઆતના પેજને આનાથી બદલો: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">કૅમેરા અથવા ફાઇલમાંથી અસ્તિત્વમાંનો ફોટો</translation>
+<translation id="7160182524506337403">હવે તમે તમારા ફોનના નોટિફિકેશન જોઈ શકો છો</translation>
 <translation id="7163202347044721291">સક્રિયકરણનો કોડ ચકાસી રહ્યાં છીએ...</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" આ તપાસાયેલા સ્થાનોમાં ફોટા, વીડિયો અને સાઉન્ડ ફાઇલોને વાંચી શકે છે.</translation>
 <translation id="7167486101654761064">આ પ્રકારની ફાઇલો &amp;હંમેશાં ખોલો</translation>
@@ -7324,6 +7331,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> સ્ટેટસ</translation>
 <translation id="8139447493436036221">Google Drive ફાઇલો</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">ફોન હબના સેટિંગમાં તમે વધુ સુવિધાઓનું સેટઅપ કરી શકો છો</translation>
 <translation id="8141584439523427891">હવે વૈકલ્પિક બ્રાઉઝરમાં ખોલી રહ્યાં છીએ</translation>
 <translation id="8141725884565838206">તમારા પાસવર્ડ્સનું સંચાલન કરો</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{એક વીડિયો}one{# વીડિયો}other{# વીડિયો}}</translation>
@@ -7531,6 +7539,7 @@
 <translation id="833986336429795709">આ લિંક ખોલવા માટે, એક ઍપ પસંદ કરો</translation>
 <translation id="8342221978608739536">પ્રયાસ કર્યો ન હતો</translation>
 <translation id="8342861492835240085">સંગ્રહ પસંદ કરો</translation>
+<translation id="8345848587667658367">હવે તમે તમારા ફોનના તાજેતરના ફોટા, મીડિયા, નોટિફિકેશન અને ઍપ જોઈ શકો છો</translation>
 <translation id="8347227221149377169">પ્રિન્ટ કરવાના કામો</translation>
 <translation id="834785183489258869">જ્યારે છૂપા મોડમાં હો, ત્યારે અલગ-અલગ સાઇટ પરની તમારી બ્રાઉઝિંગ પ્રવૃત્તિ જોવા માટે સાઇટ તમારી કુકીનો ઉપયોગ કરી શકશે નહીં, ઉદાહરણ તરીકે, જાહેરાતોને વ્યક્તિગત બનાવવા માટે. અમુક સુવિધાઓ કેટલીક સાઇટ પર કામ કરી શકશે નહીં.</translation>
 <translation id="8350789879725387295">ડૉકમાં સ્ટાયલસના સાધનો બતાવો</translation>
@@ -8137,6 +8146,7 @@
 <translation id="8957757410289731985">પ્રોફાઇલ કસ્ટમાઇઝ કરો</translation>
 <translation id="895944840846194039">JavaScript મેમરી</translation>
 <translation id="8960208913905765425">ઝડપી જવાબોનું એકમ રૂપાંતરણ</translation>
+<translation id="8960638196855923532">હવે તમે તમારા ફોનના નોટિફિકેશન અને ઍપ જોઈ શકો છો</translation>
 <translation id="8962051932294470566">તમે એક સમયે ફક્ત એક જ ફાઇલ શેર કરી શકો છો. વર્તમાન ટ્રાન્સફર પૂર્ણ થાય પછી ફરીથી પ્રયાસ કરો.</translation>
 <translation id="8962083179518285172">વિગતો છુપાવો</translation>
 <translation id="8962918469425892674">આ સાઇટ મોશન અથવા લાઇટ સેન્સરનો ઉપયોગ કરી રહી છે.</translation>
@@ -8288,6 +8298,7 @@
 <translation id="9103868373786083162">પાછા જવા માટે દબાવો, ઇતિહાસ જોવા માટે સંદર્ભ મેનૂ પર જાઓ</translation>
 <translation id="9108035152087032312">નામ અને વિંડો…</translation>
 <translation id="9108072915170399168">ડેટા વપરાશના હાલના સેટિંગ ઇન્ટરનેટ વિના માટે સેટ છે</translation>
+<translation id="9108294543511800041">હવે તમે તમારા ફોનના તાજેતરના ફોટા, મીડિયા અને નોટિફિકેશન જોઈ શકો છો</translation>
 <translation id="9108674852930645435">તમારા <ph name="DEVICE_TYPE" /> પર નવું શું છે તે જુઓ</translation>
 <translation id="9108808586816295166">સુરક્ષિત DNS હંમેશાં ઉપલબ્ધ ન હોઈ શકે</translation>
 <translation id="9109122242323516435">સ્પેસ ખાલી કરવા માટે, ડિવાઇસ સ્ટોરેજમાંથી ફાઇલો ડિલીટ કરો.</translation>
@@ -8412,7 +8423,6 @@
 <translation id="934503638756687833">જો જરૂર જણાય તો, જે આઇટમ અહીંની સૂચિમાં નથી તે પણ કાઢી નાખવામાં આવશે. Chrome ગોપનીયતા વ્હાઇટ પેપરમાં &lt;a href="<ph name="URL" />"&gt;ન જોઈતા સૉફ્ટવેર સામે રક્ષણ મેળવવા&lt;/a&gt; વિશે વધુ જાણો.</translation>
 <translation id="93480724622239549">ખામી અથવા ભૂલ</translation>
 <translation id="935854577147268200">Smart Lock ફોન બદલાયો. Smart Lock અપડેટ કરવા માટે તમારો પાસવર્ડ દાખલ કરો. આગલી વખતે, તમારો ફોન તમારા <ph name="DEVICE_TYPE" />ને અનલૉક કરશે. તમે સેટિંગમાં Smart Lock બંધ કરી શકો છો</translation>
-<translation id="93610034168535821">સાઇટ દ્વારા ઉપયોગમાં લેવાયેલો કુલ સ્ટોરેજ:</translation>
 <translation id="936646668635477464">કૅમેરા અને માઇક્રોફોન</translation>
 <translation id="936801553271523408">સિસ્ટમ ડાયગ્નોસ્ટિક ડેટા</translation>
 <translation id="93766956588638423">એક્સ્ટેન્શન સુધારો</translation>
diff --git a/chrome/app/resources/generated_resources_hi.xtb b/chrome/app/resources/generated_resources_hi.xtb
index 29e9a08b..f895943 100644
--- a/chrome/app/resources/generated_resources_hi.xtb
+++ b/chrome/app/resources/generated_resources_hi.xtb
@@ -2240,6 +2240,7 @@
 <translation id="3067198360141518313">यह प्लग इन चलाएं</translation>
 <translation id="3071624960923923138">नया टैब खोलने के लिए, आप यहां क्लिक कर सकते हैं</translation>
 <translation id="3072775339180057696">क्या आप साइट को <ph name="FILE_NAME" /> देखने देना चाहते हैं?</translation>
+<translation id="3074499504015191586">पूरे पेज का अनुवाद करें</translation>
 <translation id="3075874217500066906">पावरवॉश प्रक्रिया शुरू करने के लिए फिर से प्रारंभ करने की आवश्‍यकता है. फिर से प्रारंभ करने के बाद आपसे इस बात की पुष्‍टि करने के लिए पूछा जाएगा कि क्या आप आगे बढ़ना चाहते हैं.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">सिर्फ़ इस डिवाइस में सेव करें</translation>
@@ -5095,6 +5096,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> आपके कैमरे और माइक्रोफ़ोन का इस्तेमाल कर रहा है</translation>
 <translation id="5935158534896975820">प्रमाणपत्र के लिए अनुरोध किया जा रहा है (सर्वर का इंतज़ार है)</translation>
 <translation id="5935656526031444304">सुरक्षित ब्राउज़िंग प्रबंधित करें</translation>
+<translation id="5936065461722368675">पूरे पेज का अनुवाद करें</translation>
 <translation id="5938002010494270685">सुरक्षा बेहतर बनाने की सुविधा मौजूद है</translation>
 <translation id="5939518447894949180">रीसेट करें</translation>
 <translation id="5939719276406088041">शॉर्टकट नहीं बनाए जा सकते</translation>
@@ -8441,7 +8443,6 @@
 <translation id="934503638756687833">ऐसे आइटम जिनके नाम यहां शामिल नहीं हैं, ज़रूरत पड़ने पर उन्हें भी हटाया जा सकता है. Chrome निजता श्वेत पत्र में &lt;a href="<ph name="URL" />"&gt;अनचाहे सॉफ़्टवेयर से सुरक्षा&lt;/a&gt; के बारे में ज़्यादा जानें.</translation>
 <translation id="93480724622239549">बग या गड़बड़ी</translation>
 <translation id="935854577147268200">Smart Lock वाला फ़ोन बदल गया है. Smart Lock अपडेट करने के लिए अपना पासवर्ड डालें. अगली बार, आपका फ़ोन आपके <ph name="DEVICE_TYPE" /> को अनलॉक कर देगा. आप सेटिंग में जाकर Smart Lock को बंद कर सकते हैं</translation>
-<translation id="93610034168535821">साइटों की इस्तेमाल की गई कुल मेमोरी:</translation>
 <translation id="936646668635477464">कैमरा और माइक्रोफ़ोन</translation>
 <translation id="936801553271523408">सिस्टम का गड़बड़ी संबंधी डेटा</translation>
 <translation id="93766956588638423">एक्‍सटेंशन को ठीक करें</translation>
diff --git a/chrome/app/resources/generated_resources_hr.xtb b/chrome/app/resources/generated_resources_hr.xtb
index 616fd1a..6944476 100644
--- a/chrome/app/resources/generated_resources_hr.xtb
+++ b/chrome/app/resources/generated_resources_hr.xtb
@@ -1546,6 +1546,7 @@
 <translation id="2433836460518180625">Otključaj samo uređaj</translation>
 <translation id="2434449159125086437">Postavljanje pisača nije moguće. Provjerite konfiguraciju i pokušajte ponovo.</translation>
 <translation id="2434758125294431199">Odaberite tko može dijeliti s vama</translation>
+<translation id="2434915728183570229">Sada možete pregledati aplikacije telefona</translation>
 <translation id="2435137177546457207">Dodatni uvjeti za Google Chrome i ChromeOS Flex</translation>
 <translation id="2435248616906486374">Mreža je isključena</translation>
 <translation id="2435457462613246316">Pokaži zaporku</translation>
@@ -4230,6 +4231,7 @@
 <translation id="5072900412896857127">Učitavanje uvjeta pružanja usluge za Google Play nije uspjelo. Provjerite mrežnu vezu i pokušajte ponovo.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}one{<ph name="FILE1" />, <ph name="FILE2" /> i još #}few{<ph name="FILE1" />, <ph name="FILE2" /> i još #}other{<ph name="FILE1" />, <ph name="FILE2" /> i još #}}</translation>
 <translation id="5074318175948309511">Ovu stranicu možda će biti potrebno ponovo učitati kako bi nove postavke stupile na snagu.</translation>
+<translation id="5074761966806028321">Da biste dovršili postavljanje i dalje je potrebno dopuštenje</translation>
 <translation id="5075910247684008552">Sigurne web-lokacije prema zadanim postavkama blokiraju nesiguran sadržaj</translation>
 <translation id="5078638979202084724">Označi sve kartice</translation>
 <translation id="5078796286268621944">Netočan PIN</translation>
@@ -4593,6 +4595,7 @@
 <translation id="5449551289610225147">Nevažeća zaporka</translation>
 <translation id="5449588825071916739">Označi sve kartice</translation>
 <translation id="5449716055534515760">Close Win&amp;dow (Zatvori prozor)</translation>
+<translation id="5452446625764825792">Sada možete pregledati nedavne fotografije, medije i aplikacije telefona</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (funkcionira izvanmrežno)</translation>
 <translation id="5454166040603940656">uz <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Pogledajte više rezultata pretraživanja</translation>
@@ -4653,6 +4656,7 @@
 <translation id="5499211612787418966">Ovaj dijalog trenutačno nije fokusiran. Pritisnite Alt – Shift A da biste fokusirali ovaj dijalog.</translation>
 <translation id="5499313591153584299">Ta datoteka može biti štetna za vaše računalo.</translation>
 <translation id="5499453227627332024">Dostupna je nadogradnja za vaš Linuxov spremnik. Možete nadograditi i kasnije putem aplikacije Postavke.</translation>
+<translation id="5499476581866658341">Sada možete pregledati nedavne fotografije i medije telefona</translation>
 <translation id="549957179819296104">Nova ikona</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />Povijest pretraživanja<ph name="END_LINK_SEARCH" /> i <ph name="BEGIN_LINK_GOOGLE" />drugi oblici aktivnosti<ph name="END_LINK_GOOGLE" /> mogu se spremati na vaš Google račun kad ste prijavljeni. Uvijek ih možete izbrisati.</translation>
 <translation id="5500709606820808700">Sigurnosna provjera izvršena je danas</translation>
@@ -6319,6 +6323,7 @@
 <translation id="7152478047064750137">To proširenje ne zahtijeva nikakva posebna dopuštenja</translation>
 <translation id="7154130902455071009">promijeniti vašu početnu stranicu u: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Postojeća fotografija s fotoaparata ili iz datoteke</translation>
+<translation id="7160182524506337403">Sada možete pregledati obavijesti telefona</translation>
 <translation id="7163202347044721291">Potvrđivanje aktivacijskog koda...</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" može čitati slikovne, video i audiodatoteke na označenim lokacijama.</translation>
 <translation id="7167486101654761064">&amp;Uvijek otvori ovu vrstu datoteka</translation>
@@ -7333,6 +7338,7 @@
 <translation id="8138997515734480534">Status VM-a <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">Datoteke Google diska</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Više značajki možete postaviti u postavkama Phone huba</translation>
 <translation id="8141584439523427891">Otvaranje u zamjenskom pregledniku</translation>
 <translation id="8141725884565838206">Upravljanje zaporkama</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{videozapis}one{# videozapis}few{# videozapisa}other{# videozapisa}}</translation>
@@ -7540,6 +7546,7 @@
 <translation id="833986336429795709">Da biste otvorili tu vezu, odaberite aplikaciju</translation>
 <translation id="8342221978608739536">Nisam pokušao/pokušala</translation>
 <translation id="8342861492835240085">Odaberite zbirku</translation>
+<translation id="8345848587667658367">Sada možete pregledati nedavne fotografije, medije, obavijesti i aplikacije telefona</translation>
 <translation id="8347227221149377169">Zadaci ispisa</translation>
 <translation id="834785183489258869">Dok ste u anonimnom načinu, web-lokacije ne mogu upotrebljavati vaše kolačiće za uvid u vašu aktivnost pregledavanja na različitim web-lokacijama, primjerice radi prilagođavanja oglasa. Značajke na nekim web-lokacijama možda neće funkcionirati.</translation>
 <translation id="8350789879725387295">Alati pisaljke na traci</translation>
@@ -8147,6 +8154,7 @@
 <translation id="8957757410289731985">Prilagodite profil</translation>
 <translation id="895944840846194039">Memorija JavaScripta</translation>
 <translation id="8960208913905765425">Pretvorba jedinica za brze odgovore</translation>
+<translation id="8960638196855923532">Sada možete pregledati obavijesti i aplikacije telefona</translation>
 <translation id="8962051932294470566">Možete dijeliti samo po jednu datoteku. Pokušajte ponovno nakon dovršetka trenutačnog prijenosa.</translation>
 <translation id="8962083179518285172">Sakrij pojedinosti</translation>
 <translation id="8962918469425892674">Ova web-lokacija upotrebljava senzore pokreta ili svjetla.</translation>
@@ -8298,6 +8306,7 @@
 <translation id="9103868373786083162">Pritisnite za povratak, kontekstni izbornik za prikaz povijesti</translation>
 <translation id="9108035152087032312">Dodijeli &amp;prozoru naziv...</translation>
 <translation id="9108072915170399168">Za potrošnju podatkovnog prometa trenutačno je odabrana postavka Bez interneta</translation>
+<translation id="9108294543511800041">Sada možete pregledati nedavne fotografije, medije i obavijesti telefona</translation>
 <translation id="9108674852930645435">Istražite što je novo na uređaju <ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">Sigurni DNS možda neće biti dostupan cijelo vrijeme</translation>
 <translation id="9109122242323516435">Da biste oslobodili prostor, izbrišite datoteke iz pohrane uređaja.</translation>
@@ -8422,7 +8431,6 @@
 <translation id="934503638756687833">Stavke koje nisu ovdje navedene također će se po potrebi ukloniti. Više o &lt;a href="<ph name="URL" />"&gt;zaštiti od neželjenog softvera&lt;/a&gt; potražite u Chromeovoj bijeloj knjizi o privatnosti.</translation>
 <translation id="93480724622239549">Programska ili neka druga pogreška</translation>
 <translation id="935854577147268200">Promijenjen je telefon Smart Locka. Unesite zaporku da biste ažurirali Smart Lock. Sljedeći će put vaš telefon otključati vaš uređaj <ph name="DEVICE_TYPE" />. Smart Lock možete isključiti u Postavkama.</translation>
-<translation id="93610034168535821">Ukupna pohrana koju upotrebljavaju web-lokacije:</translation>
 <translation id="936646668635477464">Fotoaparat i mikrofon</translation>
 <translation id="936801553271523408">Podaci o dijagnozi sustava</translation>
 <translation id="93766956588638423">Popravi proširenje</translation>
diff --git a/chrome/app/resources/generated_resources_hu.xtb b/chrome/app/resources/generated_resources_hu.xtb
index 614a808..e390d8b 100644
--- a/chrome/app/resources/generated_resources_hu.xtb
+++ b/chrome/app/resources/generated_resources_hu.xtb
@@ -3890,7 +3890,7 @@
 <translation id="4701025263201366865">Szülői bejelentkezés</translation>
 <translation id="4701335814944566468">Tegnap tekintette meg</translation>
 <translation id="4707337002099455863">Mindig, minden webhelyen</translation>
-<translation id="4708794300267213770">Lezárási képernyő megjelenítése, az alvó módból történő felébresztéskor</translation>
+<translation id="4708794300267213770">Lezárási képernyő megjelenítése az alvó módból történő felébresztéskor</translation>
 <translation id="4708849949179781599">Kilépés a <ph name="PRODUCT_NAME" />-ból</translation>
 <translation id="4711638718396952945">A beállítások visszaállítása</translation>
 <translation id="47158868804223727">Kattintson a csoport nevére a kibontásához vagy összecsukásához</translation>
@@ -8438,7 +8438,6 @@
 <translation id="934503638756687833">A listán nem szereplő elemeket szükség szerint el is lehet távolítani. A &lt;a href="<ph name="URL" />"&gt;nem kívánt szoftverek elleni védelemről&lt;/a&gt; a Chrome adatvédelemmel foglalkozó útmutatójában talál további információt.</translation>
 <translation id="93480724622239549">Programhiba vagy hiba</translation>
 <translation id="935854577147268200">A Smart Lock funkcióval használt telefon megváltozott. Adja meg jelszavát a Smart Lock frissítéséhez. Legközelebb a telefonjával oldhatja fel <ph name="DEVICE_TYPE" /> eszköze lezárását. A Smart Lock funkciót a Beállításokban kapcsolhatja ki.</translation>
-<translation id="93610034168535821">Webhelyek által használt teljes tárhely:</translation>
 <translation id="936646668635477464">Kamera és mikrofon</translation>
 <translation id="936801553271523408">Rendszerdiagnosztikai adatok</translation>
 <translation id="93766956588638423">Bővítmény javítása</translation>
diff --git a/chrome/app/resources/generated_resources_hy.xtb b/chrome/app/resources/generated_resources_hy.xtb
index 9907432..f740006 100644
--- a/chrome/app/resources/generated_resources_hy.xtb
+++ b/chrome/app/resources/generated_resources_hy.xtb
@@ -1545,6 +1545,7 @@
 <translation id="2433836460518180625">Միայն ապակողպել սարքը</translation>
 <translation id="2434449159125086437">Չհաջողվեց կարգավորել տպիչը: Ստուգեք կարգավորումները և նորից փորձեք:</translation>
 <translation id="2434758125294431199">Նշեք, թե ով կարող է կիսվել ձեզ հետ ֆայլերով</translation>
+<translation id="2434915728183570229">Այժմ դուք կարող եք դիտել ձեր հեռախոսի հավելվածները</translation>
 <translation id="2435137177546457207">Google Chrome-ի և ChromeOS Flex-ի լրացուցիչ պայմաններ</translation>
 <translation id="2435248616906486374">Ցանցն անջատված է</translation>
 <translation id="2435457462613246316">Ցույց տալ գաղտնաբառը</translation>
@@ -4226,6 +4227,7 @@
 <translation id="5072900412896857127">Չհաջողվեց բեռնել Google Play-ի օգտագործման պայմանները։ Ստուգեք կապը և նորից փորձեք։</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}one{<ph name="FILE1" />, <ph name="FILE2" /> ու ևս # ֆայլ}other{<ph name="FILE1" />, <ph name="FILE2" /> ու ևս # ֆայլ}}</translation>
 <translation id="5074318175948309511">Որպեսզի նոր կարգավորումներն ուժի մեջ մտնեն, այս էջը հարկավոր է կրկին բեռնել:</translation>
+<translation id="5074761966806028321">Կարգավորումն ավարտելու համար դեռ թույլտվություն է պահանջվում</translation>
 <translation id="5075910247684008552">Պաշտպանված կայքերում վտանգավոր բովանդակությունն արգելափակվում է ըստ կանխադրման:</translation>
 <translation id="5078638979202084724">Էջանշել բոլոր ներդիրները</translation>
 <translation id="5078796286268621944">Սխալ PIN կոդ</translation>
@@ -4591,6 +4593,7 @@
 <translation id="5449551289610225147">Սխալ գաղտնաբառ</translation>
 <translation id="5449588825071916739">Բոլոր ներդիրների էջանշում</translation>
 <translation id="5449716055534515760">Փակել պա&amp;տուհանը</translation>
+<translation id="5452446625764825792">Այժմ դուք կարող եք դիտել ձեր հեռախոսի վերջին լուսանկարները, մեդիաֆայլերն ու հավելվածները</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (աշխատում է անցանց ռեժիմում)</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" />-ի հետ</translation>
 <translation id="545484289444831485">Դիտել որոնման այլ արդյունքներ</translation>
@@ -4651,6 +4654,7 @@
 <translation id="5499211612787418966">Երկխոսության այս պատուհանը ֆոկուսում չէ։ Սեղմեք Alt + Shift + A՝ ուղղելու համար։</translation>
 <translation id="5499313591153584299">Այս ֆայլը կարող է վնասաբեր լինել ձեր համակարգչի համար:</translation>
 <translation id="5499453227627332024">Լինուքսի կոնտեյների համար հասանելի է նոր տարբերակ։ Դուք նաև կարող եք նորացնել կոնտեյներն ավելի ուշ Կարգավորումներում։</translation>
+<translation id="5499476581866658341">Այժմ դուք կարող եք դիտել ձեր հեռախոսի վերջին լուսանկարներն ու մեդիաֆայլերը</translation>
 <translation id="549957179819296104">Նոր պատկերակ</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />Որոնումների պատմությունը<ph name="END_LINK_SEARCH" /> և <ph name="BEGIN_LINK_GOOGLE" />այլ գործողություններ<ph name="END_LINK_GOOGLE" /> կարող են պահվել ձեր Google հաշվում, երբ դուք մուտք եք գործում։ Դրանք ցանկացած ժամանակ հնարավոր է ջնջել։</translation>
 <translation id="5500709606820808700">Անվտանգության ստուգումն այսօր է արվել</translation>
@@ -6314,6 +6318,7 @@
 <translation id="7152478047064750137">Այս ընդլայնումը հատուկ թույլտվություն չի պահանջում</translation>
 <translation id="7154130902455071009">Դարձնել <ph name="START_PAGE" />-ը սկզբնական էջը</translation>
 <translation id="7155171745945906037">Առկա լուսանկար խցիկից կամ ֆայլից</translation>
+<translation id="7160182524506337403">Այժմ դուք կարող եք դիտել ձեր հեռախոսի ծանուցումները</translation>
 <translation id="7163202347044721291">Ակտիվացման կոդը ստուգվում է…</translation>
 <translation id="716640248772308851">«<ph name="EXTENSION" />» ընդլայնումը կարող է նշված պանակներում կարդալ պատկերները, տեսանյութերը և ձայնային ֆայլերը:</translation>
 <translation id="7167486101654761064">&amp;Միշտ բացել այս տեսակի ֆայլերը</translation>
@@ -7326,6 +7331,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> վիրտուալ մեքենայի կարգավիճակը</translation>
 <translation id="8139447493436036221">Google Drive-ի ֆայլեր</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Հեռախոսի կառավարման կենտրոնի կարգավորումներում կարող եք ավելի շատ գործառույթներ կարգավորել</translation>
 <translation id="8141584439523427891">Բացվում է այլ դիտարկիչում</translation>
 <translation id="8141725884565838206">Գաղտնաբառերի կառավարում</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{տեսանյութ}one{# տեսանյութ}other{# տեսանյութ}}</translation>
@@ -7533,6 +7539,7 @@
 <translation id="833986336429795709">Հղումը բացելու համար ընտրեք հավելված</translation>
 <translation id="8342221978608739536">Չեմ փորձել</translation>
 <translation id="8342861492835240085">Ընտրել հավաքածու</translation>
+<translation id="8345848587667658367">Այժմ դուք կարող եք դիտել ձեր հեռախոսի վերջին լուսանկարները, մեդիաֆայլերը, ծանուցումներն ու հավելվածները</translation>
 <translation id="8347227221149377169">Տպելու առաջադրանքներ</translation>
 <translation id="834785183489258869">Ինկոգնիտո ռեժիմում կայքերը չեն կարող օգտագործել քուքիներ՝ դիտարկիչում ձեր գործողությունները տեսնելու համար, օրինակ, գովազդի անհատականացման նպատակով։ Որոշ կայքերում գործառույթները կարող են չաշխատել։</translation>
 <translation id="8350789879725387295">Ստիլուսի գործիքներ դոկ-կայանում</translation>
@@ -8139,6 +8146,7 @@
 <translation id="8957757410289731985">Կարգավորել պրոֆիլը</translation>
 <translation id="895944840846194039">JavaScript հիշողություն</translation>
 <translation id="8960208913905765425">Արագ պատասխաններ․ չափման միավորների փոխարկում</translation>
+<translation id="8960638196855923532">Այժմ դուք կարող եք դիտել ձեր հեռախոսի ծանուցումներն ու հավելվածները</translation>
 <translation id="8962051932294470566">Դուք միաժամանակ կարող եք կիսվել միայն մեկ ֆայլով։ Նորից փորձեք, երբ ընթացիկ փոխանցումն ավարտվի։</translation>
 <translation id="8962083179518285172">Թաքցնել մանրամասները</translation>
 <translation id="8962918469425892674">Այս կայքն օգտագործում է շարժման և լուսավորության տվիչներ:</translation>
@@ -8290,6 +8298,7 @@
 <translation id="9103868373786083162">Սեղմեք՝ հետ գնալու համար, բացեք տեղային ընտրացանկը՝ պատմությունը տեսնելու համար</translation>
 <translation id="9108035152087032312">Անվանել պատուհանը…</translation>
 <translation id="9108072915170399168">Տվյալների փոխանցման ընթացիկ կարգավորումը՝ «Առանց ինտերնետի»</translation>
+<translation id="9108294543511800041">Այժմ դուք կարող եք դիտել ձեր հեռախոսի վերջին լուսանկարները, մեդիաֆայլերն ու ծանուցումները</translation>
 <translation id="9108674852930645435">Իմացեք, թե ինչ նոր բան կա ձեր <ph name="DEVICE_TYPE" /> սարքում</translation>
 <translation id="9108808586816295166">Ապահով DNS-ը կարող է ամբողջ ընթացքում հասանելի չլինել</translation>
 <translation id="9109122242323516435">Տարածք ազատելու համար սարքի հիշողությունից ֆայլեր ջնջեք:</translation>
@@ -8414,7 +8423,6 @@
 <translation id="934503638756687833">Այստեղ չնշված տարրերը նույնպես կարող են հեռացվել։ Անցանկալի ծրագրերից պաշտպանվելու մասին մանրամասն կարդացեք &lt;a href="<ph name="URL" />"&gt;այստեղ&lt;/a&gt;:</translation>
 <translation id="93480724622239549">Վրիպակ կամ սխալ</translation>
 <translation id="935854577147268200">Ապակողպման համար օգտագործվող հեռախոսը փոխվել է։ Մուտքագրեք ձեր գաղտնաբառը՝ Smart Lock-ը թարմացնելու համար։ Դրանից հետո ձեր հեռախոսով կարող եք ապակողպել <ph name="DEVICE_TYPE" /> սարքը։ Smart Lock-ը կարող եք անջատել կարգավորումներում։</translation>
-<translation id="93610034168535821">Կայքերի կողմից օգտագործվող ընդհանուր տարածքը՝</translation>
 <translation id="936646668635477464">Տեսախցիկ և խոսափող</translation>
 <translation id="936801553271523408">Համակարգի դիագնոստիկ տվյալներ</translation>
 <translation id="93766956588638423">Ընդլայնման վերանորոգում</translation>
diff --git a/chrome/app/resources/generated_resources_id.xtb b/chrome/app/resources/generated_resources_id.xtb
index 30cb73b..ea5d2419 100644
--- a/chrome/app/resources/generated_resources_id.xtb
+++ b/chrome/app/resources/generated_resources_id.xtb
@@ -1558,6 +1558,7 @@
 <translation id="2433836460518180625">Hanya buka kunci perangkat</translation>
 <translation id="2434449159125086437">Tidak dapat menyiapkan printer. Harap periksa konfigurasi dan coba lagi.</translation>
 <translation id="2434758125294431199">Pilih siapa yang dapat berbagi dengan Anda</translation>
+<translation id="2434915728183570229">Anda kini dapat melihat aplikasi ponsel Anda</translation>
 <translation id="2435137177546457207">Persyaratan Tambahan Google Chrome dan ChromeOS Flex</translation>
 <translation id="2435248616906486374">Jaringan terputus</translation>
 <translation id="2435457462613246316">Tampilkan sandi</translation>
@@ -4242,6 +4243,7 @@
 <translation id="5072900412896857127">Persyaratan Layanan Google Play tidak dapat dimuat. Harap periksa koneksi jaringan Anda, lalu coba lagi.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" />, dan # lainnya}}</translation>
 <translation id="5074318175948309511">Halaman ini mungkin perlu dimuat ulang sebelum setelan baru berpengaruh.</translation>
+<translation id="5074761966806028321">Izin masih diperlukan untuk menyelesaikan penyiapan</translation>
 <translation id="5075910247684008552">Konten yang tidak aman akan diblokir secara default di situs aman</translation>
 <translation id="5078638979202084724">Bookmark semua tab</translation>
 <translation id="5078796286268621944">PIN salah</translation>
@@ -4605,6 +4607,7 @@
 <translation id="5449551289610225147">Sandi tidak valid</translation>
 <translation id="5449588825071916739">Bookmark Semua Tab</translation>
 <translation id="5449716055534515760">Tutup Jen&amp;dela</translation>
+<translation id="5452446625764825792">Anda kini dapat melihat foto, media, dan aplikasi terbaru ponsel Anda</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (berfungsi secara offline)</translation>
 <translation id="5454166040603940656">dengan <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Lihat hasil penelusuran lainnya</translation>
@@ -4665,6 +4668,7 @@
 <translation id="5499211612787418966">Dialog ini sedang tidak difokuskan. Tekan Alt-Shift A untuk memfokuskan dialog ini.</translation>
 <translation id="5499313591153584299">File ini mungkin berbahaya untuk komputer Anda.</translation>
 <translation id="5499453227627332024">Upgrade tersedia untuk Container Linux Anda. Anda juga dapat mengupgrade nanti di aplikasi Setelan.</translation>
+<translation id="5499476581866658341">Anda kini dapat melihat foto dan media terbaru ponsel Anda</translation>
 <translation id="549957179819296104">Ikon baru</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />Histori penelusuran<ph name="END_LINK_SEARCH" /> dan <ph name="BEGIN_LINK_GOOGLE" />bentuk aktivitas lainnya<ph name="END_LINK_GOOGLE" /> dapat disimpan di Akun Google Anda saat login. Anda dapat menghapusnya kapan saja.</translation>
 <translation id="5500709606820808700">Pemeriksaan keamanan berjalan hari ini</translation>
@@ -6329,6 +6333,7 @@
 <translation id="7152478047064750137">Ekstensi ini tidak memerlukan izin khusus</translation>
 <translation id="7154130902455071009">Ubah halaman awal Anda menjadi: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Foto yang sudah ada dari kamera atau file</translation>
+<translation id="7160182524506337403">Anda kini dapat melihat notifikasi ponsel Anda</translation>
 <translation id="7163202347044721291">Memverifikasi kode aktivasi ...</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" dapat membaca file gambar, video, dan suara di lokasi yang dicentang.</translation>
 <translation id="7167486101654761064">Sel&amp;alu buka file jenis ini</translation>
@@ -7344,6 +7349,7 @@
 <translation id="8138997515734480534">Status <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">File Google Drive</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Anda dapat menyiapkan fitur lainnya di setelan Phone Hub</translation>
 <translation id="8141584439523427891">Membuka di browser alternatif sekarang</translation>
 <translation id="8141725884565838206">Kelola sandi Anda</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{1 video}other{# video}}</translation>
@@ -7551,6 +7557,7 @@
 <translation id="833986336429795709">Untuk membuka link ini, pilih aplikasi</translation>
 <translation id="8342221978608739536">Tidak mencoba</translation>
 <translation id="8342861492835240085">Pilih koleksi</translation>
+<translation id="8345848587667658367">Anda kini dapat melihat foto, media, notifikasi, dan aplikasi terbaru ponsel Anda</translation>
 <translation id="8347227221149377169">Pekerjaan cetak</translation>
 <translation id="834785183489258869">Selama dalam mode Samaran, situs tidak dapat menggunakan cookie untuk melihat aktivitas penjelajahan Anda di berbagai situs, misalnya untuk mempersonalisasi iklan. Fitur tertentu di beberapa situs mungkin tidak berfungsi.</translation>
 <translation id="8350789879725387295">Alat stilus di dok</translation>
@@ -8156,6 +8163,7 @@
 <translation id="8957757410289731985">Sesuaikan profil</translation>
 <translation id="895944840846194039">Memori JavaScript</translation>
 <translation id="8960208913905765425">Konversi unit Jawaban Instan</translation>
+<translation id="8960638196855923532">Anda kini dapat melihat notifikasi dan aplikasi ponsel Anda</translation>
 <translation id="8962051932294470566">Anda hanya dapat membagikan satu file dalam satu waktu. Coba lagi setelah transfer saat ini selesai.</translation>
 <translation id="8962083179518285172">Sembunyikan Detail</translation>
 <translation id="8962918469425892674">Situs ini menggunakan sensor gerakan atau sensor cahaya.</translation>
@@ -8307,6 +8315,7 @@
 <translation id="9103868373786083162">Tekan untuk kembali ke menu konteks guna melihat histori</translation>
 <translation id="9108035152087032312">Namai Jendela ...</translation>
 <translation id="9108072915170399168">Setelan penggunaan data saat ini adalah Tanpa internet</translation>
+<translation id="9108294543511800041">Anda kini dapat melihat foto, media, dan notifikasi terbaru ponsel Anda</translation>
 <translation id="9108674852930645435">Lihat yang baru di <ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">DNS aman mungkin tidak tersedia sepanjang waktu</translation>
 <translation id="9109122242323516435">Untuk mengosongkan ruang, hapus file dari penyimpanan perangkat.</translation>
@@ -8431,7 +8440,6 @@
 <translation id="934503638756687833">Item yang tidak tercantum di sini juga akan dihapus, jika perlu. Pelajari lebih lanjut tentang &lt;a href="<ph name="URL" />"&gt;perlindungan terhadap software yang tidak diinginkan&lt;/a&gt; di panduan layanan privasi Chrome.</translation>
 <translation id="93480724622239549">Bug atau Error</translation>
 <translation id="935854577147268200">Ponsel Smart Lock diubah. Masukkan sandi Anda untuk memperbarui Smart Lock. Saat digunakan lagi, ponsel Anda akan membuka kunci <ph name="DEVICE_TYPE" /> ini. Anda dapat menonaktifkan Smart Lock di Setelan</translation>
-<translation id="93610034168535821">Total penyimpanan yang digunakan oleh situs:</translation>
 <translation id="936646668635477464">Kamera &amp; mikrofon</translation>
 <translation id="936801553271523408">Data diagnosis sistem</translation>
 <translation id="93766956588638423">Perbaiki ekstensi</translation>
diff --git a/chrome/app/resources/generated_resources_is.xtb b/chrome/app/resources/generated_resources_is.xtb
index 5fd6d65f..0c35e3e9 100644
--- a/chrome/app/resources/generated_resources_is.xtb
+++ b/chrome/app/resources/generated_resources_is.xtb
@@ -8442,7 +8442,6 @@
 <translation id="934503638756687833">Atriði sem eru ekki talin upp hér verða einnig fjarlægð ef þörf krefur. Frekari upplýsingar um &lt;a href="<ph name="URL" />"&gt;vernd gegn óæskilegum hugbúnaði&lt;/a&gt; má finna í skýrslu um persónuvernd í Chrome.</translation>
 <translation id="93480724622239549">Villa</translation>
 <translation id="935854577147268200">Smart Lock síma var breytt. Færðu inn aðgangsorðið þitt til að uppfæra Smart Lock. Næst tekur síminn þinn <ph name="DEVICE_TYPE" /> úr lás. Þú getur slökkt á Smart Lock í stillingunum</translation>
-<translation id="93610034168535821">Heildargeymslurými sem vefsvæði nota:</translation>
 <translation id="936646668635477464">Myndavél og hljóðnemi</translation>
 <translation id="936801553271523408">Greiningargögn kerfis</translation>
 <translation id="93766956588638423">Gera við viðbót</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb
index 2beedda..148804f 100644
--- a/chrome/app/resources/generated_resources_it.xtb
+++ b/chrome/app/resources/generated_resources_it.xtb
@@ -8423,7 +8423,6 @@
 <translation id="934503638756687833">Se necessario verranno rimossi anche elementi non elencati qui. Leggi ulteriori informazioni sulla &lt;a href="<ph name="URL" />"&gt;protezione da software indesiderato&lt;/a&gt; nel whitepaper sulla privacy di Chrome.</translation>
 <translation id="93480724622239549">Bug o errore</translation>
 <translation id="935854577147268200">Telefono con Smart Lock cambiato. Inserisci la password per aggiornare Smart Lock. La prossima volta potrai usare il tuo telefono per sbloccare il dispositivo <ph name="DEVICE_TYPE" />. Puoi disattivare Smart Lock nelle Impostazioni</translation>
-<translation id="93610034168535821">Spazio di archiviazione totale usato dai siti:</translation>
 <translation id="936646668635477464">Videocamera e microfono</translation>
 <translation id="936801553271523408">Dati diagnostica di sistema</translation>
 <translation id="93766956588638423">Ripara estensione</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb
index 52891c3..94ccbf6 100644
--- a/chrome/app/resources/generated_resources_iw.xtb
+++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -1557,6 +1557,7 @@
 <translation id="2433836460518180625">ביטול הנעילה של המכשיר בלבד</translation>
 <translation id="2434449159125086437">לא ניתן להגדיר את המדפסת. יש לבדוק את התצורה ולנסות שוב.</translation>
 <translation id="2434758125294431199">אנשי קשר לבחירתך שיוכלו לשתף איתך</translation>
+<translation id="2434915728183570229">עכשיו יש לך אפשרות לראות את האפליקציות שבטלפון</translation>
 <translation id="2435137177546457207">‏תנאים נוספים של Google Chrome ו-ChromeOS Flex</translation>
 <translation id="2435248616906486374">הרשת מנותקת</translation>
 <translation id="2435457462613246316">הצגת סיסמה</translation>
@@ -4242,6 +4243,7 @@
 <translation id="5072900412896857127">‏לא ניתן לטעון את התנאים וההגבלות של Google Play. יש לבדוק את החיבור לרשת ולנסות שוב.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />,‏ <ph name="FILE2" />}many{<ph name="FILE1" />,‏ <ph name="FILE2" /> ועוד #}other{<ph name="FILE1" />,‏ <ph name="FILE2" /> ועוד #}}</translation>
 <translation id="5074318175948309511">ייתכן שיהיה צורך לטעון מחדש דף זה על מנת שההגדרות החדשות ייכנסו לתוקף.</translation>
+<translation id="5074761966806028321">עדיין נדרשת הרשאה כדי להשלים את ההגדרה</translation>
 <translation id="5075910247684008552">תוכן לא מאובטח נחסם כברירת מחדל באתרים מאובטחים</translation>
 <translation id="5078638979202084724">יצירת סימנייה לכל הכרטיסיות</translation>
 <translation id="5078796286268621944">‏PIN שגוי</translation>
@@ -4605,6 +4607,7 @@
 <translation id="5449551289610225147">סיסמה לא חוקית</translation>
 <translation id="5449588825071916739">הוספת סימנייה לכל הכרטיסיות</translation>
 <translation id="5449716055534515760">סגירת ח&amp;לון</translation>
+<translation id="5452446625764825792">עכשיו יש לך אפשרות לראות את התמונות, המדיה והאפליקציות האחרונות שבטלפון</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (פועלת אופליין)</translation>
 <translation id="5454166040603940656">עם <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">הצגת תוצאות חיפוש נוספות</translation>
@@ -4665,6 +4668,7 @@
 <translation id="5499211612787418966">‏אין התמקדות בתיבת הדו-שיח הזו. כדי להתמקד בתיבת הדו-שיח הזו, צריך להקיש על Alt +‏ Shift A.</translation>
 <translation id="5499313591153584299">קובץ זה עלול להסב נזק למחשב שלך.</translation>
 <translation id="5499453227627332024">‏יש שדרוג זמין עבור קונטיינר Linux שלך. אפשר לשדרג גם במועד מאוחר יותר דרך אפליקציית ההגדרות.</translation>
+<translation id="5499476581866658341">עכשיו יש לך אפשרות לראות את המדיה והתמונות האחרונות שבטלפון</translation>
 <translation id="549957179819296104">הסמל החדש</translation>
 <translation id="5500168250243071806">‏<ph name="BEGIN_LINK_SEARCH" />היסטוריית החיפושים<ph name="END_LINK_SEARCH" /> ו<ph name="BEGIN_LINK_GOOGLE" />סוגי פעילות אחרים<ph name="END_LINK_GOOGLE" /> יכולים להישמר בחשבון Google אחרי שנכנסים. אפשר למחוק אותם בכל שלב.</translation>
 <translation id="5500709606820808700">בדיקת הבטיחות פעלה היום</translation>
@@ -6333,6 +6337,7 @@
 <translation id="7152478047064750137">אין צורך בהרשאות מיוחדות כדי להשתמש בתוסף זה</translation>
 <translation id="7154130902455071009">שינוי דף הפתיחה ל: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">תמונה קיימת ממצלמה או מקובץ</translation>
+<translation id="7160182524506337403">עכשיו יש לך אפשרות לראות את ההתראות שבטלפון</translation>
 <translation id="7163202347044721291">מתבצע אימות של קוד הפעלה...</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" יכול לקרוא קובצי תמונות, וידאו ואודיו במיקומים המסומנים.</translation>
 <translation id="7167486101654761064">&amp;פתיחה תמיד של קבצים מסוג זה</translation>
@@ -7349,6 +7354,7 @@
 <translation id="8138997515734480534">הסטטוס של <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">‏קבצים ב-Google Drive</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">‏אפשר להגדיר תכונות נוספות בהגדרות Phone Hub</translation>
 <translation id="8141584439523427891">נפתח עכשיו בדפדפן חלופי</translation>
 <translation id="8141725884565838206">ניהול הסיסמאות שלך</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{סרטון}two{# סרטונים}many{# סרטונים}other{# סרטונים}}</translation>
@@ -7556,6 +7562,7 @@
 <translation id="833986336429795709">צריך לבחור אפליקציה כדי לפתוח את הקישור הזה</translation>
 <translation id="8342221978608739536">לא ניסיתי</translation>
 <translation id="8342861492835240085">בחירת אוסף</translation>
+<translation id="8345848587667658367">עכשיו יש לך אפשרות לראות את התמונות, המדיה, ההתראות והאפליקציות האחרונות שבטלפון</translation>
 <translation id="8347227221149377169">משימות הדפסה</translation>
 <translation id="834785183489258869">‏במצב אנונימי, אתרים לא יכולים להשתמש בקובצי cookie כדי לקבל מידע על פעילות הגלישה שלך באתרים השונים, למשל לצורך הצגת מודעות בהתאמה אישית. ייתכן שתכונות באתרים מסוימים לא יפעלו.</translation>
 <translation id="8350789879725387295">כלי סטיילוס באזור המוצמד</translation>
@@ -8163,6 +8170,7 @@
 <translation id="8957757410289731985">התאמה אישית של הפרופיל</translation>
 <translation id="895944840846194039">‏זיכרון JavaScript</translation>
 <translation id="8960208913905765425">המרת יחידות של תשובות מהירות</translation>
+<translation id="8960638196855923532">עכשיו יש לך אפשרות לראות את ההתראות והאפליקציות שבטלפון</translation>
 <translation id="8962051932294470566">אפשר לשתף רק קובץ אחד בכל פעם. יש לנסות שוב כאשר ההעברה הנוכחית תסתיים.</translation>
 <translation id="8962083179518285172">הסתרת פרטים</translation>
 <translation id="8962918469425892674">האתר הזה משתמש בחיישני תנועה או תאורה.</translation>
@@ -8314,6 +8322,7 @@
 <translation id="9103868373786083162">יש ללחוץ כדי לחזור אחורה, תפריט הקשר להצגת ההיסטוריה</translation>
 <translation id="9108035152087032312">מתן &amp;שם לחלון…</translation>
 <translation id="9108072915170399168">ההגדרה הנוכחית של השימוש בחבילת הגלישה היא 'ללא אינטרנט'</translation>
+<translation id="9108294543511800041">עכשיו יש לך אפשרות לראות את התמונות, המדיה וההתראות האחרונות שבטלפון</translation>
 <translation id="9108674852930645435">מה חדש ב-<ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">‏ה-DNS המאובטח לא יהיה בהכרח זמין תמיד</translation>
 <translation id="9109122242323516435">כדי לפנות נפח אחסון, יש למחוק קבצים מאחסון המכשיר.</translation>
@@ -8438,7 +8447,6 @@
 <translation id="934503638756687833">‏במקרה הצורך ייתכן שיוסרו גם פריטים שלא מופיעים כאן. מידע נוסף על &lt;a href="<ph name="URL" />"&gt;הגנה מפני תוכנות לא רצויות&lt;/a&gt; זמין בסקירה הטכנית לגבי פרטיות ב-Chrome.</translation>
 <translation id="93480724622239549">באג או שגיאה</translation>
 <translation id="935854577147268200">‏הטלפון שהוגדר ב-Smart Lock השתנה. עליך להזין את הסיסמה כדי לעדכן את Smart Lock. בפעם הבאה, הטלפון יבטל את הנעילה של <ph name="DEVICE_TYPE" />. אפשר להשבית את Smart Lock בהגדרות.</translation>
-<translation id="93610034168535821">נפח האחסון הכולל שמנוצל על ידי אתרים:</translation>
 <translation id="936646668635477464">מצלמה ומיקרופון</translation>
 <translation id="936801553271523408">נתוני אבחון של מערכת</translation>
 <translation id="93766956588638423">תיקון התוסף</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index 8fcf1a79..de30b95 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -1538,6 +1538,7 @@
 <translation id="2433836460518180625">デバイスのロック解除のみ</translation>
 <translation id="2434449159125086437">プリンタをセットアップできません。設定を確認してもう一度お試しください。</translation>
 <translation id="2434758125294431199">あなたとファイルを共有できる相手を選択してください</translation>
+<translation id="2434915728183570229">スマートフォンのアプリを表示できるようになりました</translation>
 <translation id="2435137177546457207">Google Chrome および ChromeOS Flex 追加利用規約</translation>
 <translation id="2435248616906486374">ネットワークが切断されました</translation>
 <translation id="2435457462613246316">パスワードを表示</translation>
@@ -4214,6 +4215,7 @@
 <translation id="5072900412896857127">Google Play 利用規約を読み込めません。ネットワーク接続を確認してからもう一度お試しください。</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />、<ph name="FILE2" />}other{<ph name="FILE1" />、<ph name="FILE2" />、他 # 件}}</translation>
 <translation id="5074318175948309511">新しい設定を有効にするには、ページの再読み込みが必要な可能性があります。</translation>
+<translation id="5074761966806028321">設定を完了するには権限が必要です</translation>
 <translation id="5075910247684008552">保護されているサイトでは、保護されていないコンテンツはデフォルトでブロックされます。</translation>
 <translation id="5078638979202084724">すべてのタブをブックマークに追加する</translation>
 <translation id="5078796286268621944">PIN が正しくありません</translation>
@@ -4575,6 +4577,7 @@
 <translation id="5449551289610225147">パスワードが無効です</translation>
 <translation id="5449588825071916739">すべてのタブをブックマークに追加する</translation>
 <translation id="5449716055534515760">ウィンドウを閉じる(&amp;D)</translation>
+<translation id="5452446625764825792">スマートフォンの最近の写真、メディア、アプリを表示できるようになりました</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" />(オフラインで利用可能)</translation>
 <translation id="5454166040603940656">- <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">他の検索結果を表示</translation>
@@ -4635,6 +4638,7 @@
 <translation id="5499211612787418966">このダイアログは現在フォーカスされていません。このダイアログをフォーカスするには Alt+Shift+A キーを押してください。</translation>
 <translation id="5499313591153584299">このファイルはパソコンに危害を加える可能性があります。</translation>
 <translation id="5499453227627332024">Linux コンテナのアップグレードが可能です。後で設定アプリからアップグレードすることもできます。</translation>
+<translation id="5499476581866658341">スマートフォンの最近の写真やメディアを表示できるようになりました</translation>
 <translation id="549957179819296104">アイコンが新しくなりました</translation>
 <translation id="5500168250243071806">ログイン中は Google アカウントに<ph name="BEGIN_LINK_SEARCH" />検索履歴<ph name="END_LINK_SEARCH" />や<ph name="BEGIN_LINK_GOOGLE" />その他のアクティビティ<ph name="END_LINK_GOOGLE" />が保存される可能性があります。これらのデータはいつでも削除できます。</translation>
 <translation id="5500709606820808700">安全確認を今日実行しました</translation>
@@ -6294,6 +6298,7 @@
 <translation id="7152478047064750137">この拡張機能に特別な権限は必要ありません</translation>
 <translation id="7154130902455071009">スタート ページを次に変更します: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">カメラやファイルに保存されている写真</translation>
+<translation id="7160182524506337403">スマートフォンの通知を表示できるようになりました</translation>
 <translation id="7163202347044721291">アクティベーション コードを確認しています...</translation>
 <translation id="716640248772308851">「<ph name="EXTENSION" />」はチェックした場所にある画像、動画、音声の各ファイルを読み取ることができます。</translation>
 <translation id="7167486101654761064">この種類のファイルは常に開く(&amp;A)</translation>
@@ -7306,6 +7311,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> ステータス</translation>
 <translation id="8139447493436036221">Google ドライブのファイル</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />、<ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">スマートフォン ハブではその他の機能も設定できます</translation>
 <translation id="8141584439523427891">まもなく代替ブラウザで開きます</translation>
 <translation id="8141725884565838206">パスワードを管理する</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{動画}other{# 件の動画}}</translation>
@@ -7513,6 +7519,7 @@
 <translation id="833986336429795709">このリンクを開くにはアプリを選択します</translation>
 <translation id="8342221978608739536">試していない</translation>
 <translation id="8342861492835240085">コレクションを選択</translation>
+<translation id="8345848587667658367">スマートフォンの最近の写真、メディア、通知、アプリを表示できるようになりました</translation>
 <translation id="8347227221149377169">印刷ジョブ</translation>
 <translation id="834785183489258869">シークレット モードのとき、サイトは Cookie を使用して別のサイトでのあなたの閲覧アクティビティを確認できず、広告のカスタマイズなどを行えなくなります。一部のサイトで機能を使用できなくなる可能性があります。</translation>
 <translation id="8350789879725387295">Dock のタッチペン ツール</translation>
@@ -8118,6 +8125,7 @@
 <translation id="8957757410289731985">プロフィールをカスタマイズ</translation>
 <translation id="895944840846194039">JavaScript メモリ</translation>
 <translation id="8960208913905765425">クイック アンサーの単位変換</translation>
+<translation id="8960638196855923532">スマートフォンの通知とアプリを表示できるようになりました</translation>
 <translation id="8962051932294470566">一度に共有できるファイルは 1 つのみです。現在の転送が終わってから、もう一度お試しください。</translation>
 <translation id="8962083179518285172">詳細を非表示</translation>
 <translation id="8962918469425892674">このサイトはモーション センサーまたは光センサーを使用しています。</translation>
@@ -8269,6 +8277,7 @@
 <translation id="9103868373786083162">ボタンを押して前に戻ります。履歴を表示するにはコンテキスト メニューを選択します</translation>
 <translation id="9108035152087032312">ウィンドウに名前を付ける(&amp;W)...</translation>
 <translation id="9108072915170399168">現在のデータ使用設定は「インターネットを使用しない」です</translation>
+<translation id="9108294543511800041">スマートフォンの最近の写真、メディア、通知を表示できるようになりました</translation>
 <translation id="9108674852930645435"><ph name="DEVICE_TYPE" /> の新機能のご案内</translation>
 <translation id="9108808586816295166">セキュア DNS は使用できない場合があります</translation>
 <translation id="9109122242323516435">空き領域を確保するために、デバイスのストレージからファイルを削除してください。</translation>
@@ -8393,7 +8402,6 @@
 <translation id="934503638756687833">ここに表示されていないアイテムも、必要に応じて削除されます。&lt;a href="<ph name="URL" />"&gt;迷惑ソフトウェアからの保護&lt;/a&gt;について詳しくは、Chrome のプライバシーに関するホワイト ペーパーをご覧ください。</translation>
 <translation id="93480724622239549">バグまたはエラー</translation>
 <translation id="935854577147268200">Smart Lock に使用するスマートフォンが変更されました。パスワードを入力して Smart Lock を更新すると、次回から、新しいスマートフォンで <ph name="DEVICE_TYPE" /> のロックを解除できます。Smart Lock を無効にするには [設定] をご利用ください。</translation>
-<translation id="93610034168535821">サイトの合計ストレージ使用状況:</translation>
 <translation id="936646668635477464">カメラとマイク</translation>
 <translation id="936801553271523408">システム診断データ</translation>
 <translation id="93766956588638423">拡張機能を修復</translation>
diff --git a/chrome/app/resources/generated_resources_ka.xtb b/chrome/app/resources/generated_resources_ka.xtb
index 5ffd857..38bfc507 100644
--- a/chrome/app/resources/generated_resources_ka.xtb
+++ b/chrome/app/resources/generated_resources_ka.xtb
@@ -2225,6 +2225,7 @@
 <translation id="3067198360141518313">ამ დანამატის გაშვება</translation>
 <translation id="3071624960923923138">ახალი ჩანართის გასახსნელად შეგიძლიათ დააწკაპუნოთ აქ</translation>
 <translation id="3072775339180057696">გსურთ საიტისთვის <ph name="FILE_NAME" />-ის ნახვის დაშვება?</translation>
+<translation id="3074499504015191586">გვერდის სრულად თარგმნა</translation>
 <translation id="3075874217500066906">Powerwash პროცესის დასაწყებად საჭიროა ხელახლა გაშვება. ხელახლა გაშვების შემდეგ უნდა დაადასტუროთ, რომ გაგრძელება გსურთ.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">მხოლოდ ამ მოწყობილობაზე შენახვა</translation>
@@ -5080,6 +5081,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> იყენებს თქვენს კამერას და მიკროფონს</translation>
 <translation id="5935158534896975820">მზადდება სერტიფიკატის ხელმოწერის მოთხოვნა (მოლოდინშია სერვერზე)</translation>
 <translation id="5935656526031444304">Safe Browsing-ის მართვა</translation>
+<translation id="5936065461722368675">გვერდის სრულად თარგმნა</translation>
 <translation id="5938002010494270685">ხელმისაწვდომია უსაფრთხოების განახლება</translation>
 <translation id="5939518447894949180">გადატვირთვა</translation>
 <translation id="5939719276406088041">მალსახმობი ვერ შეიქმნა</translation>
@@ -8422,7 +8424,6 @@
 <translation id="934503638756687833">საჭიროების შემთხვევაში, შეიძლება ამოიშალოს ის ერთეულებიც, რომელიც აქ ჩამოთვლილი არ არის. შეიტყვეთ მეტი &lt;a href="<ph name="URL" />"&gt;არასასურველი პროგრამული უზრუნველყოფისგან დაცვის&lt;/a&gt; შესახებ Chrome-ის კონფიდენციალურობასთან დაკავშირებულ დოკუმენტში.</translation>
 <translation id="93480724622239549">ხარვეზი ან შეცდომა</translation>
 <translation id="935854577147268200">Smart Lock-ისთვის გამოყენებული ტელეფონი შეიცვალა. შეიყვანეთ თქვენი პაროლი Smart Lock-ის გასაახლებლად. შემდეგში <ph name="DEVICE_TYPE" /> განიბლოკება თქვენი ტელეფონის მეშვეობით. Smart Lock-ის გამორთვა შესაძლებელია პარამეტრებიდან.</translation>
-<translation id="93610034168535821">საიტების მიერ გამოყენებული მეხსიერების საერთო მოცულობა:</translation>
 <translation id="936646668635477464">კამერა და მიკროფონი</translation>
 <translation id="936801553271523408">სისტემის დიაგნოსტიკის მონაცემები</translation>
 <translation id="93766956588638423">გაფართოების აღდგენა</translation>
diff --git a/chrome/app/resources/generated_resources_kk.xtb b/chrome/app/resources/generated_resources_kk.xtb
index b2f79a7..5f38151e 100644
--- a/chrome/app/resources/generated_resources_kk.xtb
+++ b/chrome/app/resources/generated_resources_kk.xtb
@@ -1904,6 +1904,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Қолдау көрсетілмейтін 1 қолданбаны жою}other{Қолдау көрсетілмейтін # қолданбаны жою}}</translation>
 <translation id="2776560192867872731">Құрылғы атауын <ph name="DEVICE_NAME" /> деп өзгерту</translation>
 <translation id="2777251078198759550">Бұл контейнерді жою</translation>
+<translation id="2778471504622896352">ChromeOS іске қосу панеліне қашықтағы құрылғыларды қосу</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Linux қолданбасын орнату кезінде қате кетті</translation>
 <translation id="2783298271312924866">Жүктелген</translation>
@@ -3539,6 +3540,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> және тағы <ph name="NUMBER_OF_OTHER_SWITCHES" /> ауыстырғыш</translation>
 <translation id="439266289085815679">Bluetooth конфигурациясын <ph name="USER_EMAIL" /> басқарады.</translation>
 <translation id="4392896746540753732">Конфигурация файлын өзгерту</translation>
+<translation id="4393713825278446281"><ph name="PRIMARY_EMAIL" /> аккаунтына сақталған Fast Pair құрылғылары</translation>
 <translation id="4394049700291259645">Өшіру</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Барлығын ашу}=1{&amp;Бетбелгіні ашу}other{&amp;Барлығын ({COUNT}) ашу}}</translation>
 <translation id="4397372003838952832">Бұл құпия сөзді есте сақтаудың қажеті жоқ. <ph name="EMAIL" /> аккаунты үшін ол мына жерде сақталады: <ph name="GOOGLE_PASSWORD_MANAGER" />.</translation>
@@ -3768,6 +3770,7 @@
 <translation id="4615586811063744755">бірде-бір cookie файлы таңдалмады</translation>
 <translation id="461661862154729886">Қуат көзі</translation>
 <translation id="4617001782309103936">Тым қысқа</translation>
+<translation id="4617019240346358451">"<ph name="EXTENSION_NAME" />" кеңейтімін пайдалану үшін бетті қайта жүктеңіз</translation>
 <translation id="4617270414136722281">Кеңейтім опциялары</translation>
 <translation id="4617880081511131945">Байланыс орнату мүмкін емес</translation>
 <translation id="4619564267100705184">Жеке басыңызды растаңыз</translation>
@@ -3983,6 +3986,7 @@
 <translation id="4833683849865011483">Басып шығару серверінен 1 принтер табылды.</translation>
 <translation id="4836504898754963407">Саусақ іздерін басқару</translation>
 <translation id="4837128290434901661">Google Search іздеу жүйесіне қайта ораласыз ба?</translation>
+<translation id="4837165100461973682">Өзгерістер күшіне енуі үшін бетті қайта жүктеңіз</translation>
 <translation id="4837926214103741331">Бұл құрылғыны пайдалану рұқсатыңыз жоқ. Кіру рұқсатын алу үшін құрылғы иесіне хабарласыңыз.</translation>
 <translation id="4837952862063191349">Жергілікті деректердің құлпын ашып, қалпына келтіру үшін, ескі <ph name="DEVICE_TYPE" /> құпия сөзіңізді енгізіңіз.</translation>
 <translation id="4838170306476614339">Телефондағы фотосуреттерді, медиафайлдар мен хабарландыруларды көру</translation>
@@ -4292,6 +4296,7 @@
 <translation id="5150254825601720210">Netscape сертификат SSL сервер атауы</translation>
 <translation id="5151354047782775295">Дискіде орын босатпасаңыз, кейбір деректер автоматты түрде жойылады</translation>
 <translation id="5153234146675181447">Телефонды ұмыту</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722"><ph name="PRINTING_DESTINATION" /> кеңейтілген параметрлері</translation>
 <translation id="5154702632169343078">Тақырыбы</translation>
 <translation id="5155327081870541046">Мекенжай жолағына іздегіңіз келген сайттың жылдам пәрменін (мысалы, "@bookmarks") енгізіңіз. Содан кейін қажетті перне тіркесімін басып, ізделетін сөзді енгізіңіз.</translation>
@@ -5924,6 +5929,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> қашықтан қосылды</translation>
 <translation id="6790820461102226165">Адам қосу…</translation>
 <translation id="6793604637258913070">Шыққанда не жылжығанда, курсорды бөлектеу</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">Автосканерлеу функциясы экрандағы элементтер арасында автоматты түрде жылжуға мүмкіндік береді. Элемент бөлектелген кезде, оны іске қосу үшін "Таңдау" пернесін басыңыз.</translation>
 <translation id="6795884519221689054">Панда</translation>
 <translation id="6797493596609571643">Бір нәрсе дұрыс емес.</translation>
@@ -7795,6 +7801,7 @@
 <translation id="8642947597466641025">Мәтінді үлкейту</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> қауіпті болуы мүмкін. Сканерлеу үшін Google Күшейтілген қорғаныс қызметіне жіберілсін бе?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Ешқандай cookie файлы жоқ}=1{1 cookie файлы бөгелді}other{# cookie файлы бөгелді}}</translation>
+<translation id="864423554496711319">Аккаунтыңызға сақталған құрылғылар</translation>
 <translation id="8644655801811752511">Қауіпсіздік кілтін бастапқы күйіне қайтару мүмкін емес. Кілтті енгізгеннен кейін, дереу бастапқы қалпына қайтарып көріңіз.</translation>
 <translation id="8645354835496065562">Датчиктерді пайдалану рұқсатын беруді тоқтатпау</translation>
 <translation id="8645920082661222035">Қауіпті іс-шараларды алдын ала болжайды және олар туралы хабарлайды.</translation>
@@ -8399,7 +8406,6 @@
 <translation id="934503638756687833">Қажет болса, бұл тізімде жоқ элементтер де өшіріледі. <ph name="URL" />Қажетсіз бағдарламалық құралдан қорғану&lt;/a&gt; туралы ақпаратты Chrome құпиялылықты қорғау ақпараттық құжатынан таба аласыз.</translation>
 <translation id="93480724622239549">Қате</translation>
 <translation id="935854577147268200">Smart Lock телефоны өзгерді. Smart Lock функциясын жаңарту үшін құпия сөзіңізді енгізіңіз. Келесіде телефон <ph name="DEVICE_TYPE" /> құрылғысының құлпын аша алады. Smart Lock функциясын "Параметрлер" бөлімінен өшіруге болады.</translation>
-<translation id="93610034168535821">Сайт пайдаланатын жалпы жад көлемі:</translation>
 <translation id="936646668635477464">Камера және микрофон</translation>
 <translation id="936801553271523408">Жүйенің диагностикалық деректері</translation>
 <translation id="93766956588638423">Кеңейтімді жөндеу</translation>
diff --git a/chrome/app/resources/generated_resources_km.xtb b/chrome/app/resources/generated_resources_km.xtb
index 98433cc5..9a4e91b 100644
--- a/chrome/app/resources/generated_resources_km.xtb
+++ b/chrome/app/resources/generated_resources_km.xtb
@@ -2240,6 +2240,7 @@
 <translation id="3067198360141518313">ដំណើរការកម្មវិធីជំនួយនេះ</translation>
 <translation id="3071624960923923138">អ្នកអាច​ចុច​ទីនេះ​ដើម្បី​បើក​ផ្ទាំងថ្មី</translation>
 <translation id="3072775339180057696">អនុញ្ញាតឱ្យ​គេហទំព័រ​មើល <ph name="FILE_NAME" /> ឬ?</translation>
+<translation id="3074499504015191586">បកប្រែ​ទំព័រ​ទាំងមូល</translation>
 <translation id="3075874217500066906">ការចាប់ផ្តើមឡើងវិញតម្រូវឲ្យចាប់ផ្តើមដំណើរការ Powerwash។ បន្ទាប់ពីចាប់ផ្តើមឡើងវិញ អ្នកត្រូវបានសួរឲ្យអះអាងថា អ្នកចង់បន្តឬទេ។</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">រក្សាទុកនៅលើឧបករណ៍នេះតែប៉ុណ្ណោះ</translation>
@@ -5097,6 +5098,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> កំពុងប្រើ​កាមេរ៉ា និងមីក្រូហ្វូន​របស់អ្នក</translation>
 <translation id="5935158534896975820">កំពុងរៀបចំ​សំណើសុំ​ចុះហត្ថលេខា​លើវិញ្ញាបនបត្រ (កំពុងរង់ចាំ​ម៉ាស៊ីនមេ)</translation>
 <translation id="5935656526031444304">គ្រប់គ្រង​ការរុករក​ដោយសុវត្ថិភាព</translation>
+<translation id="5936065461722368675">បកប្រែ​ទំព័រ​ទាំងមូល</translation>
 <translation id="5938002010494270685">អាចដំឡើងកំណែ​សោសុវត្ថិភាព​បានហើយ</translation>
 <translation id="5939518447894949180">កំណត់ឡើងវិញ</translation>
 <translation id="5939719276406088041">មិនអាចបង្កើត​ផ្លូវកាត់​បានទេ</translation>
@@ -8441,7 +8443,6 @@
 <translation id="934503638756687833">ធាតុ​ដែល​មិន​​បង្ហាញនៅ​ទី​នេះ​ក៏​នឹង​ត្រូវ​លុប​​ចេញ​ផងដែរ ប្រសិន​បើ​ចាំបាច់។ ស្វែង​យល់​បន្ថែម​អំពី &lt;a href="<ph name="URL" />"&gt;ការ​ការ​ពារ​កម្មវិធី​ដែល​មិន​ចង់​បាន&lt;/a&gt;នៅក្នុង​ក្រដាស​ស​ឯកជនភាព Chrome ។</translation>
 <translation id="93480724622239549">បញ្ហា ឬកំហុស</translation>
 <translation id="935854577147268200">Smart Lock របស់​ទូរសព្ទបានផ្លាស់ប្ដូរ។ បញ្ចូល​ពាក្យសម្ងាត់​របស់អ្នក ដើម្បី​ធ្វើបច្ចុប្បន្នភាព​ Smart Lock ។ លើកក្រោយ ទូរសព្ទរបស់អ្នក​នឹងដោះសោ <ph name="DEVICE_TYPE" /> របស់អ្នក។ បិទ Smart Lock នៅក្នុង​ការកំណត់</translation>
-<translation id="93610034168535821">ទំហំផ្ទុក​សរុប​ដែលប្រើ​ដោយ​គេហទំព័រ៖</translation>
 <translation id="936646668635477464">កាមេរ៉ា និងមីក្រូហ្វូន</translation>
 <translation id="936801553271523408">ទិន្នន័យវិនិច្ឆ័យប្រព័ន្ធ</translation>
 <translation id="93766956588638423">ជួសជុលផ្នែកបន្ថែម</translation>
diff --git a/chrome/app/resources/generated_resources_kn.xtb b/chrome/app/resources/generated_resources_kn.xtb
index 8889dcb..86a496da 100644
--- a/chrome/app/resources/generated_resources_kn.xtb
+++ b/chrome/app/resources/generated_resources_kn.xtb
@@ -2232,6 +2232,7 @@
 <translation id="3067198360141518313">ಈ ಪ್ಲಗಿನ್ ಚಾಲನೆ ಮಾಡು</translation>
 <translation id="3071624960923923138">ಹೊಸ ಟ್ಯಾಬ್ ತೆರೆಯಲು ಇಲ್ಲಿ ನೀವು ಕ್ಲಿಕ್ ಮಾಡಬಹುದು</translation>
 <translation id="3072775339180057696"><ph name="FILE_NAME" /> ಅನ್ನು ವೀಕ್ಷಿಸಲು ಸೈಟ್‌ಗೆ ಅನುಮತಿಸುವುದೇ?</translation>
+<translation id="3074499504015191586">ಪೂರ್ಣ ಪುಟವನ್ನು ಅನುವಾದಿಸಿ</translation>
 <translation id="3075874217500066906">ಪವರ್‌ವಾಶ್ ಪ್ರಕ್ರಿಯೆಯನ್ನು ಆರಂಭಿಸಲು ಪುನರಾರಂಭದ ಅಗತ್ಯವಿದೆ. ಪುನರಾರಂಭದ ನಂತರ ಮುಂದುವರಿಸಲು ಬಯಸುತ್ತೀರಾ ಎಂದು ನಿಮ್ಮಲ್ಲಿ ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ಕೇಳಲಾಗುತ್ತದೆ.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">ಈ ಸಾಧನದಲ್ಲಿ ಮಾತ್ರ ಉಳಿಸಿ</translation>
@@ -5090,6 +5091,7 @@
 <translation id="5933522550144185133">ನಿಮ್ಮ ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು <ph name="APP_NAME" /> ಬಳಸುತ್ತಿದೆ</translation>
 <translation id="5935158534896975820">ಪ್ರಮಾಣಪತ್ರಕ್ಕೆ ಸಹಿ ಮಾಡುವ ವಿನಂತಿಯನ್ನು ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ (ಸರ್ವರ್‌ನಲ್ಲಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ)</translation>
 <translation id="5935656526031444304">ಸುರಕ್ಷಿತ ಬ್ರೌಸಿಂಗ್‌ ಅನ್ನು ನಿರ್ವಹಿಸಿ</translation>
+<translation id="5936065461722368675">ಪೂರ್ಣ ಪುಟವನ್ನು ಅನುವಾದಿಸಿ</translation>
 <translation id="5938002010494270685">ಸುರಕ್ಷತಾ ಅಪ್‌ಗ್ರೇಡ್‌‌ ಲಭ್ಯವಿದೆ</translation>
 <translation id="5939518447894949180">ಮರುಹೊಂದಿಸು</translation>
 <translation id="5939719276406088041">ಶಾರ್ಟ್‌ಕಟ್ ರಚಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ</translation>
@@ -8435,7 +8437,6 @@
 <translation id="934503638756687833">ಅಗತ್ಯವಿದ್ದರೆ, ಇಲ್ಲಿ ಪಟ್ಟಿ ಮಾಡಿರದ ಐಟಂಗಳನ್ನು ಸಹ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ. &lt;a href="<ph name="URL" />"&gt;ಅನಪೇಕ್ಷಿತ ಸಾಫ್ಟ್‌ವೇರ್‌ನಿಂದ ಸಂರಕ್ಷಣೆ&lt;/a&gt; ಕುರಿತು Chrome ಗೌಪ್ಯತೆ ಬಿಳಿ ಹಾಳೆಯಲ್ಲಿ ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ.</translation>
 <translation id="93480724622239549">ಬಗ್‌ ಅಥವಾ ದೋಷ</translation>
 <translation id="935854577147268200">Smart Lock ಫೋನ್ ಬದಲಾಗಿದೆ. Smart Lock ಅನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಲು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ. ಮುಂದಿನ ಬಾರಿ, ನಿಮ್ಮ ಫೋನ್ ನಿಮ್ಮ <ph name="DEVICE_TYPE" /> ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡುತ್ತದೆ. ನೀವು ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ Smart Lock ಅನ್ನು ಆಫ್ ಮಾಡಬಹುದು</translation>
-<translation id="93610034168535821">ಸೈಟ್‌ಗಳು ಬಳಸಿದ ಒಟ್ಟು ಸಂಗ್ರಹಣೆ:</translation>
 <translation id="936646668635477464">ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೋಫೋನ್</translation>
 <translation id="936801553271523408">ಸಿಸ್ಟಂ ವಿಶ್ಲೇಷಣಾತ್ಮಕ ಡೇಟಾ</translation>
 <translation id="93766956588638423">ವಿಸ್ತರಣೆ ದುರಸ್ತಿಪಡಿಸಿ</translation>
diff --git a/chrome/app/resources/generated_resources_ko.xtb b/chrome/app/resources/generated_resources_ko.xtb
index ea87447..4e0b2a1 100644
--- a/chrome/app/resources/generated_resources_ko.xtb
+++ b/chrome/app/resources/generated_resources_ko.xtb
@@ -1559,6 +1559,7 @@
 <translation id="2433836460518180625">기기만 잠금 해제</translation>
 <translation id="2434449159125086437">프린터를 설정할 수 없습니다. 설정을 확인하고 다시 시도해 보세요.</translation>
 <translation id="2434758125294431199">나에게 공유할 수 있는 사람을 선택하세요.</translation>
+<translation id="2434915728183570229">이제 휴대전화의 앱을 확인할 수 있습니다.</translation>
 <translation id="2435137177546457207">Chrome 및 ChromeOS Flex 추가 약관</translation>
 <translation id="2435248616906486374">네트워크 연결 끊김</translation>
 <translation id="2435457462613246316">비밀번호 표시</translation>
@@ -4241,6 +4242,7 @@
 <translation id="5072900412896857127">Google Play 서비스 약관을 로드할 수 없습니다. 네트워크 연결을 확인한 다음 다시 시도하세요.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" /> 외 #개}}</translation>
 <translation id="5074318175948309511">새로운 설정을 적용하기 전에 페이지를 다시 로드해야 할 수도 있습니다.</translation>
+<translation id="5074761966806028321">설정을 완료하려면 여전히 권한이 필요합니다.</translation>
 <translation id="5075910247684008552">보안 사이트에서는 안전하지 않은 콘텐츠가 기본적으로 차단됩니다.</translation>
 <translation id="5078638979202084724">모든 탭 북마크</translation>
 <translation id="5078796286268621944">잘못된 PIN</translation>
@@ -4604,6 +4606,7 @@
 <translation id="5449551289610225147">비밀번호가 잘못되었습니다.</translation>
 <translation id="5449588825071916739">모든 탭 북마크</translation>
 <translation id="5449716055534515760">창 닫기(&amp;D)</translation>
+<translation id="5452446625764825792">이제 휴대전화의 최근 사진, 미디어, 앱을 확인할 수 있습니다.</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" />(오프라인에서 사용 가능)</translation>
 <translation id="5454166040603940656">제공업체: <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">검색결과 더보기</translation>
@@ -4664,6 +4667,7 @@
 <translation id="5499211612787418966">현재 이 대화상자에 포커스가 지정되지 않았습니다. Alt+Shift+A를 눌러 이 대화상자에 포커스를 지정하세요.</translation>
 <translation id="5499313591153584299">이 파일은 컴퓨터에 해로울 수 있습니다.</translation>
 <translation id="5499453227627332024">Linux 컨테이너를 업그레이드할 수 있습니다. 나중에 설정 앱에서 업그레이드해도 됩니다.</translation>
+<translation id="5499476581866658341">이제 휴대전화의 최근 사진과 미디어를 확인할 수 있습니다.</translation>
 <translation id="549957179819296104">새로운 아이콘</translation>
 <translation id="5500168250243071806">로그인할 경우 <ph name="BEGIN_LINK_SEARCH" />검색 기록<ph name="END_LINK_SEARCH" /> 및 <ph name="BEGIN_LINK_GOOGLE" />다른 활동 형식<ph name="END_LINK_GOOGLE" />이 Google 계정에 저장될 수 있습니다. 이러한 데이터는 언제든지 삭제할 수 있습니다.</translation>
 <translation id="5500709606820808700">안전 확인이 오늘 실행됨</translation>
@@ -6328,6 +6332,7 @@
 <translation id="7152478047064750137">이 확장 프로그램에는 특별한 권한이 필요하지 않습니다</translation>
 <translation id="7154130902455071009">다음으로 시작 페이지 변경: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">카메라 또는 파일의 기존 사진</translation>
+<translation id="7160182524506337403">이제 휴대전화의 알림을 확인할 수 있습니다.</translation>
 <translation id="7163202347044721291">활성화 코드 확인 중…</translation>
 <translation id="716640248772308851">'<ph name="EXTENSION" />'은(는) 선택된 위치에서 이미지, 동영상 및 사운드 파일을 읽을 수 있습니다.</translation>
 <translation id="7167486101654761064">해당 유형의 파일 항상 열기(&amp;A)</translation>
@@ -7344,6 +7349,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> 상태</translation>
 <translation id="8139447493436036221">Google Drive 파일</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">휴대전화 허브 설정에서 더 많은 기능을 설정할 수 있습니다.</translation>
 <translation id="8141584439523427891">지금 대체 브라우저에서 열립니다.</translation>
 <translation id="8141725884565838206">비밀번호 관리</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{동영상 1개}other{동영상 #개}}</translation>
@@ -7551,6 +7557,7 @@
 <translation id="833986336429795709">이 링크를 열려면 앱을 선택하세요.</translation>
 <translation id="8342221978608739536">사용해 보지 않음</translation>
 <translation id="8342861492835240085">컬렉션 선택</translation>
+<translation id="8345848587667658367">이제 휴대전화의 최근 사진, 미디어, 알림, 앱을 확인할 수 있습니다.</translation>
 <translation id="8347227221149377169">인쇄 작업</translation>
 <translation id="834785183489258869">시크릿 모드에 있는 동안에는 사이트에서 사용자의 다양한 사이트 탐색 활동 정보를 이용해 광고 맞춤설정 등의 작업을 하는 데 쿠키를 사용할 수 없습니다. 일부 사이트에서는 기능이 작동하지 않을 수 있습니다.</translation>
 <translation id="8350789879725387295">도크에 스타일러스 도구 표시</translation>
@@ -8156,6 +8163,7 @@
 <translation id="8957757410289731985">프로필 맞춤설정</translation>
 <translation id="895944840846194039">자바스크립트 메모리</translation>
 <translation id="8960208913905765425">빠른 답변 단위 변환</translation>
+<translation id="8960638196855923532">이제 휴대전화의 알림과 앱을 확인할 수 있습니다.</translation>
 <translation id="8962051932294470566">한 번에 하나의 파일만 공유할 수 있습니다. 현재 전송이 완료되면 다시 시도해 보세요.</translation>
 <translation id="8962083179518285172">세부정보 숨기기</translation>
 <translation id="8962918469425892674">사이트에서 모션 센서 또는 조도 센서를 사용 중입니다.</translation>
@@ -8307,6 +8315,7 @@
 <translation id="9103868373786083162">돌아가려면 뒤로 버튼을 누르고, 방문 기록을 보려면 컨텍스트 메뉴 키를 누릅니다.</translation>
 <translation id="9108035152087032312">창 이름 지정...</translation>
 <translation id="9108072915170399168">현재 데이터 사용 설정은 인터넷 사용 안함입니다</translation>
+<translation id="9108294543511800041">이제 휴대전화의 최근 사진, 미디어, 알림을 확인할 수 있습니다.</translation>
 <translation id="9108674852930645435"><ph name="DEVICE_TYPE" />의 새로운 기능 살펴보기</translation>
 <translation id="9108808586816295166">보안 DNS가 항상 제공되지는 않을 수도 있습니다.</translation>
 <translation id="9109122242323516435">저장 공간을 확보하려면 기기 저장소에서 파일을 삭제하세요.</translation>
@@ -8431,7 +8440,6 @@
 <translation id="934503638756687833">필요한 경우 여기에 표시되지 않은 항목도 삭제됩니다. Chrome 개인정보 보호 백서에서 &lt;a href="<ph name="URL" />"&gt;원치 않는 소프트웨어 보호&lt;/a&gt;에 관해 자세히 알아보세요.</translation>
 <translation id="93480724622239549">버그 또는 오류</translation>
 <translation id="935854577147268200">Smart Lock 휴대전화가 변경되었습니다. Smart Lock을 업데이트하려면 비밀번호를 입력하세요. 다음번에는 휴대전화를 통해 <ph name="DEVICE_TYPE" />이(가) 잠금 해제됩니다. 설정에서 Smart Lock을 사용 중지할 수 있습니다.</translation>
-<translation id="93610034168535821">사이트에서 사용 중인 총 저장용량:</translation>
 <translation id="936646668635477464">카메라 및 마이크</translation>
 <translation id="936801553271523408">시스템 진단 데이터</translation>
 <translation id="93766956588638423">확장 프로그램 복구</translation>
diff --git a/chrome/app/resources/generated_resources_ky.xtb b/chrome/app/resources/generated_resources_ky.xtb
index ee63e74f..f28bb7d 100644
--- a/chrome/app/resources/generated_resources_ky.xtb
+++ b/chrome/app/resources/generated_resources_ky.xtb
@@ -1558,6 +1558,7 @@
 <translation id="2433836460518180625">Түзмөктүн кулпусун гана ачуу</translation>
 <translation id="2434449159125086437">Принтер жөндөлгөн жок. Анын конфигурациясын текшерип, кайталап көрүңүз.</translation>
 <translation id="2434758125294431199">Сиз менен ким бөлүшө аларын тандаңыз</translation>
+<translation id="2434915728183570229">Телефонуңуздагы колдонмолорду көрө аласыз</translation>
 <translation id="2435137177546457207">Google Chrome жана ChromeOS Flex'тин кошумча шарттары</translation>
 <translation id="2435248616906486374">Тармак ажыратылды</translation>
 <translation id="2435457462613246316">Сырсөздү көрсөтүү</translation>
@@ -2239,6 +2240,7 @@
 <translation id="3067198360141518313">Бул плагинди иштетүү</translation>
 <translation id="3071624960923923138">Жаңы өтмөк ачуу үчүн бул жерди чыкылдатып коюңуз</translation>
 <translation id="3072775339180057696">Сайт <ph name="FILE_NAME" /> файлын көрсүнбү?</translation>
+<translation id="3074499504015191586">Толук баракты которуу</translation>
 <translation id="3075874217500066906">Жууп салуу процессин баштоо үчүн өчүрүп күйгүзүү аракети талап кылынат. Өчүрүлүп күйгүзүлгөндөн кийин, уланта турганыңызды ырасташыңыз керек.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">Ушул түзмөктө гана сактоо</translation>
@@ -4242,6 +4244,7 @@
 <translation id="5072900412896857127">Google Play Тейлөө шарттары жүктөлбөй жатат. Тармактык туташууңузду текшерип, дагы бир жолу аракет кылыңыз.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" /> жана дагы #}}</translation>
 <translation id="5074318175948309511">Жаңы жөндөөлөр күчүнө киргенге чейин бул баракча кайра жүктөлүшү керек.</translation>
+<translation id="5074761966806028321">Тууралап бүтүрүү үчүн уруксат берүү керек</translation>
 <translation id="5075910247684008552">Коопсуз сайттарда кооптуу мазмун демейки шартта бөгөттөлөт</translation>
 <translation id="5078638979202084724">Бардык өтмөктөрдү кыстарып коюу</translation>
 <translation id="5078796286268621944">Туура эмес PIN</translation>
@@ -4605,6 +4608,7 @@
 <translation id="5449551289610225147">Сырсөз жараксыз</translation>
 <translation id="5449588825071916739">Бардык өтмөктөрдү кыстарып коюу</translation>
 <translation id="5449716055534515760">Тере&amp;зени жабуу</translation>
+<translation id="5452446625764825792">Телефонуңуздагы соңку сүрөттөрдү, медианы жана колдонмолорду көрө аласыз</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (оффлайн режиминде иштейт)</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" /> менен</translation>
 <translation id="545484289444831485">Дагы табылган нерселерди көрүү</translation>
@@ -4665,6 +4669,7 @@
 <translation id="5499211612787418966">Учурда бул диалог тандалбай турат. Бул диалогду тандоо үчүн Alt-Shift A баскычын басыңыз.</translation>
 <translation id="5499313591153584299">Бул файлдын компьютериңизге зыяны тийип калышы мүмкүн.</translation>
 <translation id="5499453227627332024">Linux контейнеринин жаңы версиясы жеткиликтүү. Аны кийинчерээк колдонмонун Жөндөөлөрүнө өтүп, жүктөп алсаңыз болот.</translation>
+<translation id="5499476581866658341">Телефонуңуздагы соңку сүрөттөрдү жана медианы көрө аласыз</translation>
 <translation id="549957179819296104">Жаңы сүрөтчө</translation>
 <translation id="5500168250243071806">Аккаунтуңузга кирип турсаңыз, <ph name="BEGIN_LINK_SEARCH" />издөө таржымалы<ph name="END_LINK_SEARCH" /> жана <ph name="BEGIN_LINK_GOOGLE" />башка аракеттер<ph name="END_LINK_GOOGLE" /> Google аккаунтуңузга сакталышы мүмкүн. Аларды каалаган убакта жок кылсаңыз болот.</translation>
 <translation id="5500709606820808700">Коопсуздук бүгүн текшерилди</translation>
@@ -5092,6 +5097,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> сиздин камера менен микрофонуңузду колдонууда</translation>
 <translation id="5935158534896975820">Тастыктамага кол коюу сурамы даярдалууда (серверде күтүлүүдө)</translation>
 <translation id="5935656526031444304">Коопсуз серептөөнү башкаруу</translation>
+<translation id="5936065461722368675">Толук баракты которуу</translation>
 <translation id="5938002010494270685">Коопсуздук тутумунун жаңы версиясы бар</translation>
 <translation id="5939518447894949180">Кайра коюу</translation>
 <translation id="5939719276406088041">Ыкчам баскыч түзүлбөй жатат</translation>
@@ -6329,6 +6335,7 @@
 <translation id="7152478047064750137">Бул кеңейтүү атайын уруксаттарды талап кылбайт</translation>
 <translation id="7154130902455071009">Баштоо баракчаңызды төмөнкүгө өзгөртүңүз: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Камерадагы же файлдагы учурдагы сүрөт</translation>
+<translation id="7160182524506337403">Телефонуңуздагы билдирмелерди көрө аласыз</translation>
 <translation id="7163202347044721291">Жандандыруу коду текшерилүүдө…</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" белгиленген жерлердеги сүрөттөрдү, видеону жана үн файлдарын окуй алат.</translation>
 <translation id="7167486101654761064">Мындай түрдөгү файлдар &amp;ар дайым ачылсын</translation>
@@ -7343,6 +7350,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> абалы</translation>
 <translation id="8139447493436036221">Google Drive файлдары</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Phone Hub параметрлеринен кошумча функцияларды тууралап алсаңыз болот</translation>
 <translation id="8141584439523427891">Кошумча серепчи азыр ачылууда</translation>
 <translation id="8141725884565838206">Сырсөздөрүңүздү башкарыңыз</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{видео}other{# видео}}</translation>
@@ -7550,6 +7558,7 @@
 <translation id="833986336429795709">Бул шилтемени ачуудан мурда колдонмону тандаңыз</translation>
 <translation id="8342221978608739536">Колдонуп көргөн жокмун</translation>
 <translation id="8342861492835240085">Жыйнакты тандаңыз</translation>
+<translation id="8345848587667658367">Телефонуңуздагы акыркы сүрөттөрдү, медиа файлдарды, билдирмелерди жана колдонмолорду көрө аласыз</translation>
 <translation id="8347227221149377169">Басып чыгаруу тапшырмалары</translation>
 <translation id="834785183489258869">Жашыруун режимде, сайттар cookie файлдарыңыз аркылуу сиз көргөн вебсайттарды көрө албайт (мисалы, жарнамаларды жекелештирүү үчүн). Функциялар айрым сайттарда иштебеши мүмкүн.</translation>
 <translation id="8350789879725387295">Стилус куралдарын тилкеде көрсөтүү</translation>
@@ -8155,6 +8164,7 @@
 <translation id="8957757410289731985">Профилди ыңгайлаштыруу</translation>
 <translation id="895944840846194039">JavaScript эстутуму</translation>
 <translation id="8960208913905765425">Ыкчам жооптордогу бирдик которуу</translation>
+<translation id="8960638196855923532">Телефонуңуздагы билдирмелерди жана колдонмолорду көрө аласыз</translation>
 <translation id="8962051932294470566">Бир маалда бир файлды гана өткөрө аласыз. Учурдагы файл өткөрүлүп бүткөндөн кийин кайра аракет кылыңыз.</translation>
 <translation id="8962083179518285172">Чоо-жайды жашыруу</translation>
 <translation id="8962918469425892674">Бул сайт кыймыл же жарык сенсорлорун колдонуп жатат.</translation>
@@ -8306,6 +8316,7 @@
 <translation id="9103868373786083162">Артка кайрылуу үчүн басыңыз, таржымалды көрүү үчүн мазмундук меню</translation>
 <translation id="9108035152087032312">&amp;Терезенин аталышын коюңуз...</translation>
 <translation id="9108072915170399168">Учурда дайын-даректердин өткөрүлүшү "Интернетсиз" деп коюлган</translation>
+<translation id="9108294543511800041">Телефонуңуздагы соңку сүрөттөрдү, медианы жана билдирмелерди көрө аласыз</translation>
 <translation id="9108674852930645435"><ph name="DEVICE_TYPE" /> түзмөгүңүздөгү жаңылыктарды көрүңүз</translation>
 <translation id="9108808586816295166">Коопсуз DNS ар дайым жеткиликтүү болбошу мүмкүн</translation>
 <translation id="9109122242323516435">Орун бошотуу үчүн түзмөктүн сактагычынан файлдарды жок кылыңыз.</translation>
@@ -8430,7 +8441,6 @@
 <translation id="934503638756687833">Эгер зарыл болсо, бул тизмеде жок нерселерди да алып салууга болот. &lt;a href="<ph name="URL" />"&gt;Зыяндуу программалардан коргоо&lt;/a&gt; тууралуу кененирээк маалымат алуу үчүн Chrome'дун Купуялык саясатынын артыкчылыктарын карап чыгыңыз.</translation>
 <translation id="93480724622239549">Мүчүлүштүк же ката</translation>
 <translation id="935854577147268200">Smart Lock үчүн телефон өзгөрдү. Smart Lock'ту жаңыртуу үчүн, сырсөзүңүздү киргизиңиз. Эми <ph name="DEVICE_TYPE" /> түзмөгүңүздүн кулпусун телефонуңуз менен ачсаңыз болот. Жөндөөлөргө өтүп, Smart Lock'ту өчүрүп койсоңуз болот.</translation>
-<translation id="93610034168535821">Сайттар ээлеген жалпы орун:</translation>
 <translation id="936646668635477464">Камера жана микрофон</translation>
 <translation id="936801553271523408">Системанын диагностика дайындары</translation>
 <translation id="93766956588638423">Кеңейтүүнү оңдоо</translation>
diff --git a/chrome/app/resources/generated_resources_lo.xtb b/chrome/app/resources/generated_resources_lo.xtb
index 76f7180..86a0f6b7 100644
--- a/chrome/app/resources/generated_resources_lo.xtb
+++ b/chrome/app/resources/generated_resources_lo.xtb
@@ -2238,6 +2238,7 @@
 <translation id="3067198360141518313">ແລ່ນປລັກອິນນີ້</translation>
 <translation id="3071624960923923138">ທ່ານສາມາດຄລິກບ່ອນນີ້ເພື່ອເປີດແຖບໃໝ່</translation>
 <translation id="3072775339180057696">ອະນຸຍາດໃຫ້ເວັບໄຊເບິ່ງ <ph name="FILE_NAME" /> ບໍ?</translation>
+<translation id="3074499504015191586">ແປພາສາໜ້າເຕັມ</translation>
 <translation id="3075874217500066906">ຕ້ອງການໃຫ້ມີການປິດເປີດໃໝ່ ເພື່ອເລີ່ມຕົ້ນຂະບວນການ Powerwash. ຫຼັງຈາກປິດເປີດໃໝ່ແລ້ວ ທ່ານຈະຖືກຖາມໃຫ້ຢືນຢັນວ່າ ທ່ານຕ້ອງການດໍາເນີນການຕໍ່.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">ບັນທຶກໄວ້ໃນອຸປະກອນນີ້ເທົ່ານັ້ນ</translation>
@@ -5090,6 +5091,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> ກຳລັງໃຊ້ກ້ອງ ແລະ ໄມໂຄຣໂຟນຂອງທ່ານ</translation>
 <translation id="5935158534896975820">ກຳລັງກະກຽມຄຳຂໍເຊັນໃບຮັບຮອງ (ລໍຖ້າໃນເຊີບເວີ)</translation>
 <translation id="5935656526031444304">ຈັດການ Safe Browsing</translation>
+<translation id="5936065461722368675">ແປພາສາໜ້າເຕັມ</translation>
 <translation id="5938002010494270685">ມີການອັບເກຣດຄວາມປອດໄພ</translation>
 <translation id="5939518447894949180">ຕັ້ງຄ່າຄືນໃໝ່</translation>
 <translation id="5939719276406088041">ບໍ່ສາມາດສ້າງທາງລັດໄດ້</translation>
@@ -8427,7 +8429,6 @@
 <translation id="934503638756687833">ລາຍການທີ່ບໍ່ລະບຸຢູ່ບ່ອນນີ້ຈະຖືກລຶບອອກເຊັ່ນກັນ ຖ້າຈຳເປັນ. ສຶກສາເພີ່ມເຕີມກ່ຽວກັບ &lt;a href="<ph name="URL" />"&gt;ການປົກປ້ອງຊອບແວທີ່ບໍ່ຕ້ອງການ&lt;/a&gt; ໃນເອກະສານຂາວວ່າດ້ວຍຄວາມເປັນສ່ວນຕົວຂອງ Chrome.</translation>
 <translation id="93480724622239549">ຂໍ້ບົກພ່ອງ ຫຼື ຂໍ້ຜິດພາດ</translation>
 <translation id="935854577147268200">ປ່ຽນໂທລະສັບ Smart Lock ແລ້ວ ປ້ອນລະຫັດຜ່ານຂອງທ່ານເພື່ອອັບເດດ Smart Lock. ຄັ້ງຕໍ່ໄປ, ໂທລະສັບຂອງທ່ານຈະປົດລັອກ <ph name="DEVICE_TYPE" /> ຂອງທ່ານ. ທ່ານສາມາດປິດ Smart Lock ໄດ້ໃນການຕັ້ງຄ່າ</translation>
-<translation id="93610034168535821">ພື້ນທີ່ຈັດເກັບຂໍ້ມູນທັງໝົດທີ່ໃຊ້ໂດຍເວັບໄຊ:</translation>
 <translation id="936646668635477464">ກ້ອງ ແລະ ໄມໂຄຣໂຟນ</translation>
 <translation id="936801553271523408">ຂໍ້ມູນກວດວິເຄາະລະບົບ</translation>
 <translation id="93766956588638423">ສ້ອມ​ແປງສ່ວນຂະ​ຫຍາຍ​</translation>
diff --git a/chrome/app/resources/generated_resources_lt.xtb b/chrome/app/resources/generated_resources_lt.xtb
index 1458e2c..f984bb3 100644
--- a/chrome/app/resources/generated_resources_lt.xtb
+++ b/chrome/app/resources/generated_resources_lt.xtb
@@ -8453,7 +8453,6 @@
 <translation id="934503638756687833">Jei reikės, bus pašalinti ir elementai, kurie čia nenurodyti. Sužinokite daugiau apie &lt;a href="<ph name="URL" />"&gt;apsaugą nuo nepageidaujamos programinės įrangos&lt;/a&gt; „Chrome“ privatumo baltojoje knygoje.</translation>
 <translation id="93480724622239549">Riktas arba klaida</translation>
 <translation id="935854577147268200">„Smart Lock“ telefonas pakeistas. Įveskite slaptažodį, kad atnaujintumėte „Smart Lock“. Kitą kartą telefonu bus galima atrakinti „<ph name="DEVICE_TYPE" />“. Funkciją „Smart Lock“ galite išjungti „Nustatymų“ skiltyje.</translation>
-<translation id="93610034168535821">Iš viso svetainių naudojamos vietos saugykloje:</translation>
 <translation id="936646668635477464">Fotoaparatas ir mikrofonas</translation>
 <translation id="936801553271523408">Sistemos diagnostikos duomenys</translation>
 <translation id="93766956588638423">Pataisyti plėtinį</translation>
diff --git a/chrome/app/resources/generated_resources_lv.xtb b/chrome/app/resources/generated_resources_lv.xtb
index f04fcd9..9e3b6e01 100644
--- a/chrome/app/resources/generated_resources_lv.xtb
+++ b/chrome/app/resources/generated_resources_lv.xtb
@@ -8419,7 +8419,6 @@
 <translation id="934503638756687833">Ja nepieciešams, tiks noņemti arī vienumi, kas nav norādīti šajā sarakstā. Lai uzzinātu vairāk par &lt;a href="<ph name="URL" />"&gt;aizsardzību pret nevēlamu programmatūru&lt;/a&gt;, skatiet Chrome konfidencialitātes tehnisko dokumentu.</translation>
 <translation id="93480724622239549">Kļūda</translation>
 <translation id="935854577147268200">Smart Lock tālrunis ir mainīts. Ievadiet paroli, lai atjauninātu Smart Lock. Nākamajā reizē šīs ierīces <ph name="DEVICE_TYPE" /> atbloķēšanai tiks izmantots jūsu tālrunis. Iestatījumos varat izslēgt Smart Lock.</translation>
-<translation id="93610034168535821">Kopējais krātuves apjoms, ko izmanto vietnes:</translation>
 <translation id="936646668635477464">Kamera un mikrofons</translation>
 <translation id="936801553271523408">Sistēmas diagnostikas dati</translation>
 <translation id="93766956588638423">Labot paplašinājumu</translation>
diff --git a/chrome/app/resources/generated_resources_mk.xtb b/chrome/app/resources/generated_resources_mk.xtb
index f495da7..06be13d 100644
--- a/chrome/app/resources/generated_resources_mk.xtb
+++ b/chrome/app/resources/generated_resources_mk.xtb
@@ -8448,7 +8448,6 @@
 <translation id="934503638756687833">Ставките што не се наведени тука исто така ќе се отстранат ако е потребно. Дознајте повеќе за &lt;a href="<ph name="URL" />"&gt;заштита од несакан софтвер&lt;/a&gt; во белата книга за приватност на Chrome.</translation>
 <translation id="93480724622239549">Мала или голема грешка</translation>
 <translation id="935854577147268200">Телефонот за Smart Lock е сменет. Внесете ја вашата лозинка за да се ажурира Smart Lock. Следниот пат, телефонот ќе го отклучи вашиот <ph name="DEVICE_TYPE" />. Smart Lock може да се исклучи во „Поставки“.</translation>
-<translation id="93610034168535821">Вкупен капацитет искористен од сајтовите:</translation>
 <translation id="936646668635477464">Камера и микрофон</translation>
 <translation id="936801553271523408">Дијагностички податоци на системот</translation>
 <translation id="93766956588638423">Поправи ја екстензијата</translation>
diff --git a/chrome/app/resources/generated_resources_ml.xtb b/chrome/app/resources/generated_resources_ml.xtb
index 0ac47803..c1c76f37 100644
--- a/chrome/app/resources/generated_resources_ml.xtb
+++ b/chrome/app/resources/generated_resources_ml.xtb
@@ -2224,6 +2224,7 @@
 <translation id="3067198360141518313">ഈ പ്ലഗിന്‍ പ്രവര്‍ത്തിപ്പിക്കുക</translation>
 <translation id="3071624960923923138">പുതിയ ടാബ് തുറക്കാൻ ഇവിടെ ക്ലിക്ക് ചെയ്യാം</translation>
 <translation id="3072775339180057696"><ph name="FILE_NAME" /> കാണാൻ സൈറ്റിനെ അനുവദിക്കണോ?</translation>
+<translation id="3074499504015191586">മുഴുവൻ പേജും വിവർത്തനം ചെയ്യുക</translation>
 <translation id="3075874217500066906">പവർവാഷ് പ്രോസസ്സ് ആരംഭിക്കുന്നതിന് പുനരാരംഭിക്കേണ്ടതുണ്ട്. പുനരാരംഭിച്ചതിന് ശേഷം തുടരേണ്ടതുണ്ടോയെന്ന് സ്ഥിരീകരിക്കാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">ഈ ഉപകരണത്തിൽ മാത്രം സംരക്ഷിക്കുക</translation>
@@ -5079,6 +5080,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> നിങ്ങളുടെ ക്യാമറയും മൈക്രോഫോണും ഉപയോഗിക്കുന്നു</translation>
 <translation id="5935158534896975820">സര്‍ട്ടിഫിക്കറ്റ് സൈനിംഗ് അഭ്യർത്ഥന തയ്യാറാക്കുന്നു (സെർവറിൽ കാത്തിരിക്കുന്നു)</translation>
 <translation id="5935656526031444304">സുരക്ഷിത ബ്രൗസിംഗ് മാനേജ് ചെയ്യുക</translation>
+<translation id="5936065461722368675">മുഴുവൻ പേജും വിവർത്തനം ചെയ്യുക</translation>
 <translation id="5938002010494270685">സുരക്ഷാ അപ്ഗ്രേഡ് ലഭ്യമാണ്</translation>
 <translation id="5939518447894949180">റീസെറ്റ് ചെയ്യുക</translation>
 <translation id="5939719276406088041">കുറുക്കുവഴി സൃഷ്‌ടിക്കാനാകില്ല</translation>
@@ -8422,7 +8424,6 @@
 <translation id="934503638756687833">ആവശ്യമെങ്കിൽ, ഇവിടെ ലിസ്‌റ്റ് ചെയ്യപ്പെടാത്ത ഇനങ്ങളും നീക്കം ചെയ്യപ്പെടും. &lt;a href="<ph name="URL" />"&gt;അനാവശ്യ സോഫ്‌റ്റ്‌വെയർ പരിരക്ഷയെ&lt;/a&gt; കുറിച്ച് Chrome സ്വകാര്യതാ വൈറ്റ് പേപ്പറിൽ കൂടുതലറിയുക.</translation>
 <translation id="93480724622239549">ബഗ് അല്ലെങ്കിൽ പിശക്</translation>
 <translation id="935854577147268200">Smart Lock ഫോൺ മാറ്റി. Smart Lock അപ്‌ഡേറ്റ് ചെയ്യാൻ നിങ്ങളുടെ പാസ്‌വേഡ് നൽകുക. അടുത്ത തവണ, നിങ്ങളുടെ <ph name="DEVICE_TYPE" /> ഫോൺ അൺലോക്ക് ചെയ്യും. ക്രമീകരണത്തിൽ Smart Lock ഓഫാക്കാം</translation>
-<translation id="93610034168535821">സൈറ്റുകൾ ഉപയോഗിച്ച മൊത്തം സ്റ്റോറേജ്:</translation>
 <translation id="936646668635477464">ക്യാമറയും മൈക്രോഫോണും</translation>
 <translation id="936801553271523408">സിസ്റ്റം ഡയഗണോസ്റ്റിക് ഡാറ്റ</translation>
 <translation id="93766956588638423">വിപുലീകരണം റിപ്പയർ ചെയ്യുക</translation>
diff --git a/chrome/app/resources/generated_resources_mn.xtb b/chrome/app/resources/generated_resources_mn.xtb
index 3626e36..e8a732b 100644
--- a/chrome/app/resources/generated_resources_mn.xtb
+++ b/chrome/app/resources/generated_resources_mn.xtb
@@ -8432,7 +8432,6 @@
 <translation id="934503638756687833">Энд жагсаагаагүй зүйлсийг шаардлагатай бол устгаж болно. Chrome-н нууцлалын цагаан хуудаснаас &lt;a href="<ph name="URL" />"&gt;хүсээгүй программ хангамжийн хамгаалалтын&lt;/a&gt; талаар дэлгэрэнгүй үзнэ үү.</translation>
 <translation id="93480724622239549">Алдаа эсвэл гэмтэл</translation>
 <translation id="935854577147268200">Smart Lock-н утсыг өөрчилсөн байна. Smart Lock-г шинэчлэхийн тулд нууц үгээ оруулна уу. Дараагийн удаа таны утас таны <ph name="DEVICE_TYPE" />-н түгжээг тайлна. Та Smart Lock-г Тохиргоонд унтрааж болно</translation>
-<translation id="93610034168535821">Сайтуудын ашиглаж байгаа хадгалах сангийн нийт хэмжээ:</translation>
 <translation id="936646668635477464">Камер болон микрофон</translation>
 <translation id="936801553271523408">Системийн оношлогоотой холбоотой өгөгдөл</translation>
 <translation id="93766956588638423">Өргөтгөлийг засах</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 5d20bd495..c49750e 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -8437,7 +8437,6 @@
 <translation id="934503638756687833">आवश्‍यक असल्‍यास, येथे सूचीत नसलेले आयटम देखील काढून टाकले जातील. Chrome गोपनीयता व्‍हाइट पेपरमध्‍ये &lt;a href="<ph name="URL" />"&gt; नको असलेल्या सॉफ्टवेअर संरक्षण&lt;/a&gt; बद्दल अधिक जाणून घ्‍या.</translation>
 <translation id="93480724622239549">बग किंवा एरर</translation>
 <translation id="935854577147268200">Smart Lock फोन बदलला आहे. Smart Lock अपडेट करण्यासाठी तुमचा पासवर्ड एंटर करा. पुढील वेळेस तुमचा फोन तुमचे <ph name="DEVICE_TYPE" /> अनलॉक करेल. तुम्ही सेटिंग्जमधून Smart Lock बंद करू शकता</translation>
-<translation id="93610034168535821">साइटनी वापरलेले एकूण स्टोरेज:</translation>
 <translation id="936646668635477464">कॅमेरा आणि मायक्रोफोन</translation>
 <translation id="936801553271523408">सिस्टम निदान डेटा</translation>
 <translation id="93766956588638423">एक्स्टेंशन दुरुस्त करा</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb
index 4868532..3d6cf2c 100644
--- a/chrome/app/resources/generated_resources_ms.xtb
+++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -8441,7 +8441,6 @@
 <translation id="934503638756687833">Item yang tidak disenaraikan di sini turut akan dialih keluar, jika perlu. Ketahui lebih lanjut tentang &lt;a href="<ph name="URL" />"&gt;perlindungan daripada perisian yang tidak diingini&lt;/a&gt; dalam kertas putih privasi Chrome.</translation>
 <translation id="93480724622239549">Pepijat atau Ralat</translation>
 <translation id="935854577147268200">Telefon Smart Lock ditukar. Masukkan kata laluan anda untuk mengemas kini Smart Lock. Selepas ini, telefon anda akan membuka kunci <ph name="DEVICE_TYPE" /> anda. Anda boleh mematikan Smart Lock dalam Tetapan</translation>
-<translation id="93610034168535821">Jumlah storan yang digunakan oleh tapak:</translation>
 <translation id="936646668635477464">Kamera &amp; mikrofon</translation>
 <translation id="936801553271523408">Data diagnostik sistem</translation>
 <translation id="93766956588638423">Baiki sambungan</translation>
diff --git a/chrome/app/resources/generated_resources_my.xtb b/chrome/app/resources/generated_resources_my.xtb
index e4172cdd..c182938 100644
--- a/chrome/app/resources/generated_resources_my.xtb
+++ b/chrome/app/resources/generated_resources_my.xtb
@@ -8434,7 +8434,6 @@
 <translation id="934503638756687833">လိုအပ်လျှင် ဤနေရာတွင် ဖော်ပြမထားသော အရာများကို ဖယ်ရှားလိုက်ပါမည်။ &lt;a href="<ph name="URL" />"&gt;မလိုလားအပ်သည့် ဆော့ဖ်ဝဲမှ ကာကွယ်မှု&lt;/a&gt; အကြောင်း ပိုမိုလေ့လာရန် Chrome ပုဂ္ဂိုလ်ရေးဆိုင်ရာ စက္ကူဖြူမူဝါဒတွင် ကြည့်ပါ။</translation>
 <translation id="93480724622239549">ချွတ်ယွင်းမှု (သို့) အမှားအယွင်း</translation>
 <translation id="935854577147268200">Smart Lock ဖုန်း ပြောင်းသွားပါပြီ။ Smart Lock ကို အပ်ဒိတ်လုပ်ရန် စကားဝှက်ထည့်ပါ။ နောက်တစ်ကြိမ်တွင် သင့်ဖုန်းသည် <ph name="DEVICE_TYPE" /> ကို လော့ခ်ဖွင့်ပေးပါမည်။ Smart Lock ကို 'ဆက်တင်များ' တွင် ပိတ်နိုင်သည်</translation>
-<translation id="93610034168535821">ဝဘ်ဆိုက်များက အသုံးပြုထားသည့် စုစုပေါင်းသိုလှောင်ခန်း-</translation>
 <translation id="936646668635477464">ကင်မရာနှင့် မိုက်ခရိုဖုန်း</translation>
 <translation id="936801553271523408">စနစ် ချွတ်ယွင်းချက် စူးစမ်းမှု ဒေတာ</translation>
 <translation id="93766956588638423">ပရိုဂရမ်အဆက်အား ပြင်ဆင်ရန်</translation>
diff --git a/chrome/app/resources/generated_resources_ne.xtb b/chrome/app/resources/generated_resources_ne.xtb
index 96c4c69..58fe662 100644
--- a/chrome/app/resources/generated_resources_ne.xtb
+++ b/chrome/app/resources/generated_resources_ne.xtb
@@ -8412,7 +8412,6 @@
 <translation id="934503638756687833">आवश्यक परेका खण्डमा यहाँ सूचीबद्ध नगरिएका वस्तुहरूलाई हटाउन पनि सकिने छ। Chrome को गोपनीयतासम्बन्धी श्वेतपत्रमा गई &lt;a href="<ph name="URL" />"&gt;अवाञ्छित सफ्टवेयरबाट सुरक्षा&lt;/a&gt; बारे थप जान्नुहोस्।</translation>
 <translation id="93480724622239549">त्रुटि</translation>
 <translation id="935854577147268200">Smart Lock रहेको फोन परिवर्तन गरियो। Smart Lock अद्यावधिक गर्न आफ्नो पासवर्ड प्रविष्टि गर्नुहोस्। अर्को पटकदेखि, तपाईंको फोनले तपाईंको <ph name="DEVICE_TYPE" />अनलक गर्ने छ। तपाईं सेटिङहरूमा गई Smart Lock निष्क्रिय पार्न सक्नुहुन्छ</translation>
-<translation id="93610034168535821">साइटहरूले प्रयोग गरेको कुल भण्डारण:</translation>
 <translation id="936646668635477464">क्यामेरा र माइक्रोफोन</translation>
 <translation id="936801553271523408">प्रणाली विकर्ण लगत</translation>
 <translation id="93766956588638423">विस्तार मर्मत गर्नुहोस्</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb
index b39025a..3871005 100644
--- a/chrome/app/resources/generated_resources_nl.xtb
+++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -8417,7 +8417,6 @@
 <translation id="934503638756687833">Items die hier niet worden vermeld, worden zo nodig ook verwijderd. Lees meer informatie over &lt;a href="<ph name="URL" />"&gt;bescherming tegen ongewenste software&lt;/a&gt; in de whitepaper over privacy in Chrome.</translation>
 <translation id="93480724622239549">Bug of fout</translation>
 <translation id="935854577147268200">Telefoon voor Smart Lock gewijzigd. Geef je wachtwoord op om Smart Lock te updaten. De volgende keer wordt je <ph name="DEVICE_TYPE" /> ontgrendeld met je telefoon. Je kunt Smart Lock uitzetten in Instellingen.</translation>
-<translation id="93610034168535821">Totale opslagruimte gebruikt door sites:</translation>
 <translation id="936646668635477464">Camera en microfoon</translation>
 <translation id="936801553271523408">Diagnostische systeemgegevens</translation>
 <translation id="93766956588638423">Extensie repareren</translation>
diff --git a/chrome/app/resources/generated_resources_no.xtb b/chrome/app/resources/generated_resources_no.xtb
index ee56965..0a0ac7be 100644
--- a/chrome/app/resources/generated_resources_no.xtb
+++ b/chrome/app/resources/generated_resources_no.xtb
@@ -8429,7 +8429,6 @@
 <translation id="934503638756687833">Elementer som ikke er oppført her, blir også fjernet ved behov. Du kan finne ut mer om &lt;a href="<ph name="URL" />"&gt;beskyttelse mot uønsket programvare&lt;/a&gt; i det tekniske dokumentet om personvern i Chrome.</translation>
 <translation id="93480724622239549">Feil</translation>
 <translation id="935854577147268200">Smart Lock-telefonen er endret. Skriv inn passordet ditt for å oppdatere Smart Lock. Neste gang låser telefonen opp <ph name="DEVICE_TYPE" />-enheten din. Du kan slå av Smart Lock i innstillingene</translation>
-<translation id="93610034168535821">Total mengde lagring som brukes av nettsteder:</translation>
 <translation id="936646668635477464">Kamera og mikrofon</translation>
 <translation id="936801553271523408">Systemdiagnostikkdata</translation>
 <translation id="93766956588638423">Reparer utvidelsen</translation>
diff --git a/chrome/app/resources/generated_resources_or.xtb b/chrome/app/resources/generated_resources_or.xtb
index baa40fe..8d70496 100644
--- a/chrome/app/resources/generated_resources_or.xtb
+++ b/chrome/app/resources/generated_resources_or.xtb
@@ -1541,6 +1541,7 @@
 <translation id="2433836460518180625">କେବଳ ଡିଭାଇସ୍‌‌କୁ ଅନ୍‌ଲକ୍ କରନ୍ତୁ</translation>
 <translation id="2434449159125086437">ପ୍ରିଣ୍ଟର୍ ସେଟ୍ ଅପ୍ କରିବାକୁ ଅକ୍ଷମ। ଦୟାକରି କନ୍‌ଫିଗ୍‌ରେସନ୍ ଯାଞ୍ଚ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="2434758125294431199">ଆପଣଙ୍କ ସହ କିଏ ସେୟାର୍ କରିପାରିବେ, ତାହା ଚୟନ କରନ୍ତୁ</translation>
+<translation id="2434915728183570229">ଆପଣ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ଆପ୍ସକୁ ଦେଖିପାରିବେ</translation>
 <translation id="2435137177546457207">Google Chrome ଏବଂ ChromeOS Flexର ଅତିରିକ୍ତ ସର୍ତ୍ତାବଳୀ</translation>
 <translation id="2435248616906486374">ନେଟ୍‍ୱର୍କ ବିଚ୍ଛିନ୍ନ ହୋ‍ଇଯାଇଛି।</translation>
 <translation id="2435457462613246316">ପାସୱାର୍ଡ ଦେଖାନ୍ତୁ</translation>
@@ -4224,6 +4225,7 @@
 <translation id="5072900412896857127">Google Play ସେବାର ସର୍ତ୍ତାବଳୀ ଲୋଡ୍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ଆପଣଙ୍କ ନେଟୱାର୍କ ସଂଯୋଗ ଯାଞ୍ଚ କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" />, ଏବଂ ଅଧିକ #ଟି}}</translation>
 <translation id="5074318175948309511">ନୂତନ ସେଟିଂସ୍ ପ୍ରଭାବ ପକାଇବା ପୂର୍ବରୁ ଏହି ପୃଷ୍ଠାକୁ ହୁଏତ ପୁଣି ଲୋଡ୍ କରିବା ଆବଶ୍ୟକ।</translation>
+<translation id="5074761966806028321">ସେଟଅପ ସମ୍ପୂର୍ଣ୍ଣ କରିବା ପାଇଁ ଏବେ ବି ଅନୁମତି ଆବଶ୍ୟକ</translation>
 <translation id="5075910247684008552">ସୁରକ୍ଷିତ ସାଇଟ୍‍ଗୁଡ଼ିକରେ ଅସୁରକ୍ଷିତ ବିଷୟବସ୍ତୁକୁ ଡିଫଲ୍ଟ ଭାବେ ବ୍ଲକ୍ କରାଯାଇଛି</translation>
 <translation id="5078638979202084724">ସମସ୍ତ ଟାବ୍‌କୁ ବୁକ୍‌ମାର୍କ କରନ୍ତୁ</translation>
 <translation id="5078796286268621944">ଭୁଲ ପିନ୍</translation>
@@ -4587,6 +4589,7 @@
 <translation id="5449551289610225147">ଅବୈଧ ପାସ୍‌ୱର୍ଡ</translation>
 <translation id="5449588825071916739">ସମସ୍ତ ଟାବ୍‌କୁ ବୁକ୍‌ମାର୍କ କରନ୍ତୁ</translation>
 <translation id="5449716055534515760">Win&amp;dow ବନ୍ଦ କରନ୍ତୁ</translation>
+<translation id="5452446625764825792">ଆପଣ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ବର୍ତ୍ତମାନର ଫଟୋ, ମିଡିଆ ଏବଂ ଆପ୍ସକୁ ଦେଖିପାରିବେ</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (ଅଫଲାଇନରେ କାମ କରେ)</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" />ଙ୍କ ସହିତ</translation>
 <translation id="545484289444831485">ଅଧିକ ସନ୍ଧାନ ଫଳାଫଳ ଦେଖନ୍ତୁ</translation>
@@ -4647,6 +4650,7 @@
 <translation id="5499211612787418966">ବର୍ତ୍ତମାନ ଏହି ଡାଏଲଗକୁ ଫୋକସ୍ କରାଯାଇନାହିଁ। ଏହି ଡାଏଲଗକୁ ଫୋକସ୍ କରିବା ପାଇଁ Alt-Shift A ଦବାନ୍ତୁ।</translation>
 <translation id="5499313591153584299">ଏହି ଫାଇଲ୍ ଆପଣଙ୍କର କମ୍ପ୍ୟୁଟର୍ ପାଇଁ କ୍ଷତିକାରକ ହୋଇପାରେ।</translation>
 <translation id="5499453227627332024">ଆପଣଙ୍କ Linux କଣ୍ଟେନର୍ ପାଇଁ ଏକ ଅପଗ୍ରେଡ୍ ଉପଲବ୍ଧ ଅଛି। ଆପଣ ପରେ ସେଟିଂସ୍ ଆପରୁ ମଧ୍ୟ ଅପଗ୍ରେଡ୍ କରିପାରିବେ।</translation>
+<translation id="5499476581866658341">ଆପଣ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ବର୍ତ୍ତମାନର ଫଟୋ ଏବଂ ମିଡିଆକୁ ଦେଖିପାରିବେ</translation>
 <translation id="549957179819296104">ନୂଆ ଆଇକନ୍</translation>
 <translation id="5500168250243071806">ଆପଣ ସାଇନ୍ ଇନ୍ କରିଥିବା ବେଳେ <ph name="BEGIN_LINK_SEARCH" />ସନ୍ଧାନ ଇତିହାସ<ph name="END_LINK_SEARCH" /> ଏବଂ <ph name="BEGIN_LINK_GOOGLE" />ଅନ୍ୟ ପ୍ରକାରର କାର୍ଯ୍ୟକଳାପ<ph name="END_LINK_GOOGLE" /> ଆପଣଙ୍କ Google ଆକାଉଣ୍ଟରେ ସେଭ୍ ହୋଇପାରେ। ଆପଣ ସେଗୁଡ଼ିକୁ ଯେ କୌଣସି ସମୟରେ ଡିଲିଟ୍ କରିପାରିବେ।</translation>
 <translation id="5500709606820808700">ସୁରକ୍ଷା ଯାଞ୍ଚ ଆଜି ଚାଲିଥିଲା</translation>
@@ -6310,6 +6314,7 @@
 <translation id="7152478047064750137">ଏହି ଏକ୍ସଟେନ୍‍ସନ୍‍ ପାଇଁ କୌଣସି ବିଶେଷ ଅନୁମତିର ଆବଶ୍ୟକତା ନାହିଁ</translation>
 <translation id="7154130902455071009">ଆପଣଙ୍କ ପ୍ରାରମ୍ଭ ପୃଷ୍ଠାକୁ ଏଥିରେ ପରିବର୍ତ୍ତନ କରନ୍ତୁ: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">କ୍ୟାମେରା କିମ୍ବା ଫାଇଲ୍‍‍ରେ ବିଦ୍ୟମାନ ଥିବା ଫଟୋ</translation>
+<translation id="7160182524506337403">ଆପଣ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଦେଖିପାରିବେ</translation>
 <translation id="7163202347044721291">ସକ୍ରିୟକରଣ କୋଡକୁ ଯାଞ୍ଚ କରାଯାଉଛି…</translation>
 <translation id="716640248772308851">ଚେକ୍ କରାଯିଥିବା ଲୋକେସନ୍‌ଗୁଡ଼ିକରେ "<ph name="EXTENSION" />" ଛବି, ଭିଡିଓ ଓ ସାଉଣ୍ଡ୍ ଫାଇଲ୍‌ଗୁଡ଼ିକୁ ପଢ଼ିପାରିବ।</translation>
 <translation id="7167486101654761064">&amp;ସର୍ବଦା ଏହି ପ୍ରକାରର ଫାଇଲଗୁଡିକୁ ଖୋଲନ୍ତୁ</translation>
@@ -7322,6 +7327,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> ସ୍ଥିତି</translation>
 <translation id="8139447493436036221">Google Drive ଫାଇଲଗୁଡ଼ିକ</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">ଆପଣ ଫୋନ ହବ ସେଟିଂସରେ ଅଧିକ ଫିଚର ସେଟ ଅପ କରିପାରିବେ</translation>
 <translation id="8141584439523427891">ବର୍ତ୍ତମାନ ବିକଳ୍ପ ବ୍ରାଉଜର୍‌ରେ ଖୋଲୁଛି</translation>
 <translation id="8141725884565838206">ଆପଣଙ୍କର ପାସ୍‌ୱର୍ଡଗୁଡ଼ିକ ପରିଚାଳିତ କରନ୍ତୁ</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{ଏକ ଭିଡିଓ}other{#ଟି ଭିଡିଓ}}</translation>
@@ -7529,6 +7535,7 @@
 <translation id="833986336429795709">ଏହି ଲିଙ୍କ୍‌କୁ ଖୋଲିବା ପାଇଁ, ଏକ ଆପ୍ ବାଛନ୍ତୁ</translation>
 <translation id="8342221978608739536">ବ୍ୟବହାର କରାଯାଇନାହିଁ</translation>
 <translation id="8342861492835240085">ଏକ ସଂଗ୍ରହ ବାଛନ୍ତୁ</translation>
+<translation id="8345848587667658367">ଆପଣ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ବର୍ତ୍ତମାନର ଫଟୋ, ମିଡିଆ, ବିଜ୍ଞପ୍ତି ଏବଂ ଆପ୍ସକୁ ଦେଖିପାରିବେ</translation>
 <translation id="8347227221149377169">ପ୍ରିଣ୍ଟ ଜବ୍</translation>
 <translation id="834785183489258869">ଇନକଗ୍ନିଟୋ ମୋଡରେ ଥିବା ସମୟରେ, ବିଜ୍ଞାପନଗୁଡ଼ିକୁ ପର୍ସନାଲାଇଜ୍ କରିବା ପରି ବିଭିନ୍ନ ସାଇଟରେ ଆପଣଙ୍କ ବ୍ରାଉଜିଂ କାର୍ଯ୍ୟକଳାପକୁ ଦେଖିବା ନିମନ୍ତେ ସାଇଟଗୁଡ଼ିକ କୁକୀଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିପାରିବ ନାହିଁ। କିଛି ସାଇଟରେ ଫିଚରଗୁଡ଼ିକ କାମ କରିନପାରେ।</translation>
 <translation id="8350789879725387295">ଡକରେ ଷ୍ଟାଇଲସ୍ ଟୁଲଗୁଡ଼ିକ</translation>
@@ -8134,6 +8141,7 @@
 <translation id="8957757410289731985">ପ୍ରୋଫାଇଲକୁ କଷ୍ଟମାଇଜ୍ କରନ୍ତୁ</translation>
 <translation id="895944840846194039">JavaScript ମେମୋରୀ</translation>
 <translation id="8960208913905765425">କ୍ୱିକ୍ ଉତ୍ତରଗୁଡ଼ିକର ୟୁନିଟ୍ ରୂପାନ୍ତର</translation>
+<translation id="8960638196855923532">ଆପଣ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ବିଜ୍ଞପ୍ତି ଏବଂ ଆପ୍ସକୁ ଦେଖିପାରିବେ</translation>
 <translation id="8962051932294470566">ଆପଣ ଏକ ସମୟରେ କେବଳ ଗୋଟିଏ ଫାଇଲ୍ ସେୟାର୍ କରିପାରିବେ। ବର୍ତ୍ତମାନର ସ୍ଥାନାନ୍ତର ଶେଷ ହେବା ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
 <translation id="8962083179518285172">ବିବରଣୀଗୁଡିକୁ ଲୁଚାନ୍ତୁ</translation>
 <translation id="8962918469425892674">ଏହି ସାଇଟ୍ ମୋସନ୍ କିମ୍ବା ଲାଇଟ୍ ସେନସର୍ ବ୍ୟବହାର କରୁଛି।</translation>
@@ -8285,6 +8293,7 @@
 <translation id="9103868373786083162">ଇତିବୃତ୍ତି ଦେଖିବାକୁ ଦୟାକରି ପ୍ରସଙ୍ଗ ମେନୁକୁ ଫେରନ୍ତୁ</translation>
 <translation id="9108035152087032312">ୱିଣ୍ଡୋର ନାମ ଦିଅନ୍ତୁ...</translation>
 <translation id="9108072915170399168">ଡାଟା ବ୍ୟବହାରର ବର୍ତ୍ତମାନ ସେଟିଂ "ବିନା ଇଣ୍ଟର୍ନେଟ୍"ରେ ସେଟ୍ ହୋଇଛି</translation>
+<translation id="9108294543511800041">ଆପଣ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଫୋନରେ ଥିବା ବର୍ତ୍ତମାନର ଫଟୋ, ମିଡିଆ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଦେଖିପାରିବେ</translation>
 <translation id="9108674852930645435">ଆପଣଙ୍କ <ph name="DEVICE_TYPE" />ରେ ନୂଆ କଣ ଅଛି ତାହା ଏକ୍ସପ୍ଲୋର କର</translation>
 <translation id="9108808586816295166">ସୁରକ୍ଷିତ DNS ସବୁ ସମୟରେ ଉପଲବ୍ଧ ହୋଇନପାରେ</translation>
 <translation id="9109122242323516435">ସ୍ଥାନ ଖାଲି କରିବାକୁ, ଡିଭାଇସ୍‌ ଷ୍ଟୋରେଜ୍‌ରୁ ଫାଇଲ୍‌ ଡିଲିଟ୍‍ କରନ୍ତୁ।</translation>
@@ -8409,7 +8418,6 @@
 <translation id="934503638756687833">ଆବଶ୍ୟକ ହେଲେ, ଏଠାରେ ତାଲିକାଭୁକ୍ତ ନଥିବା ଆଇଟମ୍‍ଗୁଡ଼ିକୁ କାଢ଼ିଦିଆଯିବ। Chrome ଗୋପନୀୟତା ହ୍ୱାଇଟ୍ ପେପର୍‍‍ରେ &lt;a href="<ph name="URL" />"&gt;ଅବାଞ୍ଚିତ ସଫ୍ଟୱେର୍‍ରୁ ସୁରକ୍ଷା&lt;/a&gt; ବିଷୟରେ ଅଧିକ ଜାଣନ୍ତୁ।</translation>
 <translation id="93480724622239549">ବଗ୍ କିମ୍ବା ତ୍ରୁଟି</translation>
 <translation id="935854577147268200">ସ୍ମାର୍ଟ ଲକ୍ ଫୋନ୍ ବଦଳିଗଲା। ସ୍ମାର୍ଟ ଲକ୍‌କୁ ଅପ୍‌ଡେଟ୍ କରିବା ପାଇଁ ଆପଣଙ୍କର ପାସ୍‌ୱର୍ଡ ଲେଖନ୍ତୁ। ପରବର୍ତ୍ତୀ ସମୟରେ, ଆପଣଙ୍କର ଫୋନ୍‌ ଆପଣଙ୍କ <ph name="DEVICE_TYPE" /> ଅନ୍‌ଲକ୍‌ କରିବ।ସେଟିଂସ୍‌ରେ ଆପଣ ସ୍ମାର୍ଟ ଲକ୍‌ ପରିବର୍ତ୍ତନ କରିପାରିବେ</translation>
-<translation id="93610034168535821">ସାଇଟଗୁଡ଼ିକ ଦ୍ୱାରା ବ୍ୟବହାର କରାଯାଇଥିବା ମୋଟ ଷ୍ଟୋରେଜ୍:</translation>
 <translation id="936646668635477464">କ୍ୟାମେରା ଓ ମାଇକ୍ରୋଫୋନ୍</translation>
 <translation id="936801553271523408">ସିଷ୍ଟମ୍ ଡାଏଗ୍ନୋଷ୍ଟିକ୍ ଡାଟା</translation>
 <translation id="93766956588638423">ଏକ୍ସଟେନ୍‌ସନ୍ ମରାମତି କରନ୍ତୁ</translation>
diff --git a/chrome/app/resources/generated_resources_pa.xtb b/chrome/app/resources/generated_resources_pa.xtb
index 03e6738..fb361266 100644
--- a/chrome/app/resources/generated_resources_pa.xtb
+++ b/chrome/app/resources/generated_resources_pa.xtb
@@ -1559,6 +1559,7 @@
 <translation id="2433836460518180625">ਸਿਰਫ਼ ਡੀਵਾਈਸ ਅਣਲਾਕ ਕਰੋ</translation>
 <translation id="2434449159125086437">ਪ੍ਰਿੰਟਰ ਦਾ ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਸੰਰੂਪਣ ਦੀ ਜਾਂਚ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
 <translation id="2434758125294431199">ਚੁਣੋ ਕਿ ਤੁਹਾਡੇ ਨਾਲ ਕੌਣ ਸਾਂਝਾ ਕਰ ਸਕਦਾ ਹੈ</translation>
+<translation id="2434915728183570229">ਤੁਸੀਂ ਹੁਣ ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹੋ</translation>
 <translation id="2435137177546457207">Google Chrome ਅਤੇ ChromeOS Flex ਦੇ ਵਧੀਕ ਨਿਯਮ</translation>
 <translation id="2435248616906486374">ਨੈੱਟਵਰਕ ਡਿਸਕਨੈਕਟ ਕੀਤਾ</translation>
 <translation id="2435457462613246316">ਪਾਸਵਰਡ ਵੇਖੋ</translation>
@@ -4243,6 +4244,7 @@
 <translation id="5072900412896857127">Google Play ਦੇ ਸੇਵਾ ਦੇ ਨਿਯਮਾਂ ਨੂੰ ਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦੀ ਜਾਂਚ ਕਰਕੇ ਮੁੜ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}one{<ph name="FILE1" />, <ph name="FILE2" />, ਅਤੇ # ਹੋਰ}other{<ph name="FILE1" />, <ph name="FILE2" />, ਅਤੇ # ਹੋਰ}}</translation>
 <translation id="5074318175948309511">ਇਹ ਪੰਨਾਂ ਨਵੀਆਂ ਸੈਟਿੰਗਾਂ ਦੇ ਲਾਗੂ ਹੋਣ ਤੋਂ ਪਹਿਲਾਂ ਦੁਬਾਰਾ ਲੋਡ ਕੀਤੇ ਜਾਣ ਦੀ ਲੋੜ ਹੋ ਸਕਦੀ ਹੈ।</translation>
+<translation id="5074761966806028321">ਸੈੱਟਅੱਪ ਪੂਰਾ ਕਰਨ ਲਈ ਹਾਲੇ ਵੀ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ</translation>
 <translation id="5075910247684008552">ਅਸੁਰੱਖਿਅਤ ਸਮੱਗਰੀ ਨੂੰ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੌਰ 'ਤੇ ਸੁਰੱਖਿਅਤ ਸਾਈਟਾਂ 'ਤੇ ਬਲਾਕ ਕੀਤਾ ਜਾਂਦਾ ਹੈ</translation>
 <translation id="5078638979202084724">ਸਾਰੀਆਂ ਟੈਬਾਂ ਨੂੰ ਬੁੱਕਮਾਰਕ ਕਰੋ</translation>
 <translation id="5078796286268621944">ਗ਼ਲਤ PIN</translation>
@@ -4606,6 +4608,7 @@
 <translation id="5449551289610225147">ਅਵੈਧ ਪਾਸਵਰਡ</translation>
 <translation id="5449588825071916739">ਸਾਰੀਆਂ ਟੈਬਾਂ ਨੂੰ ਬੁੱਕਮਾਰਕ ਕਰੋ</translation>
 <translation id="5449716055534515760">Win&amp;dow ਬੰਦ ਕਰੋ</translation>
+<translation id="5452446625764825792">ਤੁਸੀਂ ਹੁਣ ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਹਾਲੀਆ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਐਪਾਂ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹੋ</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (ਆਫ਼ਲਾਈਨ ਕੰਮ ਕਰਦੀ ਹੈ)</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" /> ਨਾਲ</translation>
 <translation id="545484289444831485">ਹੋਰ ਖੋਜ ਨਤੀਜੇ ਦੇਖੋ</translation>
@@ -4666,6 +4669,7 @@
 <translation id="5499211612787418966">ਇਹ ਵਿੰਡੋ ਫ਼ਿਲਹਾਲ ਫੋਕਸ ਵਿੱਚ ਨਹੀਂ ਹੈ। ਇਸ ਵਿੰਡੋ 'ਤੇ ਫੋਕਸ ਕਰਨ ਲਈ Alt-Shift A ਦਬਾਓ।</translation>
 <translation id="5499313591153584299">ਇਹ ਫ਼ਾਈਲ ਤੁਹਾਡੇ ਕੰਪਿਊਟਰ 'ਤੇ ਹਾਨੀਕਾਰਕ ਹੋ ਸਕਦੀ ਹੈ।</translation>
 <translation id="5499453227627332024">ਤੁਹਾਡੇ Linux ਕੰਟੇਨਰ ਲਈ ਅੱਪਗ੍ਰੇਡ ਉਪਲਬਧ ਹੈ। ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ ਐਪ ਵਿੱਚ ਜਾ ਕੇ ਇਸਨੂੰ ਬਾਅਦ ਵਿੱਚ ਵੀ ਅੱਪਗ੍ਰੇਡ ਕਰ ਸਕਦੇ ਹੋ।</translation>
+<translation id="5499476581866658341">ਤੁਸੀਂ ਹੁਣ ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਹਾਲੀਆ ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹੋ</translation>
 <translation id="549957179819296104">ਨਵਾਂ ਪ੍ਰਤੀਕ</translation>
 <translation id="5500168250243071806">ਤੁਹਾਡੇ ਸਾਈਨ-ਇਨ ਹੋਣ 'ਤੇ, ਤੁਹਾਡੇ Google ਖਾਤੇ ਵਿੱਚ <ph name="BEGIN_LINK_SEARCH" />ਖੋਜ ਇਤਿਹਾਸ<ph name="END_LINK_SEARCH" /> ਅਤੇ <ph name="BEGIN_LINK_GOOGLE" />ਸਰਗਰਮੀ ਦੀਆਂ ਹੋਰ ਕਿਸਮਾਂ<ph name="END_LINK_GOOGLE" /> ਨੂੰ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। ਤੁਸੀਂ ਉਨ੍ਹਾਂ ਨੂੰ ਕਿਸੇ ਵੀ ਸਮੇਂ ਮਿਟਾ ਸਕਦੇ ਹੋ।</translation>
 <translation id="5500709606820808700">ਸੁਰੱਖਿਆ ਜਾਂਚ ਅੱਜ ਚਲਾਈ ਗਈ</translation>
@@ -6334,6 +6338,7 @@
 <translation id="7152478047064750137">ਇਸ ਐਕਸਟੈਂਸ਼ਨ ਲਈ ਕੋਈ ਖਾਸ ਇਜਾਜ਼ਤਾਂ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ</translation>
 <translation id="7154130902455071009">ਆਪਣਾ ਸਟਾਰਟ ਸਫ਼ਾ ਇਸ ਵਿੱਚ ਬਦਲੋ: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">ਕੈਮਰੇ ਜਾਂ ਫ਼ਾਈਲ ਤੋਂ ਮੌਜੂਦਾ ਫ਼ੋਟੋ</translation>
+<translation id="7160182524506337403">ਤੁਸੀਂ ਹੁਣ ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹੋ</translation>
 <translation id="7163202347044721291">ਕਿਰਿਆਸ਼ੀਲ ਕਰਨ ਲਈ ਕੋਡ ਦੀ ਪੁਸ਼ਟੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ...</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" ਸਹੀ ਦਾ ਨਿਸ਼ਾਨ ਲਗਾਏ ਹੋਏ ਨਿਰਧਾਰਿਤ ਸਥਾਨਾਂ ਵਿੱਚ ਚਿੱਤਰ, ਵੀਡਿਓ ਅਤੇ ਅਵਾਜ਼ ਫਾਈਲਾਂ ਪੜ੍ਹ ਸਕਦਾ ਹੈ।</translation>
 <translation id="7167486101654761064">&amp;ਹਮੇਸ਼ਾਂ ਇਸ ਪ੍ਰਕਾਰ ਦੀਆਂ ਫਾਈਲਾਂ ਖੋਲ੍ਹੋ</translation>
@@ -7347,6 +7352,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> ਸਥਿਤੀ</translation>
 <translation id="8139447493436036221">Google Drive ਫ਼ਾਈਲਾਂ</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">ਤੁਸੀਂ ਫ਼ੋਨ ਹੱਬ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਹੋਰ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦਾ ਸੈੱਟਅੱਪ ਕਰ ਸਕਦੇ ਹੋ</translation>
 <translation id="8141584439523427891">ਹੁਣ ਵਿਕਲਪਿਕ ਬ੍ਰਾਊਜ਼ਰ ਵਿੱਚ ਖੋਲ੍ਹਿਆ ਜਾ ਰਿਹਾ ਹੈ</translation>
 <translation id="8141725884565838206">ਆਪਣੇ ਪਾਸਵਰਡ ਵਿਵਸਥਿਤ ਕਰੋ</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{ਇੱਕ ਵੀਡੀਓ}one{# ਵੀਡੀਓ}other{# ਵੀਡੀਓ}}</translation>
@@ -7554,6 +7560,7 @@
 <translation id="833986336429795709">ਇਸ ਲਿੰਕ ਨੂੰ ਖੋਲ੍ਹਣ ਲਈ, ਕੋਈ ਐਪ ਚੁਣੋ</translation>
 <translation id="8342221978608739536">ਕੋਸ਼ਿਸ਼ ਨਹੀਂ ਕੀਤੀ</translation>
 <translation id="8342861492835240085">ਕੋਈ ਸੰਗ੍ਰਹਿ ਚੁਣੋ</translation>
+<translation id="8345848587667658367">ਤੁਸੀਂ ਹੁਣ ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਹਾਲੀਆ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ, ਸੂਚਨਾਵਾਂ ਅਤੇ ਐਪਾਂ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹੋ</translation>
 <translation id="8347227221149377169">ਪ੍ਰਿੰਟ ਜੌਬਾਂ</translation>
 <translation id="834785183489258869">ਇਨਕੋਗਨਿਟੋ ਵਿੱਚ ਹੋਣ ਵੇਲੇ, ਸਾਈਟਾਂ ਵੱਖ-ਵੱਖ ਸਾਈਟਾਂ ਵਿਚਲੀ ਤੁਹਾਡੀ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਰਗਰਮੀ ਦੇਖਣ ਲਈ ਕੁਕੀਜ਼ ਨੂੰ ਨਹੀਂ ਵਰਤ ਸਕਦੀਆਂ, ਉਦਾਹਰਨ ਲਈ, ਵਿਗਿਆਪਨਾਂ ਨੂੰ ਵਿਅਕਤੀਗਤ ਬਣਾਉਣ ਵਾਸਤੇ। ਸ਼ਾਇਦ ਕੁਝ ਸਾਈਟਾਂ 'ਤੇ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਕੰਮ ਨਾ ਕਰਨ।</translation>
 <translation id="8350789879725387295">ਡੌਕ ਵਿੱਚ ਸਟਾਈਲਸ ਟੂਲ</translation>
@@ -8160,6 +8167,7 @@
 <translation id="8957757410289731985">ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਵਿਉਂਤਬੱਧ ਕਰੋ</translation>
 <translation id="895944840846194039">JavaScript ਮੈਮਰੀ</translation>
 <translation id="8960208913905765425">ਤਤਕਾਲ ਜਵਾਬਾਂ ਦਾ ਇਕਾਈ ਰੂਪਾਂਤਰਨ</translation>
+<translation id="8960638196855923532">ਤੁਸੀਂ ਹੁਣ ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਅਤੇ ਐਪਾਂ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹੋ</translation>
 <translation id="8962051932294470566">ਤੁਸੀਂ ਇੱਕ ਸਮੇਂ 'ਤੇ ਸਿਰਫ਼ ਇੱਕ ਫ਼ਾਈਲ ਨੂੰ ਹੀ ਸਾਂਝਾ ਕਰ ਸਕਦੇ ਹੋ। ਮੌਜੂਦਾ ਟ੍ਰਾਂਸਫ਼ਰ ਪੂਰਾ ਹੋਣ 'ਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
 <translation id="8962083179518285172">ਵੇਰਵੇ ਲੁਕਾਓ</translation>
 <translation id="8962918469425892674">ਇਹ ਸਾਈਟ ਮੋਸ਼ਨ ਜਾਂ ਲਾਈਟ ਸੈਂਸਰਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।</translation>
@@ -8311,6 +8319,7 @@
 <translation id="9103868373786083162">ਇਤਿਹਾਸ ਦੇਖਣ ਲਈ ਪਿੱਛੇ ਜਾਓ, ਸੰਦਰਭੀ ਮੀਨੂ ਦਬਾਓ</translation>
 <translation id="9108035152087032312">&amp;ਵਿੰਡੋ ਦਾ ਨਾਮ ਰੱਖੋ...</translation>
 <translation id="9108072915170399168">ਮੌਜੂਦਾ ਡਾਟਾ ਵਰਤੋਂ ਸੈਟਿੰਗ 'ਇੰਟਰਨੈੱਟ ਤੋਂ ਬਿਨਾਂ' ਹੈ</translation>
+<translation id="9108294543511800041">ਤੁਸੀਂ ਹੁਣ ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਹਾਲੀਆ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹੋ</translation>
 <translation id="9108674852930645435">ਤੁਹਾਡੇ <ph name="DEVICE_TYPE" /> ਵਿੱਚ ਨਵਾਂ ਕੀ ਹੈ ਇਸ ਦੀ ਪੜਚੋਲ ਕਰੋ</translation>
 <translation id="9108808586816295166">ਸੁਰੱਖਿਅਤ DNS ਸ਼ਾਇਦ ਹਰ ਵੇਲੇ ਉਪਲਬਧ ਨਾ ਹੋਵੇ</translation>
 <translation id="9109122242323516435">ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ, ਡੀਵਾਈਸ ਸਟੋਰੇਜ ਵਿੱਚੋਂ ਫ਼ਾਈਲਾਂ ਮਿਟਾਓ।</translation>
@@ -8435,7 +8444,6 @@
 <translation id="934503638756687833">ਜੇਕਰ ਲੋੜ ਹੋਵੇ ਤਾਂ ਇੱਥੇ ਸੂਚੀਬੱਧ ਨਹੀਂ ਕੀਤੀਆਂ ਆਈਟਮਾਂ ਨੂੰ ਵੀ ਹਟਾਇਆ ਜਾਵੇਗਾ। Chrome ਪਰਦੇਦਾਰੀ ਸ਼ਵੇਤ ਪੱਤਰ ਵਿੱਚ &lt;a href="<ph name="URL" />"&gt;ਅਣਚਾਹੇ ਸਾਫ਼ਟਵੇਅਰਾਂ ਸੰਬੰਧੀ ਸੁਰੱਖਿਆ&lt;/a&gt; ਦੇ ਬਾਰੇ ਹੋਰ ਜਾਣੋ।</translation>
 <translation id="93480724622239549">ਬੱਗ ਜਾਂ ਗੜਬੜ</translation>
 <translation id="935854577147268200">'ਸਮਾਰਟ ਲਾਕ' ਵਾਲਾ ਫ਼ੋਨ ਬਦਲਿਆ। 'ਸਮਾਰਟ ਲਾਕ' ਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਲਈ ਆਪਣਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ। ਅਗਲੀ ਵਾਰ, ਤੁਹਾਡਾ ਫ਼ੋਨ ਤੁਹਾਡੀ <ph name="DEVICE_TYPE" /> ਨੂੰ ਅਣਲਾਕ ਕਰੇਗਾ। ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ 'ਸਮਾਰਟ ਲਾਕ' ਨੂੰ ਬੰਦ ਕਰ ਸਕਦੇ ਹੋ</translation>
-<translation id="93610034168535821">ਸਾਈਟਾਂ ਵੱਲੋਂ ਵਰਤੀ ਗਈ ਕੁੱਲ ਸਟੋਰੇਜ:</translation>
 <translation id="936646668635477464">ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ</translation>
 <translation id="936801553271523408">ਸਿਸਟਮ ਨਿਦਾਨ ਡਾਟਾ</translation>
 <translation id="93766956588638423">ਐਕਸਟੈਂਸ਼ਨ ਰਿਪੇਅਰ ਕਰੋ</translation>
diff --git a/chrome/app/resources/generated_resources_pl.xtb b/chrome/app/resources/generated_resources_pl.xtb
index b16d731..de7b646 100644
--- a/chrome/app/resources/generated_resources_pl.xtb
+++ b/chrome/app/resources/generated_resources_pl.xtb
@@ -8405,7 +8405,6 @@
 <translation id="934503638756687833">W razie potrzeby zostaną usunięte też elementy niewymienione tutaj. Więcej informacji o &lt;a href="<ph name="URL" />"&gt;ochronie przed niechcianym oprogramowaniem&lt;/a&gt; znajdziesz w dokumencie dotyczącym prywatności w Chrome.</translation>
 <translation id="93480724622239549">Błąd</translation>
 <translation id="935854577147268200">Telefon z funkcją Smart Lock został zmieniony. Wpisz hasło, by zaktualizować Smart Lock. Następnym razem Twój telefon odblokuje urządzenie <ph name="DEVICE_TYPE" />. Smart Lock możesz wyłączyć w Ustawieniach.</translation>
-<translation id="93610034168535821">Całkowita pamięć używana przez strony:</translation>
 <translation id="936646668635477464">Kamera i mikrofon</translation>
 <translation id="936801553271523408">Systemowe dane diagnostyczne</translation>
 <translation id="93766956588638423">Napraw rozszerzenie</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index bcddd160..61231c59 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -1925,6 +1925,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Remover 1 app sem suporte}one{Remover # app sem suporte}other{Remover # apps sem suporte}}</translation>
 <translation id="2776560192867872731">Mudar nome do dispositivo para <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Excluir contêiner</translation>
+<translation id="2778471504622896352">Adicionar apps remotos ao iniciador do ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Erro ao instalar o aplicativo Linux</translation>
 <translation id="2783298271312924866">Download concluído</translation>
@@ -2240,6 +2241,7 @@
 <translation id="3067198360141518313">Executar este plug-in</translation>
 <translation id="3071624960923923138">Você pode clicar aqui para abrir uma nova guia</translation>
 <translation id="3072775339180057696">Permitir que o site veja <ph name="FILE_NAME" />?</translation>
+<translation id="3074499504015191586">Traduzir página inteira</translation>
 <translation id="3075874217500066906">É necessária uma reinicialização para iniciar o processo Powerwash. Após a reinicialização, solicitaremos que você confirme que deseja continuar.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">Salvar apenas neste dispositivo</translation>
@@ -3561,6 +3563,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> e mais <ph name="NUMBER_OF_OTHER_SWITCHES" /> interruptores</translation>
 <translation id="439266289085815679">A configuração do Bluetooth é controlada por <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Editar o arquivo de configuração</translation>
+<translation id="4393713825278446281">Dispositivos com Pareamento rápido salvos em <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Desativar</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Abrir tudo}=1{&amp;Abrir favorito}one{&amp;Abrir tudo ({COUNT})}other{&amp;Abrir tudo ({COUNT})}}</translation>
 <translation id="4397372003838952832">Você não precisa se lembrar dessa senha. Ela vai ficar salva na conta <ph name="EMAIL" /> do <ph name="GOOGLE_PASSWORD_MANAGER" />.</translation>
@@ -3791,6 +3794,7 @@
 <translation id="4615586811063744755">nenhum cookie foi selecionado</translation>
 <translation id="461661862154729886">Fonte de energia</translation>
 <translation id="4617001782309103936">Muito curto</translation>
+<translation id="4617019240346358451">Atualize a página para usar a extensão <ph name="EXTENSION_NAME" /></translation>
 <translation id="4617270414136722281">Opções de extensão</translation>
 <translation id="4617880081511131945">Não é possível estabelecer uma conexão</translation>
 <translation id="4619564267100705184">Confirmar sua identidade</translation>
@@ -4006,6 +4010,7 @@
 <translation id="4833683849865011483">Uma impressora encontrada no servidor de impressão.</translation>
 <translation id="4836504898754963407">Gerenciar impressões digitais</translation>
 <translation id="4837128290434901661">Voltar a usar a Pesquisa Google?</translation>
+<translation id="4837165100461973682">Atualize a página para aplicar as modificações</translation>
 <translation id="4837926214103741331">Você não tem autorização para usar este dispositivo. Para permissão de login, entre em contato com o proprietário do dispositivo.</translation>
 <translation id="4837952862063191349">Para desbloquear e restaurar seus dados locais, digite sua senha antiga do <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Veja os arquivos de mídia, fotos e notificações do smartphone</translation>
@@ -4316,6 +4321,7 @@
 <translation id="5150254825601720210">Nome do servidor SSL do certificado do Netscape</translation>
 <translation id="5151354047782775295">Libere espaço em disco, ou dados específicos podem ser excluídos automaticamente</translation>
 <translation id="5153234146675181447">Esquecer o smartphone</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Configurações avançadas para <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Assunto</translation>
 <translation id="5155327081870541046">Na barra de endereço, digite o atalho do site em que você quer pesquisar, como "@favoritos". Depois, pressione o atalho de teclado que preferir e digite o termo de pesquisa.</translation>
@@ -5094,6 +5100,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> está usando sua câmera e seu microfone</translation>
 <translation id="5935158534896975820">Preparando a solicitação de assinatura de certificado (aguardando o servidor)</translation>
 <translation id="5935656526031444304">Gerenciar "Navegação segura"</translation>
+<translation id="5936065461722368675">Traduzir página inteira</translation>
 <translation id="5938002010494270685">Atualização de segurança disponível</translation>
 <translation id="5939518447894949180">Redefinir</translation>
 <translation id="5939719276406088041">Não é possível criar o atalho</translation>
@@ -5956,6 +5963,7 @@
 <translation id="6790497603648687708">A extensão <ph name="EXTENSION_NAME" /> foi adicionada remotamente</translation>
 <translation id="6790820461102226165">Adicionar pessoa...</translation>
 <translation id="6793604637258913070">Destacar o cursor de texto quando ele aparecer ou se mover</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">Com a leitura automática, você navega automaticamente pelos itens na tela. Quando um item estiver destacado, pressione "Selecionar" para ativá-lo.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Algo deu errado.</translation>
@@ -7832,6 +7840,7 @@
 <translation id="8642947597466641025">Aumentar o texto</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> pode ser perigoso. Enviar para verificação no Proteção Avançada do Google?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Sem cookies}=1{1 cookie foi bloqueado}one{# cookie foi bloqueado}other{# cookies foram bloqueados}}</translation>
+<translation id="864423554496711319">Dispositivos salvos na sua conta</translation>
 <translation id="8644655801811752511">Não é possível redefinir esta chave de segurança. Tente redefinir a chave imediatamente após inseri-la.</translation>
 <translation id="8645354835496065562">Continuar permitindo acesso ao sensor</translation>
 <translation id="8645920082661222035">Prevê eventos perigosos e alerta você antes que eles aconteçam</translation>
@@ -8439,7 +8448,6 @@
 <translation id="934503638756687833">Itens que não estão listados aqui também serão removidos, se necessário. Saiba mais sobre a &lt;a href="<ph name="URL" />"&gt;proteção contra softwares indesejados&lt;/a&gt; no artigo sobre privacidade do Chrome.</translation>
 <translation id="93480724622239549">Bug ou erro</translation>
 <translation id="935854577147268200">O smartphone do Smart Lock mudou. Digite sua senha para atualizar o Smart Lock. Na próxima vez, o smartphone desbloqueará seu <ph name="DEVICE_TYPE" />. É possível desativar o Smart Lock nas configurações</translation>
-<translation id="93610034168535821">Armazenamento total usado pelos sites:</translation>
 <translation id="936646668635477464">Câmera e microfone</translation>
 <translation id="936801553271523408">Dados de diagnóstico do sistema</translation>
 <translation id="93766956588638423">Reparar extensão</translation>
diff --git a/chrome/app/resources/generated_resources_pt-PT.xtb b/chrome/app/resources/generated_resources_pt-PT.xtb
index 8d019c4..81f4f205 100644
--- a/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -8426,7 +8426,6 @@
 <translation id="934503638756687833">Também serão removidos itens não indicados aqui, se necessário. Saiba mais acerca da &lt;a href="<ph name="URL" />"&gt;proteção contra software indesejado&lt;/a&gt; no documento técnico da Privacidade do Chrome.</translation>
 <translation id="93480724622239549">Erro</translation>
 <translation id="935854577147268200">O telemóvel com Smart Lock foi alterado. Introduza a palavra-passe para atualizar o Smart Lock. Da próxima vez, o telemóvel irá desbloquear o <ph name="DEVICE_TYPE" />. Desative o Smart Lock nas Definições.</translation>
-<translation id="93610034168535821">Armazenamento total utilizado pelos sites:</translation>
 <translation id="936646668635477464">Câmara e microfone</translation>
 <translation id="936801553271523408">Dados de diagnóstico do sistema</translation>
 <translation id="93766956588638423">Reparar extensão</translation>
diff --git a/chrome/app/resources/generated_resources_ro.xtb b/chrome/app/resources/generated_resources_ro.xtb
index 000e43b..44c6e27 100644
--- a/chrome/app/resources/generated_resources_ro.xtb
+++ b/chrome/app/resources/generated_resources_ro.xtb
@@ -8429,7 +8429,6 @@
 <translation id="934503638756687833">Vor fi șterse și articole care nu sunt afișate aici, dacă este necesar. Află mai multe despre &lt;a href="<ph name="URL" />"&gt;protecția împotriva software-ului nedorit&lt;/a&gt; din cartea albă privind confidențialitatea Chrome.</translation>
 <translation id="93480724622239549">Eroare</translation>
 <translation id="935854577147268200">Telefonul Smart Lock s-a schimbat. Introdu parola pentru a actualiza Smart Lock. Data viitoare, telefonul tău va debloca dispozitivul <ph name="DEVICE_TYPE" />. Poți dezactiva Smart Lock din Setări.</translation>
-<translation id="93610034168535821">Spațiul total de stocare folosit de site-uri:</translation>
 <translation id="936646668635477464">Camera și microfonul</translation>
 <translation id="936801553271523408">Date de diagnosticare a sistemului</translation>
 <translation id="93766956588638423">Repară extensia</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb
index b1b9ebb9..f5b2a2a 100644
--- a/chrome/app/resources/generated_resources_ru.xtb
+++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -1545,6 +1545,7 @@
 <translation id="2433836460518180625">Только снимать блокировку устройства</translation>
 <translation id="2434449159125086437">Не удалось настроить принтер. Проверьте конфигурацию и повторите попытку.</translation>
 <translation id="2434758125294431199">Укажите, кто может делиться файлами и ссылками с вами</translation>
+<translation id="2434915728183570229">Теперь вы можете просматривать приложения с телефона</translation>
 <translation id="2435137177546457207">Дополнительные условия использования Google Chrome и Chrome OS Flex</translation>
 <translation id="2435248616906486374">Подключение отсутствует</translation>
 <translation id="2435457462613246316">Показать пароль</translation>
@@ -4227,6 +4228,7 @@
 <translation id="5072900412896857127">Не удалось скачать Условия использования Google Play. Проверьте подключение к интернету и повторите попытку.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}one{<ph name="FILE1" />, <ph name="FILE2" /> и ещё # файл}few{<ph name="FILE1" />, <ph name="FILE2" /> и ещё # файла}many{<ph name="FILE1" />, <ph name="FILE2" /> и ещё # файлов}other{<ph name="FILE1" />, <ph name="FILE2" /> и ещё # файла}}</translation>
 <translation id="5074318175948309511">Чтобы настройки вступили в силу, необходимо перезагрузить страницу.</translation>
+<translation id="5074761966806028321">Чтобы завершить настройку, предоставьте разрешение</translation>
 <translation id="5075910247684008552">На защищенных сайтах небезопасный контент блокируется по умолчанию.</translation>
 <translation id="5078638979202084724">Добавить все вкладки в закладки</translation>
 <translation id="5078796286268621944">Неверный PIN-код</translation>
@@ -4590,6 +4592,7 @@
 <translation id="5449551289610225147">Неправильный пароль</translation>
 <translation id="5449588825071916739">Добавить все вкладки в закладки</translation>
 <translation id="5449716055534515760">Закрыть &amp;окно</translation>
+<translation id="5452446625764825792">Теперь вы можете просматривать недавние фотографии, медиафайлы и приложения с телефона</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (доступен офлайн)</translation>
 <translation id="5454166040603940656">с помощью <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Показывать больше результатов поиска</translation>
@@ -4650,6 +4653,7 @@
 <translation id="5499211612787418966">Это диалоговое окно находится не в фокусе. Чтобы это исправить, нажмите Alt + Shift + A.</translation>
 <translation id="5499313591153584299">Этот файл может быть опасен для вашего компьютера.</translation>
 <translation id="5499453227627332024">Доступно обновление для контейнера Linux. Его также можно обновить позже из приложения "Настройки".</translation>
+<translation id="5499476581866658341">Теперь вы можете просматривать недавние фотографии и медиафайлы с телефона</translation>
 <translation id="549957179819296104">Новый значок</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />История поиска<ph name="END_LINK_SEARCH" /> и сведения о <ph name="BEGIN_LINK_GOOGLE" />других действиях<ph name="END_LINK_GOOGLE" /> могут сохраняться в аккаунте Google, если вы в него вошли. Эти данные можно удалить в любое время.</translation>
 <translation id="5500709606820808700">Проверка безопасности выполнена сегодня.</translation>
@@ -6320,6 +6324,7 @@
 <translation id="7152478047064750137">Расширению не требуются особые разрешения</translation>
 <translation id="7154130902455071009">Смена стартовой страницы на <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Фото с камеры или из галереи</translation>
+<translation id="7160182524506337403">Теперь вы можете просматривать уведомления с телефона</translation>
 <translation id="7163202347044721291">Проверка кода активации…</translation>
 <translation id="716640248772308851">Расширению "<ph name="EXTENSION" />" будет предоставлен доступ для чтения к изображениям, видео- и аудиофайлам в отмеченных папках.</translation>
 <translation id="7167486101654761064">&amp;Всегда открывать файлы этого типа</translation>
@@ -7334,6 +7339,7 @@
 <translation id="8138997515734480534">Статус ВМ "<ph name="VM_NAME" />"</translation>
 <translation id="8139447493436036221">Файлы на Google Диске</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Вы можете настроить больше функций в разделе "Управление телефоном".</translation>
 <translation id="8141584439523427891">Запуск альтернативного браузера…</translation>
 <translation id="8141725884565838206">Управление паролями</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{видео}one{# видео}few{# видео}many{# видео}other{# видео}}</translation>
@@ -7541,6 +7547,7 @@
 <translation id="833986336429795709">Чтобы открыть ссылку, выберите приложение</translation>
 <translation id="8342221978608739536">Не знаю</translation>
 <translation id="8342861492835240085">Выберите коллекцию</translation>
+<translation id="8345848587667658367">Теперь вы можете просматривать недавние фотографии, медиафайлы, уведомления и приложения с телефона</translation>
 <translation id="8347227221149377169">Задания печати</translation>
 <translation id="834785183489258869">В режиме инкогнито сайты не могут использовать файлы cookie, чтобы отслеживать ваши действия в браузере, например для показа персонализированной рекламы. Из-за этого функции некоторых сайтов могут стать недоступными.</translation>
 <translation id="8350789879725387295">Инструменты стилуса на панели Dock</translation>
@@ -8149,6 +8156,7 @@
 <translation id="8957757410289731985">Настроить профиль</translation>
 <translation id="895944840846194039">Память JavaScript</translation>
 <translation id="8960208913905765425">Преобразование единиц измерения с помощью функции "Быстрые ответы"</translation>
+<translation id="8960638196855923532">Теперь вы можете просматривать уведомления и приложения с телефона</translation>
 <translation id="8962051932294470566">За раз можно поделиться только одним файлом. Повторите попытку, когда завершится текущая передача данных.</translation>
 <translation id="8962083179518285172">Скрыть детали</translation>
 <translation id="8962918469425892674">Этот сайт использует датчики движения и освещенности</translation>
@@ -8300,6 +8308,7 @@
 <translation id="9103868373786083162">Нажмите, чтобы вернуться, используйте контекстное меню, чтобы открыть историю</translation>
 <translation id="9108035152087032312">Добавить название окна</translation>
 <translation id="9108072915170399168">Выбран режим передачи данных "Без подключения к Интернету".</translation>
+<translation id="9108294543511800041">Теперь вы можете просматривать недавние фотографии, медиафайлы и уведомления с телефона</translation>
 <translation id="9108674852930645435">Что нового в <ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">Иногда безопасный DNS-сервер может быть недоступен.</translation>
 <translation id="9109122242323516435">Чтобы освободить пространство, удалите файлы, хранящиеся на устройстве.</translation>
@@ -8424,7 +8433,6 @@
 <translation id="934503638756687833">Объекты, не перечисленные здесь, также будут удалены при необходимости. Подробнее &lt;a href="<ph name="URL" />"&gt;о защите от нежелательного ПО&lt;/a&gt;…</translation>
 <translation id="93480724622239549">Ошибка</translation>
 <translation id="935854577147268200">Телефон для снятия блокировки был изменен. Чтобы обновить параметры Smart Lock, введите пароль. После этого вы сможете снимать блокировку устройства <ph name="DEVICE_TYPE" /> с помощью телефона. Чтобы выключить Smart Lock, перейдите в настройки.</translation>
-<translation id="93610034168535821">Объем хранилища, занятый сайтами:</translation>
 <translation id="936646668635477464">Камера и микрофон</translation>
 <translation id="936801553271523408">Диагностические данные системы</translation>
 <translation id="93766956588638423">Восстановить расширение</translation>
diff --git a/chrome/app/resources/generated_resources_si.xtb b/chrome/app/resources/generated_resources_si.xtb
index 257fbe0..b59bdcb2 100644
--- a/chrome/app/resources/generated_resources_si.xtb
+++ b/chrome/app/resources/generated_resources_si.xtb
@@ -8427,7 +8427,6 @@
 <translation id="934503638756687833">මෙහි ලැයිස්තුගත නොකළ අයිතම අවශ්‍ය නම්, ඉවත් කරනු ඇත. Chrome රහස්‍යතා ධවල පත්‍රිකාව තුළ &lt;a href="<ph name="URL" />"&gt;අනවශ්‍ය මෘදුකාංග ආරක්ෂණය&lt;/a&gt; ගැන තව දැන ගන්න.</translation>
 <translation id="93480724622239549">දොස හෝ දෝෂය</translation>
 <translation id="935854577147268200">Smart Lock දුරකථනය වෙනස් විය. Smart Lock යාවත්කාලීන කිරීමට ඔබේ මුරපදය ඇතුළත් කරන්න. ඊළඟ වතාවේ, ඔබේ දුරකථනය ඔබගේ <ph name="DEVICE_TYPE" /> අඟුලු අරියි. ඔබට සැකසීම් තුළ Smart Lock අක්‍රිය කළ හැක.</translation>
-<translation id="93610034168535821">වෙබ් අඩවිවලින් භාවිත කරනු ලැබූ සම්පූර්ණ ආචයනය:</translation>
 <translation id="936646668635477464">කැමරාව හා මයික්‍රෆෝනය</translation>
 <translation id="936801553271523408">පද්ධති සොයා ගැනීමේ දත්ත</translation>
 <translation id="93766956588638423">දිගුව අලුත්වැඩියා කරන්න</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index 31da148..b720daf8 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -1545,6 +1545,7 @@
 <translation id="2433836460518180625">Iba odomknúť zariadenie</translation>
 <translation id="2434449159125086437">Tlačiareň sa nepodarilo nastaviť. Skontrolujte konfiguráciu a skúste to znova.</translation>
 <translation id="2434758125294431199">Vyberte, kto s vami môže zdieľať obsah</translation>
+<translation id="2434915728183570229">Teraz si môžete zobraziť aplikácie svojho telefónu</translation>
 <translation id="2435137177546457207">Dodatočné zmluvné podmienky prehliadača Google Chrome a systému Chrome OS Flex</translation>
 <translation id="2435248616906486374">Sieť je odpojená</translation>
 <translation id="2435457462613246316">Zobraziť heslo</translation>
@@ -4228,6 +4229,7 @@
 <translation id="5072900412896857127">Zmluvné podmienky služby Google Play sa nedajú načítať. Skontrolujte pripojenie k sieti a skúste to znova.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}few{<ph name="FILE1" />, <ph name="FILE2" /> a # ďalšie}many{<ph name="FILE1" />, <ph name="FILE2" />, and # more}other{<ph name="FILE1" />, <ph name="FILE2" /> a # ďalších}}</translation>
 <translation id="5074318175948309511">Na to, aby toto nové nastavenie nadobudlo platnosť, budete možno musieť znova načítať túto stránku.</translation>
+<translation id="5074761966806028321">Na dokončenie nastavenia je stále potrebné povolenie</translation>
 <translation id="5075910247684008552">Bezpečné weby predvolene blokujú nezabezpečený obsah</translation>
 <translation id="5078638979202084724">Uložiť všetky karty ako záložky</translation>
 <translation id="5078796286268621944">Nesprávny kód PIN</translation>
@@ -4591,6 +4593,7 @@
 <translation id="5449551289610225147">Neplatné heslo</translation>
 <translation id="5449588825071916739">Uložiť všetky karty ako záložky</translation>
 <translation id="5449716055534515760">Zavrieť o&amp;kno</translation>
+<translation id="5452446625764825792">Teraz si môžete zobraziť nedávne fotky, médiá a aplikácie svojho telefónu</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (funguje offline)</translation>
 <translation id="5454166040603940656">s poskytovateľom <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Zobraziť ďalšie výsledky vyhľadávania</translation>
@@ -4651,6 +4654,7 @@
 <translation id="5499211612787418966">Toto dialógové okno nie je momentálne označené. Označíte ho stlačením kombinácie klávesov Alt-Shift A.</translation>
 <translation id="5499313591153584299">Tento súbor môže poškodiť váš počítať.</translation>
 <translation id="5499453227627332024">Pre váš kontajner systému Linux je k dispozícii inovácia. Inovovať môžete aj neskôr v aplikácii Nastavenia.</translation>
+<translation id="5499476581866658341">Teraz si môžete zobraziť nedávne fotky a médiá svojho telefónu</translation>
 <translation id="549957179819296104">Nová ikona</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />História vyhľadávania<ph name="END_LINK_SEARCH" /> a <ph name="BEGIN_LINK_GOOGLE" />ďalšie formy aktivity<ph name="END_LINK_GOOGLE" /> sa môžu ukladať do vášho účtu Google, keď sa doň prihlásite. Môžete ich kedykoľvek odstrániť.</translation>
 <translation id="5500709606820808700">Kontrola bezpečnosti prebehla dnes</translation>
@@ -6319,6 +6323,7 @@
 <translation id="7152478047064750137">Toto rozšírenie nevyžaduje žiadne špeciálne povolenia</translation>
 <translation id="7154130902455071009">Zmeniť úvodnú stránku na: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Existujúca fotka z fotoaparátu alebo súboru</translation>
+<translation id="7160182524506337403">Teraz si môžete zobraziť upozornenia svojho telefónu</translation>
 <translation id="7163202347044721291">Overuje sa aktivačný kód…</translation>
 <translation id="716640248772308851">Rozšírenie <ph name="EXTENSION" /> môže čítať obrázky, video a zvukové súbory vo vybratých umiestneniach.</translation>
 <translation id="7167486101654761064">&amp;Vždy otvárať súbory tohto typu</translation>
@@ -7333,6 +7338,7 @@
 <translation id="8138997515734480534">Stav virtuálneho počítača <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">Súbory na Disku Google</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Ďalšie funkcie môžete nakonfigurovať v nastaveniach Telefónneho centra</translation>
 <translation id="8141584439523427891">Otvára sa alternatívny prehliadač</translation>
 <translation id="8141725884565838206">Správa hesiel</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{video}few{# videá}many{# videos}other{# videí}}</translation>
@@ -7540,6 +7546,7 @@
 <translation id="833986336429795709">Ak chcete otvoriť tento odkaz, vyberte aplikáciu</translation>
 <translation id="8342221978608739536">Nepokúsil(a) som sa o to</translation>
 <translation id="8342861492835240085">Vybrať zbierku</translation>
+<translation id="8345848587667658367">Teraz si môžete zobraziť najnovšie fotky, médiá, upozornenia a aplikácie svojho telefónu</translation>
 <translation id="8347227221149377169">Tlačové úlohy</translation>
 <translation id="834785183489258869">Weby v režime inkognito nemôžu pomocou súborov cookie zobraziť vašu aktivitu prehliadania v rámci rôznych webov (napríklad na prispôsobenie reklám). Funkcie na niektorých weboch nemusia fungovať.</translation>
 <translation id="8350789879725387295">Nástroje dotykového pera v doku</translation>
@@ -8147,6 +8154,7 @@
 <translation id="8957757410289731985">Prispôsobiť profil</translation>
 <translation id="895944840846194039">Pamäť JavaScript</translation>
 <translation id="8960208913905765425">Prevod jednotiek v rámci rýchlych odpovedí</translation>
+<translation id="8960638196855923532">Teraz si môžete zobraziť upozornenia a aplikácie svojho telefónu</translation>
 <translation id="8962051932294470566">Naraz môžete zdieľať iba jeden súbor. Skúste to znova po dokončení aktuálneho prenosu.</translation>
 <translation id="8962083179518285172">Skryť podrobnosti</translation>
 <translation id="8962918469425892674">Tento web používa senzory pohybu alebo svetla.</translation>
@@ -8298,6 +8306,7 @@
 <translation id="9103868373786083162">Stlačením tohto tlačidla prejdete späť, históriu si zobrazíte pomocou kontextovej ponuky</translation>
 <translation id="9108035152087032312">Pomenovať okno...</translation>
 <translation id="9108072915170399168">Aktuálne nastavenie spotreby dát: bez internetu</translation>
+<translation id="9108294543511800041">Teraz si môžete zobraziť nedávne fotky, médiá a upozornenia svojho telefónu</translation>
 <translation id="9108674852930645435">Novinky v zariadení <ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">Zabezpečený systém DNS nemusí byť vždy k dispozícii</translation>
 <translation id="9109122242323516435">Miesto uvoľníte odstránením súborov z úložiska zariadenia.</translation>
@@ -8422,7 +8431,6 @@
 <translation id="934503638756687833">Položky, ktoré tu nie sú uvedené, budú v prípade potreby tiež odstránené. Prečítajte si ďalšie informácie o &lt;a href="<ph name="URL" />"&gt;ochrane pred nežiaducim softvérom&lt;/a&gt; v bielej knihe ochrany súkromia v Chrome.</translation>
 <translation id="93480724622239549">Chyba</translation>
 <translation id="935854577147268200">Zmenil sa telefón spojený s funkciou Smart Lock. Ak chcete Smart Lock aktualizovať, zadajte heslo. Zariadenie <ph name="DEVICE_TYPE" /> nabudúce odomknete telefónom. Smart Lock vypnete v Nastaveniach.</translation>
-<translation id="93610034168535821">Celkový priestor v úložisku používaný webmi:</translation>
 <translation id="936646668635477464">Kamera a mikrofón</translation>
 <translation id="936801553271523408">Údaje o diagnostike systému</translation>
 <translation id="93766956588638423">Opraviť rozšírenie</translation>
diff --git a/chrome/app/resources/generated_resources_sl.xtb b/chrome/app/resources/generated_resources_sl.xtb
index b3e0a57..3240414 100644
--- a/chrome/app/resources/generated_resources_sl.xtb
+++ b/chrome/app/resources/generated_resources_sl.xtb
@@ -1561,6 +1561,7 @@
 <translation id="2433836460518180625">Samo odklepanje naprave</translation>
 <translation id="2434449159125086437">Ni mogoče nastaviti tiskalnika. Preverite konfiguracijo in poskusite znova.</translation>
 <translation id="2434758125294431199">Izberite, kdo lahko deli z vami</translation>
+<translation id="2434915728183570229">Zdaj si lahko ogledate aplikacije telefona</translation>
 <translation id="2435137177546457207">Dodatni pogoji za Google Chrome in ChromeOS Flex</translation>
 <translation id="2435248616906486374">Povezava z omrežjem je prekinjena</translation>
 <translation id="2435457462613246316">Pokaži geslo</translation>
@@ -2242,6 +2243,7 @@
 <translation id="3067198360141518313">Zaženi vtičnik</translation>
 <translation id="3071624960923923138">Če želite odpreti nov zavihek, lahko kliknete tukaj</translation>
 <translation id="3072775339180057696">Želite spletnemu mestu omogočiti, da si ogleda datoteko <ph name="FILE_NAME" />?</translation>
+<translation id="3074499504015191586">Prevedi celotno stran</translation>
 <translation id="3075874217500066906">Za začetek postopka Powerwash je potreben vnovični zagon. Po vnovičnem zagonu boste morali potrditi, da želite nadaljevati.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">Shrani samo v tej napravi</translation>
@@ -4245,6 +4247,7 @@
 <translation id="5072900412896857127">Pogojev storitve za Google Play ni mogoče naložiti. Preverite omrežno povezavo in poskusite znova.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}one{<ph name="FILE1" />, <ph name="FILE2" /> in še #}two{<ph name="FILE1" />, <ph name="FILE2" /> in še #}few{<ph name="FILE1" />, <ph name="FILE2" /> in še #}other{<ph name="FILE1" />, <ph name="FILE2" /> in še #}}</translation>
 <translation id="5074318175948309511">Nove nastavitve bodo morda začele veljati, šele ko znova naložite to stran.</translation>
+<translation id="5074761966806028321">Za dokončanje nastavitve je še potrebno dovoljenje</translation>
 <translation id="5075910247684008552">Vsebina, ki ni varna, je na varnih spletnih mestih privzeto blokirana</translation>
 <translation id="5078638979202084724">Dodaj vse zavihke med zaznamke</translation>
 <translation id="5078796286268621944">Napačen PIN</translation>
@@ -4608,6 +4611,7 @@
 <translation id="5449551289610225147">Neveljavno geslo</translation>
 <translation id="5449588825071916739">Dodaj vse zavihke med zaznamke</translation>
 <translation id="5449716055534515760">Zapri &amp;okno</translation>
+<translation id="5452446625764825792">Zdaj si lahko ogledate nedavne fotografije, predstavnost in aplikacije telefona</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (deluje brez povezave)</translation>
 <translation id="5454166040603940656">pri ponudniku <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Prikaz več rezultatov iskanja</translation>
@@ -4668,6 +4672,7 @@
 <translation id="5499211612787418966">To pogovorno okno trenutno ni izbrano. Pritisnite Alt + Shift + A, če ga želite izbrati.</translation>
 <translation id="5499313591153584299">Ta datoteka lahko škoduje vašemu računalniku.</translation>
 <translation id="5499453227627332024">Na voljo je nadgradnja za vsebnik za Linux. Nadgradite ga lahko tudi pozneje v aplikaciji Nastavitve.</translation>
+<translation id="5499476581866658341">Zdaj si lahko ogledate nedavne fotografije in predstavnost telefona</translation>
 <translation id="549957179819296104">Nova ikona</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />Zgodovina iskanja<ph name="END_LINK_SEARCH" /> in <ph name="BEGIN_LINK_GOOGLE" />druge oblike dejavnosti<ph name="END_LINK_GOOGLE" /> se morda shranjujejo v računu Google, ko ste prijavljeni. Izbrišete jih lahko kadar koli.</translation>
 <translation id="5500709606820808700">Varnostno preverjanje je bilo izvedeno danes</translation>
@@ -5097,6 +5102,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> uporablja vašo kamero in mikrofon</translation>
 <translation id="5935158534896975820">Pripravljanje zahteve za podpisovanje potrdila (čakanje na strežnik)</translation>
 <translation id="5935656526031444304">Upravljanje varnega brskanja</translation>
+<translation id="5936065461722368675">Prevedi celotno stran</translation>
 <translation id="5938002010494270685">Na voljo je nadgradnja varnosti</translation>
 <translation id="5939518447894949180">Ponastavi</translation>
 <translation id="5939719276406088041">Bližnjice ni mogoče ustvariti.</translation>
@@ -6340,6 +6346,7 @@
 <translation id="7152478047064750137">Za to razširitev niso potrebna posebna dovoljenja</translation>
 <translation id="7154130902455071009">Sprememba začetne strani na: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Obstoječa fotografija iz fotoaparata ali datoteke</translation>
+<translation id="7160182524506337403">Zdaj si lahko ogledate obvestila telefona</translation>
 <translation id="7163202347044721291">Preverjanje kode za aktiviranje …</translation>
 <translation id="716640248772308851">Razširitev »<ph name="EXTENSION" />« lahko prebere slike ter videodatoteke in zvočne datoteke na označenih lokacijah.</translation>
 <translation id="7167486101654761064">&amp;Vedno odpri to vrsto datotek</translation>
@@ -7355,6 +7362,7 @@
 <translation id="8138997515734480534">Stanje navideznega računalnika <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">Datoteke v Googlu Drive</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Več funkcij lahko nastavite v nastavitvah telefonskega središča.</translation>
 <translation id="8141584439523427891">Odpiranje v nadomestnem brskalniku</translation>
 <translation id="8141725884565838206">Upravljanje gesel</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{videoposnetek}one{# videoposnetek}two{# videoposnetka}few{# videoposnetki}other{# videoposnetkov}}</translation>
@@ -7562,6 +7570,7 @@
 <translation id="833986336429795709">Če želite odpreti to povezavo, izberite aplikacijo</translation>
 <translation id="8342221978608739536">Nisem poskusil(-a)</translation>
 <translation id="8342861492835240085">Izberi zbirko</translation>
+<translation id="8345848587667658367">Zdaj si lahko ogledate nedavne fotografije, predstavnost, obvestila in aplikacije telefona</translation>
 <translation id="8347227221149377169">Tiskalna opravila</translation>
 <translation id="834785183489258869">Ko uporabljate anonimni način, spletna mesta ne morejo uporabljati piškotkov za ogled dejavnosti brskanja na različnih spletnih mestih, na primer za osebno prilagajanje oglasov. Funkcije na nekaterih spletnih mestih morda ne bodo delovale.</translation>
 <translation id="8350789879725387295">Orodja za pisalo v opravilni vrstici</translation>
@@ -8170,6 +8179,7 @@
 <translation id="8957757410289731985">Prilagodi profil</translation>
 <translation id="895944840846194039">Pomnilnik za JavaScript</translation>
 <translation id="8960208913905765425">Pretvorba enot hitrih odgovorov</translation>
+<translation id="8960638196855923532">Zdaj si lahko ogledate obvestila in aplikacije telefona</translation>
 <translation id="8962051932294470566">Hkrati lahko delite samo eno datoteko. Poskusite znova, ko bo trenutni prenos končan.</translation>
 <translation id="8962083179518285172">Skrij podrobnosti</translation>
 <translation id="8962918469425892674">To spletno mesto uporablja tipala gibanja ali svetlobe.</translation>
@@ -8321,6 +8331,7 @@
 <translation id="9103868373786083162">Pritisnite, če želite nazaj, s kontekstnim menijem pa prikažete zgodovino</translation>
 <translation id="9108035152087032312">Poimenuj &amp;okno …</translation>
 <translation id="9108072915170399168">Trenutna nastavitev za preneseno količino podatkov je »Brez interneta«</translation>
+<translation id="9108294543511800041">Zdaj si lahko ogledate nedavne fotografije, predstavnost in obvestila telefona</translation>
 <translation id="9108674852930645435">Raziščite novosti v napravi <ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">Varni DNS morda ni na voljo ves čas</translation>
 <translation id="9109122242323516435">Če želite sprostiti prostor, izbrišite datoteke iz shrambe v napravi.</translation>
@@ -8445,7 +8456,6 @@
 <translation id="934503638756687833">Elementi, ki niso navedeni tukaj, bodo po potrebi morda tudi odstranjeni. Preberite več o &lt;a href="<ph name="URL" />"&gt;zaščiti pred neželeno programsko opremo&lt;/a&gt; v beli knjigi o zasebnosti za Chrome.</translation>
 <translation id="93480724622239549">Napaka</translation>
 <translation id="935854577147268200">Telefon za Smart Lock je spremenjen. Vnesite geslo, če želite posodobiti Smart Lock. Naslednjič bo telefon odklenil napravo <ph name="DEVICE_TYPE" />. Smart Lock lahko izklopite v nastavitvah.</translation>
-<translation id="93610034168535821">Skupna shramba, ki jo uporabljajo spletna mesta:</translation>
 <translation id="936646668635477464">Kamera in mikrofon</translation>
 <translation id="936801553271523408">Sistemski diagnostični podatki</translation>
 <translation id="93766956588638423">Popravi razširitev</translation>
diff --git a/chrome/app/resources/generated_resources_sq.xtb b/chrome/app/resources/generated_resources_sq.xtb
index c772e67..54345f6 100644
--- a/chrome/app/resources/generated_resources_sq.xtb
+++ b/chrome/app/resources/generated_resources_sq.xtb
@@ -1905,6 +1905,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Hiq 1 aplikacion të pambështetur}other{Hiq # aplikacione të pambështetura}}</translation>
 <translation id="2776560192867872731">Ndrysho emrin e pajisjes për <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Fshije këtë kontejner</translation>
+<translation id="2778471504622896352">Shto aplikacione në distancë te nisësi i ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Gabim në instalimin e aplikacionit Linux</translation>
 <translation id="2783298271312924866">U shkarkua</translation>
@@ -3540,6 +3541,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> dhe <ph name="NUMBER_OF_OTHER_SWITCHES" /> çelësa të tjerë</translation>
 <translation id="439266289085815679">Konfigurimi i Bluetooth-it kontrollohet nga <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Modifiko skedarin e konfigurimit</translation>
+<translation id="4393713825278446281">Pajisjet me "Çiftimin e shpejtë" që janë ruajtur te <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Çaktivizo</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Hapi të gjitha}=1{&amp;Hap faqeshënuesin}other{&amp;Hapi të gjitha ({COUNT})}}</translation>
 <translation id="4397372003838952832">Nuk është nevoja ta kujtosh këtë fjalëkalim. Ai do të ruhet te <ph name="GOOGLE_PASSWORD_MANAGER" /> për <ph name="EMAIL" /></translation>
@@ -3769,6 +3771,7 @@
 <translation id="4615586811063744755">nuk është zgjedhur asnjë kuki</translation>
 <translation id="461661862154729886">Burimi i energjisë</translation>
 <translation id="4617001782309103936">Shumë i shkurtër</translation>
+<translation id="4617019240346358451">Ringarko faqen për të përdorur "<ph name="EXTENSION_NAME" />"</translation>
 <translation id="4617270414136722281">Opsionet e prapashtesës</translation>
 <translation id="4617880081511131945">Nuk mund të vendoset lidhja</translation>
 <translation id="4619564267100705184">Verifiko që je ti</translation>
@@ -3984,6 +3987,7 @@
 <translation id="4833683849865011483">U gjet 1 printer nga serveri i printimit</translation>
 <translation id="4836504898754963407">Menaxho gjurmët e gishtave</translation>
 <translation id="4837128290434901661">Të ndryshohet përsëri në "Kërko në Google"?</translation>
+<translation id="4837165100461973682">Ringarko faqen për të zbatuar ndryshimet</translation>
 <translation id="4837926214103741331">Nuk je i autorizuar të përdorësh këtë pajisje. Kontakto me zotëruesin e pajisjes për të marrë leje për identifikim.</translation>
 <translation id="4837952862063191349">Për të shkyçur dhe rivendosur të dhënat lokale, fut fjalëkalimin e vjetër të <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Shiko fotografitë, mediat dhe njoftimet e telefonit tënd</translation>
@@ -4293,6 +4297,7 @@
 <translation id="5150254825601720210">Emri i serverit SSL të certifikatës së Netscape</translation>
 <translation id="5151354047782775295">Liro hapësirë në disk ose të dhëna të caktuara mund të fshihen automatikisht</translation>
 <translation id="5153234146675181447">Harro telefonin</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Cilësimet e përparuara për <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Subjekti</translation>
 <translation id="5155327081870541046">Në shiritin e adresave, fut shkurtoren për sajtin në të cilin dëshiron të kërkosh, si p.sh. "@faqeshënuesit". Më pas shtyp shkurtoren e preferuar të tastierës dhe fut termin e kërkimit.</translation>
@@ -5928,6 +5933,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> u shtua në distancë</translation>
 <translation id="6790820461102226165">Shto person...</translation>
 <translation id="6793604637258913070">Thekso kursorin e tekstit kur shfaqet ose lëviz.</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">Skanimi automatik të lejon të lëvizësh automatikisht nëpër artikujt në ekran. Kur një artikull është i theksuar, shtyp “Zgjidh” për ta aktivizuar atë.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Mos, ndodhi një gabim.</translation>
@@ -7798,6 +7804,7 @@
 <translation id="8642947597466641025">Bëje tekstin më të madh</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> mund të jetë i rrezikshëm. Të dërgohet te "Mbrojtja e përparuar" e Google për skanim?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Nuk ka kuki}=1{1 kuki është bllokuar}other{# kuki janë bllokuar}}</translation>
+<translation id="864423554496711319">Pajisjet e ruajtura në llogarinë tënde</translation>
 <translation id="8644655801811752511">Ky çelës sigurie nuk mund të rivendoset. Provo ta rivendosësh çelësin menjëherë pasi ta futësh.</translation>
 <translation id="8645354835496065562">Vazhdo të lejosh qasjen te sensorët</translation>
 <translation id="8645920082661222035">Parashikon dhe të paralajmëron rreth ngjarjeve të rrezikshme përpara se ato të ndodhin</translation>
@@ -8402,7 +8409,6 @@
 <translation id="934503638756687833">Do të hiqen edhe artikuj që nuk janë listuar këtu, nëse është e nevojshme. Mëso më shumë për &lt;a href="<ph name="URL" />"&gt;mbrojtjen ndaj softuerëve të padëshiruar&lt;/a&gt; në dokumentin informues të privatësisë së Chrome.</translation>
 <translation id="93480724622239549">Defekt në kod ose gabim</translation>
 <translation id="935854577147268200">Telefoni i Smart Lock ndryshoi. Fut fjalëkalimin për të përditësuar Smart Lock. Herën tjetër, telefoni yt do të shkyçë pajisjen tënde <ph name="DEVICE_TYPE" />. Mund të çaktivizosh Smart Lock te "Cilësimet"</translation>
-<translation id="93610034168535821">Hapësira ruajtëse në total e përdorur nga sajtet:</translation>
 <translation id="936646668635477464">Kamera dhe mikrofoni</translation>
 <translation id="936801553271523408">Të dhënat diagnostikuese të sistemit</translation>
 <translation id="93766956588638423">Riparo shtesën</translation>
diff --git a/chrome/app/resources/generated_resources_sr-Latn.xtb b/chrome/app/resources/generated_resources_sr-Latn.xtb
index af7a6a2..b4398129 100644
--- a/chrome/app/resources/generated_resources_sr-Latn.xtb
+++ b/chrome/app/resources/generated_resources_sr-Latn.xtb
@@ -2224,6 +2224,7 @@
 <translation id="3067198360141518313">Pokreni ovaj dodatak</translation>
 <translation id="3071624960923923138">Možete da kliknete ovde da biste otvorili novu karticu</translation>
 <translation id="3072775339180057696">Želite li da dozvolite sajtu da pregleda datoteku <ph name="FILE_NAME" />?</translation>
+<translation id="3074499504015191586">Prevedi celu stranicu</translation>
 <translation id="3075874217500066906">Potrebno je da ponovo pokrenete uređaj da bi započeo proces Powerwash-a. Kada ponovo pokrenete uređaj, zatražićemo da potvrdite da li želite da nastavite.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">Sačuvaj samo na ovom uređaju</translation>
@@ -5079,6 +5080,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> koristi kameru i mikrofon</translation>
 <translation id="5935158534896975820">Priprema se zahtev za potpisivanje sertifikata (čeka na serveru)</translation>
 <translation id="5935656526031444304">Upravljajte bezbednim pregledanjem</translation>
+<translation id="5936065461722368675">Prevedi celu stranicu</translation>
 <translation id="5938002010494270685">Bezbednosna nadogradnja je dostupna</translation>
 <translation id="5939518447894949180">Resetuj</translation>
 <translation id="5939719276406088041">Pravljenje prečice nije uspelo</translation>
@@ -8428,7 +8430,6 @@
 <translation id="934503638756687833">Ukloniće se i stavke koje nisu ovde navedene, ako je to potrebno. Saznajte više o &lt;a href="<ph name="URL" />"&gt;zaštiti od neželjenog softvera&lt;/a&gt; u beloj knjizi o privatnosti u Chrome-u.</translation>
 <translation id="93480724622239549">Problem ili greška</translation>
 <translation id="935854577147268200">Smart Lock telefon je promenjen. Unesite lozinku da biste ažurirali Smart Lock. Sledeći put će telefon otključati <ph name="DEVICE_TYPE" />. Možete da isključite Smart Lock u podešavanjima</translation>
-<translation id="93610034168535821">Ukupan memorijski prostor koji koriste sajtovi:</translation>
 <translation id="936646668635477464">Kamera i mikrofon</translation>
 <translation id="936801553271523408">Sistemski dijagnostički podaci</translation>
 <translation id="93766956588638423">Popravi dodatak</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb
index 09cdcbc..51f4041 100644
--- a/chrome/app/resources/generated_resources_sr.xtb
+++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -2224,6 +2224,7 @@
 <translation id="3067198360141518313">Покрени овај додатак</translation>
 <translation id="3071624960923923138">Можете да кликнете овде да бисте отворили нову картицу</translation>
 <translation id="3072775339180057696">Желите ли да дозволите сајту да прегледа датотеку <ph name="FILE_NAME" />?</translation>
+<translation id="3074499504015191586">Преведи целу страницу</translation>
 <translation id="3075874217500066906">Потребно је да поново покренете уређај да би започео процес Powerwash-а. Када поново покренете уређај, затражићемо да потврдите да ли желите да наставите.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">Сачувај само на овом уређају</translation>
@@ -5079,6 +5080,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> користи камеру и микрофон</translation>
 <translation id="5935158534896975820">Припрема се захтев за потписивање сертификата (чека на серверу)</translation>
 <translation id="5935656526031444304">Управљајте безбедним прегледањем</translation>
+<translation id="5936065461722368675">Преведи целу страницу</translation>
 <translation id="5938002010494270685">Безбедносна надоградња је доступна</translation>
 <translation id="5939518447894949180">Ресетуј</translation>
 <translation id="5939719276406088041">Прављење пречице није успело</translation>
@@ -8428,7 +8430,6 @@
 <translation id="934503638756687833">Уклониће се и ставке које нису овде наведене, ако је то потребно. Сазнајте више о &lt;a href="<ph name="URL" />"&gt;заштити од нежељеног софтвера&lt;/a&gt; у белој књизи о приватности у Chrome-у.</translation>
 <translation id="93480724622239549">Проблем или грешка</translation>
 <translation id="935854577147268200">Smart Lock телефон је промењен. Унесите лозинку да бисте ажурирали Smart Lock. Следећи пут ће телефон откључати <ph name="DEVICE_TYPE" />. Можете да искључите Smart Lock у подешавањима</translation>
-<translation id="93610034168535821">Укупан меморијски простор који користе сајтови:</translation>
 <translation id="936646668635477464">Камера и микрофон</translation>
 <translation id="936801553271523408">Системски дијагностички подаци</translation>
 <translation id="93766956588638423">Поправи додатак</translation>
diff --git a/chrome/app/resources/generated_resources_sv.xtb b/chrome/app/resources/generated_resources_sv.xtb
index 1a0b1bf..1354928 100644
--- a/chrome/app/resources/generated_resources_sv.xtb
+++ b/chrome/app/resources/generated_resources_sv.xtb
@@ -1923,6 +1923,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Ta bort 1 app som inte stöds}other{Ta bort # appar som inte stöds}}</translation>
 <translation id="2776560192867872731">Ändra enhetsnamn på <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Ta bort denna behållare</translation>
+<translation id="2778471504622896352">Lägg till fjärrappar i ChromeOS-startaren</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Ett fel uppstod när Linux-programmet skulle installeras</translation>
 <translation id="2783298271312924866">Nedladdad</translation>
@@ -3558,6 +3559,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> och <ph name="NUMBER_OF_OTHER_SWITCHES" /> brytare till</translation>
 <translation id="439266289085815679">Konfiguration av Bluetooth styrs av <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Redigera konfigurationsfilen</translation>
+<translation id="4393713825278446281">Enheter med Snabb parkoppling har sparats i <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Inaktivera</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Öppna alla}=1{&amp;Öppna bokmärke}other{&amp;Öppna alla ({COUNT})}}</translation>
 <translation id="4397372003838952832">Du behöver inte komma ihåg det här lösenordet. Det sparas i <ph name="GOOGLE_PASSWORD_MANAGER" /> för <ph name="EMAIL" />.</translation>
@@ -3788,6 +3790,7 @@
 <translation id="4615586811063744755">inga cookies har valts</translation>
 <translation id="461661862154729886">Energikälla</translation>
 <translation id="4617001782309103936">För kort</translation>
+<translation id="4617019240346358451">Läs in sidan igen för att använda <ph name="EXTENSION_NAME" /></translation>
 <translation id="4617270414136722281">Tilläggsalternativ</translation>
 <translation id="4617880081511131945">Det gick inte att upprätta en anslutning</translation>
 <translation id="4619564267100705184">Verifiera din identitet</translation>
@@ -4003,6 +4006,7 @@
 <translation id="4833683849865011483">1 skrivare från utskriftsservern hittades</translation>
 <translation id="4836504898754963407">Hantera fingeravtryck</translation>
 <translation id="4837128290434901661">Vill du byta tillbaka till Google Sök?</translation>
+<translation id="4837165100461973682">Läs in sidan igen för att tillämpa ändringarna</translation>
 <translation id="4837926214103741331">Du har inte behörighet att använda den här enheten. Kontakta enhetens ägare om du vill ha behörighet att logga in.</translation>
 <translation id="4837952862063191349">Lås upp och återställ lokal data genom att ange ditt gamla lösenord för <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Visa bilder, mediefiler och aviseringar från telefonen</translation>
@@ -4312,6 +4316,7 @@
 <translation id="5150254825601720210">SSL-servernamn för Netscape-certifikat</translation>
 <translation id="5151354047782775295">Frigör diskutrymme, annars tas en del data bort automatiskt.</translation>
 <translation id="5153234146675181447">Glöm mobil</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Avancerade inställningar för <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Ämne</translation>
 <translation id="5155327081870541046">Skriv genvägen till webbplatsen du vill söka på i adressfältet, till exempel @bookmarks. Tryck sedan på önskat kortkommando och ange söktermen.</translation>
@@ -5947,6 +5952,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> har lagts till via fjärranslutning</translation>
 <translation id="6790820461102226165">Lägg till person …</translation>
 <translation id="6793604637258913070">Markera textmarkören när den visas eller flyttas</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">Med automatisk genomsökning kan du flytta mellan objekt på skärmen automatiskt. När ett objekt är markerat trycker du på Välj för att aktivera det.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Hoppsan! Ett fel uppstod.</translation>
@@ -7820,6 +7826,7 @@
 <translation id="8642947597466641025">Förstora texten</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> kan vara farlig. Vill du skicka den till Avancerat skydd från Google för skanning?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Inga cookies}=1{1 cookie blockeras}other{# cookies blockeras}}</translation>
+<translation id="864423554496711319">Enheter som har sparats i kontot</translation>
 <translation id="8644655801811752511">Det går inte att återställa den här säkerhetsnyckeln. Testa att återställa nyckeln direkt när du sätter i den.</translation>
 <translation id="8645354835496065562">Fortsätt att tillåta sensoråtkomst</translation>
 <translation id="8645920082661222035">Förutser och varnar dig om farliga händelser innan de inträffar</translation>
@@ -8424,7 +8431,6 @@
 <translation id="934503638756687833">Även objekt som inte står med här tas bort om det behövs. Läs mer om &lt;a href="<ph name="URL" />"&gt;skydd mot oönskad programvara&lt;/a&gt; i vitboken om integritet och Chrome.</translation>
 <translation id="93480724622239549">Problem eller fel</translation>
 <translation id="935854577147268200">Smart Lock används med en annan mobil än tidigare. Ange lösenordet och uppdatera Smart Lock. Nästa gång låser mobilen upp denna <ph name="DEVICE_TYPE" />. Du kan inaktivera Smart Lock i inställningarna</translation>
-<translation id="93610034168535821">Totalt lagringsutrymme som används av webbplatser:</translation>
 <translation id="936646668635477464">Kamera och mikrofon</translation>
 <translation id="936801553271523408">Systemets diagnostikresultat</translation>
 <translation id="93766956588638423">Reparera tillägg</translation>
diff --git a/chrome/app/resources/generated_resources_sw.xtb b/chrome/app/resources/generated_resources_sw.xtb
index 0278f6b1..9f6bbb7 100644
--- a/chrome/app/resources/generated_resources_sw.xtb
+++ b/chrome/app/resources/generated_resources_sw.xtb
@@ -1920,6 +1920,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Ondoa programu 1 isiyotumika}other{Ondoa programu # zisizotumika}}</translation>
 <translation id="2776560192867872731">Badilisha jina la kifaa kiitwacho <ph name="DEVICE_NAME" /></translation>
 <translation id="2777251078198759550">Futa metadata hii</translation>
+<translation id="2778471504622896352">Weka programu zinazotumika kutoka mbali kwenye kifungua programu cha ChromeOS</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Hitilafu imetokea wakati wa kusakinisha programu ya Linux</translation>
 <translation id="2783298271312924866">Imepakuliwa</translation>
@@ -3553,6 +3554,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> na swichi zingine <ph name="NUMBER_OF_OTHER_SWITCHES" /></translation>
 <translation id="439266289085815679">Mipangilio ya Bluetooth inadhibitiwa na <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Badilisha faili ya mipangilio</translation>
+<translation id="4393713825278446281">Vifaa vya Kuoanisha Haraka vilivyohifadhiwa katika <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Zima</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Fungua zote}=1{&amp;Fungua alamisho}other{&amp;Fungua zote ({COUNT})}}</translation>
 <translation id="4397372003838952832">Hutahitaji kukumbuka nenosiri hili. Litahifadhiwa kwenye <ph name="GOOGLE_PASSWORD_MANAGER" /> kwa ajili ya <ph name="EMAIL" />.</translation>
@@ -3783,6 +3785,7 @@
 <translation id="4615586811063744755">hakuna vidakuzi vilivyochaguliwa</translation>
 <translation id="461661862154729886">Chanzo cha nishati</translation>
 <translation id="4617001782309103936">Ni fupi mno</translation>
+<translation id="4617019240346358451">Pakia upya ukurasa ili utumie "<ph name="EXTENSION_NAME" />"</translation>
 <translation id="4617270414136722281">Chaguo za viendelezi</translation>
 <translation id="4617880081511131945">Imeshindwa kuunganisha kwenye simu</translation>
 <translation id="4619564267100705184">Thibitisha kwamba ni wewe</translation>
@@ -3998,6 +4001,7 @@
 <translation id="4833683849865011483">Imepata printa moja kwenye seva ya kuchapisha</translation>
 <translation id="4836504898754963407">Dhibiti vitambulisho</translation>
 <translation id="4837128290434901661">Ungependa kurudi kwenye huduma ya Tafuta na Google?</translation>
+<translation id="4837165100461973682">Pakia upya ukurasa ili utekeleze mabadiliko uliyofanya</translation>
 <translation id="4837926214103741331">Huruhusiwi kukitumia kifaa hiki. Tafadhali wasiliana na mmiliki wa kifaa kwa ruhusa ya kuingia katika akaunti.</translation>
 <translation id="4837952862063191349">Ili ufungue na kurejesha data yako ya karibu, tafadhali weka nenosiri lako la zamani la <ph name="DEVICE_TYPE" />.</translation>
 <translation id="4838170306476614339">Angalia picha, maudhui na arifa za simu yako.</translation>
@@ -4307,6 +4311,7 @@
 <translation id="5150254825601720210">Jina la Seva ya SSL ya Cheti cha Netscape</translation>
 <translation id="5151354047782775295">Futa maudhui katika hifadhi ya diski au data iliyochaguliwa itafutwa kiotomatiki</translation>
 <translation id="5153234146675181447">Sahau simu</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722">Mipangilio ya kina ya <ph name="PRINTING_DESTINATION" /></translation>
 <translation id="5154702632169343078">Mada</translation>
 <translation id="5155327081870541046">Katika sehemu ya anwani, weka njia ya mkato ya tovuti unayotaka kutafuta, kama vile "@alamisho". Kisha, bonyeza mikato ya kibodi unayopendelea na uweke hoja yako ya utafutaji.</translation>
@@ -5942,6 +5947,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> iliongezwa kwa mbali</translation>
 <translation id="6790820461102226165">Ongeza Mwingine...</translation>
 <translation id="6793604637258913070">Angazia kareti ya maandishi inapoonekana au kusonga</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">Kipengele cha kuchanganua kiotomatiki hukuwezesha kusogea kati ya vipengee mbalimbali kwenye skrini kiotomatiki. Kipengee kikishaangaziwa, bonyeza "Chagua" ili ufungue kipengee hicho.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Lo! Hitilafu fulani imetokea.</translation>
@@ -7816,6 +7822,7 @@
 <translation id="8642947597466641025">Fanya Matini Kuwa Makubwa</translation>
 <translation id="8643443571868262066">Huenda <ph name="FILE_NAME" /> ni hatari. Ungependa kuituma kwenye mipangilio ya Ulinzi wa Hali ya Juu kutoka Google ili ikaguliwe?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Hakuna vidakuzi}=1{Kidakuzi kimoja kimezuiwa}other{Vidakuzi # vimezuiwa}}</translation>
+<translation id="864423554496711319">Vifaa vilivyohifadhiwa katika akaunti yako</translation>
 <translation id="8644655801811752511">Huruhusiwi kubadilisha ufunguo huu wa usalama. Jaribu kubadilisha ufunguo mara tu baada ya kuuweka.</translation>
 <translation id="8645354835496065562">Endelea kuruhusu ufikiaji wa vitambuzi</translation>
 <translation id="8645920082661222035">Hutabiri na kukuonya kuhusu matukio hatari kabla yatendeke</translation>
@@ -8420,7 +8427,6 @@
 <translation id="934503638756687833">Vipengee ambavyo havijaorodheshwa hapa pia vitaondolewa, panapohitajika. Pata maelezo zaidi kuhusu &lt;a href="<ph name="URL" />"&gt;ulinzi dhidi ya programu zisizohitajika&lt;/a&gt; katika ripoti rasmi na ya faragha ya Chrome.</translation>
 <translation id="93480724622239549">Hitilafu</translation>
 <translation id="935854577147268200">Umebadilisha simu inayotumia Smart Lock. Weka nenosiri lako ili usasishe Smart Lock. Wakati ujao, simu yako itafungua <ph name="DEVICE_TYPE" /> yako. Unaweza kuzima Smart Lock katika Mipangilio</translation>
-<translation id="93610034168535821">Jumla ya hifadhi iliyotumiwa na tovuti:</translation>
 <translation id="936646668635477464">Kamera na maikrofoni</translation>
 <translation id="936801553271523408">Data ya uchungzi wa mfumo</translation>
 <translation id="93766956588638423">Karabati kiendelezi</translation>
diff --git a/chrome/app/resources/generated_resources_ta.xtb b/chrome/app/resources/generated_resources_ta.xtb
index 5ed4ec9..7ab386e 100644
--- a/chrome/app/resources/generated_resources_ta.xtb
+++ b/chrome/app/resources/generated_resources_ta.xtb
@@ -1558,6 +1558,7 @@
 <translation id="2433836460518180625">சாதனத்தை மட்டும் அன்லாக் செய்</translation>
 <translation id="2434449159125086437">பிரிண்டரை அமைக்க இயலவில்லை. உள்ளமைவைச் சரிபார்த்து மீண்டும் முயலவும்.</translation>
 <translation id="2434758125294431199">யாரெல்லாம் உங்களுடன் பகிரலாம் என்பதைத் தேர்ந்தெடுங்கள்</translation>
+<translation id="2434915728183570229">இப்போது, உங்கள் மொபைலில் உள்ள ஆப்ஸைப் பார்க்கலாம்</translation>
 <translation id="2435137177546457207">Google Chrome &amp; ChromeOS Flex தொடர்பான கூடுதல் விதிமுறைகள்</translation>
 <translation id="2435248616906486374">நெட்வொர்க் துண்டிக்கப்பட்டது</translation>
 <translation id="2435457462613246316">கடவுச்சொல்லைக் காண்பி</translation>
@@ -1923,6 +1924,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{ஆதரிக்கப்படாத 1 ஆப்ஸை அகற்றுங்கள்}other{ஆதரிக்கப்படாத # ஆப்ஸை அகற்றுங்கள்}}</translation>
 <translation id="2776560192867872731"><ph name="DEVICE_NAME" /> இன் பெயரை மாற்றும்</translation>
 <translation id="2777251078198759550">இந்தக் கண்டெய்னரை நீக்கு</translation>
+<translation id="2778471504622896352">ChromeOS தொடக்கியில் ரிமோட் ஆப்ஸைச் சேருங்கள்</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">ஒரு Linux ஆப்ஸை நிறுவும்போது பிழை நேர்ந்தது</translation>
 <translation id="2783298271312924866">பதிவிறக்கப்பட்டது</translation>
@@ -2238,6 +2240,7 @@
 <translation id="3067198360141518313">இந்தச் செருகுநிரலை இயக்கு</translation>
 <translation id="3071624960923923138">புதிய தாவலைத் திறக்க, இங்கே கிளிக் செய்யவும்</translation>
 <translation id="3072775339180057696"><ph name="FILE_NAME" /> ஐப் பார்க்க வலைதளத்தை அனுமதிக்கவா?</translation>
+<translation id="3074499504015191586">அனைத்தையும் மொழிபெயர்</translation>
 <translation id="3075874217500066906">பவர்வாஷ் செயல்முறையைத் தொடங்க மறுதுவக்கம் தேவை. மீண்டும் துவக்கிய பின், தொடர்வதை உறுதிபடுத்தக் கேட்கப்படுவீர்கள்.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">இந்தச் சாதனத்தில் மட்டும் சேமியுங்கள்</translation>
@@ -3558,6 +3561,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" />, மேலும் <ph name="NUMBER_OF_OTHER_SWITCHES" /> ஸ்விட்சுகள்</translation>
 <translation id="439266289085815679">புளூடூத் உள்ளமைவைக் கட்டுப்படுத்துபவர்: <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">உள்ளமைவு ஃபைலைத் திருத்தும்</translation>
+<translation id="4393713825278446281"><ph name="PRIMARY_EMAIL" /> இல் சேமிக்கப்பட்டுள்ள சாதனங்களைத் துரிதமாக இணைக்கலாம்</translation>
 <translation id="4394049700291259645">முடக்கு</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;எல்லாவற்றையும் திற}=1{&amp;புக்மார்க்கைத் திற}other{&amp;எல்லாவற்றையும் ({COUNT}) திற}}</translation>
 <translation id="4397372003838952832">இந்தக் கடவுச்சொல்லை நீங்கள் நினைவில் வைத்திருக்க வேண்டிய அவசியமில்லை. இது <ph name="EMAIL" /> கணக்கின் <ph name="GOOGLE_PASSWORD_MANAGER" /> இல் சேமிக்கப்படும்.</translation>
@@ -3788,6 +3792,7 @@
 <translation id="4615586811063744755">குக்கீ எதுவும் தேர்ந்தெடுக்கப்படவில்லை</translation>
 <translation id="461661862154729886">மின்சக்தி மூலம்</translation>
 <translation id="4617001782309103936">மிகவும் சிறிதாக உள்ளது</translation>
+<translation id="4617019240346358451">"<ph name="EXTENSION_NAME" />" நீட்டிப்பைப் பயன்படுத்த, பக்கத்தை ரெஃப்ரெஷ் செய்யுங்கள்</translation>
 <translation id="4617270414136722281">நீட்டிப்பு விருப்பங்கள்</translation>
 <translation id="4617880081511131945">இணைப்பை ஏற்படுத்த முடியவில்லை</translation>
 <translation id="4619564267100705184">இது நீங்கள்தான் என உறுதிசெய்யுங்கள்</translation>
@@ -4003,6 +4008,7 @@
 <translation id="4833683849865011483">பிரிண்ட் சேவையகத்தில் ஒரு பிரிண்டர் உள்ளது</translation>
 <translation id="4836504898754963407">கைரேகைகளை நிர்வகிக்கவும்</translation>
 <translation id="4837128290434901661">மீண்டும் Google Search என அமைக்கவா?</translation>
+<translation id="4837165100461973682">மாற்றங்களைப் பயன்படுத்த, பக்கத்தை ரெஃப்ரெஷ் செய்யுங்கள்</translation>
 <translation id="4837926214103741331">இந்தச் சாதனத்தைப் பயன்படுத்த, உங்களுக்கு அங்கீகாரம் இல்லை. உள்நுழைவு அனுமதியைப் பெற, சாதன உரிமையாளரைத் தொடர்பு கொள்ளவும்.</translation>
 <translation id="4837952862063191349">உங்கள் அகக் கணினியின் தரவை அன்லாக் செய்து, மீட்டெடுக்க, <ph name="DEVICE_TYPE" /> இன் பழைய கடவுச்சொல்லை உள்ளிடவும்.</translation>
 <translation id="4838170306476614339">மொபைலில் உள்ள படங்கள், மீடியா, அறிவிப்புகள் ஆகியவற்றைப் பார்க்கலாம்</translation>
@@ -4238,6 +4244,7 @@
 <translation id="5072900412896857127">Google Play சேவை விதிமுறைகளை ஏற்ற முடியவில்லை. நெட்வொர்க் இணைப்பைச் சரிபார்த்து, மீண்டும் முயலவும்.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" />, மேலும் #}}</translation>
 <translation id="5074318175948309511">புதிய அமைப்புகளைச் செயல்படுத்துவதற்கு முன், இந்தப் பக்கம் மீண்டும் ஏற்றப்பட வேண்டியிருக்கும்.</translation>
+<translation id="5074761966806028321">அமைவை நிறைவுசெய்ய இன்னமும் அனுமதி அவசியம்</translation>
 <translation id="5075910247684008552">பாதுகாக்கப்பட்ட தளங்களில் பாதுகாப்பற்ற உள்ளடக்கம் இயல்பாகவே தடுக்கப்படும்</translation>
 <translation id="5078638979202084724">அனைத்து தாவல்களையும் புக்மார்க்கிடுக</translation>
 <translation id="5078796286268621944">தவறான PIN</translation>
@@ -4312,6 +4319,7 @@
 <translation id="5150254825601720210">Netscape சான்றிதழ் SSL சேவையகப் பெயர்</translation>
 <translation id="5151354047782775295">சாதனத்தில் காலி இடத்தை உருவாக்கவும் அல்லது குறிப்பிட்ட தரவு தானாகவே நீக்கப்படலாம்</translation>
 <translation id="5153234146675181447">ஃபோனை அகற்றும்</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722"><ph name="PRINTING_DESTINATION" /> க்கான மேம்பட்ட அமைப்புகள்</translation>
 <translation id="5154702632169343078">பொருள்</translation>
 <translation id="5155327081870541046">தேட விரும்பும் தளத்திற்கான ஷார்ட்கட்டை முகவரிப் பட்டியில் டைப் செய்யவும் (எ.கா. "@bookmarks"). அதன்பிறகு உங்களுக்கு விருப்பமான கீபோர்டு ஷார்ட்கட்டை அழுத்தி தேடல் வார்த்தையை டைப் செய்யவும்.</translation>
@@ -4600,6 +4608,7 @@
 <translation id="5449551289610225147">தவறான கடவுச்சொல்</translation>
 <translation id="5449588825071916739">எல்லா தாவல்களையும் புக்மார்க்கிடுக</translation>
 <translation id="5449716055534515760">Close Win&amp;dow</translation>
+<translation id="5452446625764825792">இப்போது, உங்கள் மொபைலில் உள்ள சமீபத்திய படங்கள், மீடியா, ஆப்ஸ் ஆகியவற்றைப் பார்க்கலாம்</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (ஆஃப்லைனிலும் பயன்படுத்தலாம்)</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" /> உடன்</translation>
 <translation id="545484289444831485">கூடுதல் தேடல் முடிவுகளைக் காட்டு</translation>
@@ -4660,6 +4669,7 @@
 <translation id="5499211612787418966">இந்த உரையாடல் தற்போது ஃபோகஸ் செய்யப்படவில்லை. இதை ஃபோகஸ் செய்ய, Alt-Shift-A அழுத்தவும்.</translation>
 <translation id="5499313591153584299">இந்த ஃபைல் உங்கள் கம்ப்யூட்டருக்குத் தீங்கு விளைவிக்கலாம்.</translation>
 <translation id="5499453227627332024">Linux கண்டெய்னருக்கான மேம்படுத்தல் உள்ளது. அமைப்புகள் ஆப்ஸிலிருந்தும் பின்னர் மேம்படுத்திக்கொள்ளலாம்.</translation>
+<translation id="5499476581866658341">இப்போது, உங்கள் மொபைலில் உள்ள சமீபத்திய படங்கள், மீடியா ஆகியவற்றைப் பார்க்கலாம்</translation>
 <translation id="549957179819296104">புதிய ஐகான்</translation>
 <translation id="5500168250243071806">நீங்கள் உள்நுழைந்திருக்கும்போது, <ph name="BEGIN_LINK_SEARCH" />தேடல் விவரங்களும்<ph name="END_LINK_SEARCH" /> <ph name="BEGIN_LINK_GOOGLE" />பிற வகையான செயல்பாடுகளும்<ph name="END_LINK_GOOGLE" /> உங்கள் Google கணக்கில் சேமிக்கப்பட்டிருக்கலாம். அவற்றை எப்போது வேண்டுமானாலும் நீக்கலாம்.</translation>
 <translation id="5500709606820808700">பாதுகாப்புச் சரிபார்ப்பு இன்று மேற்கொள்ளப்பட்டது</translation>
@@ -5088,6 +5098,7 @@
 <translation id="5933522550144185133">கேமராவையும் மைக்ரோஃபோனையும் <ph name="APP_NAME" /> பயன்படுத்துகிறது</translation>
 <translation id="5935158534896975820">சான்றிதழ் கையொப்பக் கோரிக்கையைத் தயார் செய்கிறது (சேவையகத்தில் காத்திருக்கிறது)</translation>
 <translation id="5935656526031444304">பாதுகாப்பு உலாவலை நிர்வகிக்க உதவும்</translation>
+<translation id="5936065461722368675">அனைத்தையும் மொழிபெயர்</translation>
 <translation id="5938002010494270685">பாதுகாப்பு மேம்படுத்தல் புதுப்பிப்பு உள்ளது</translation>
 <translation id="5939518447894949180">மீட்டமை</translation>
 <translation id="5939719276406088041">ஷார்ட்கட்டை உருவாக்க முடியவில்லை</translation>
@@ -5948,6 +5959,7 @@
 <translation id="6790497603648687708">தொலைநிலையில் <ph name="EXTENSION_NAME" /> சேர்க்கப்பட்டது</translation>
 <translation id="6790820461102226165">நபரைச் சேர்...</translation>
 <translation id="6793604637258913070">கர்சர் தோன்றும் போது அல்லது நகரும் போது, அதைத் தனிப்படுத்து</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">திரையில் இருப்பவற்றைத் தானாகவே ஒவ்வொன்றாக ஃபோகஸ் செய்ய ‘தானியங்கு ஸ்கேன்’ அம்சம் அனுமதிக்கிறது. உங்களுக்குத் தேவையானது ஹைலைட் செய்யப்பட்டதும் அதை இயக்க, “தேர்ந்தெடு” ஸ்விட்ச்சை அழுத்தவும்.</translation>
 <translation id="6795884519221689054">பாண்டா</translation>
 <translation id="6797493596609571643">அச்சச்சோ, ஏதோ தவறு ஏற்பட்டது.</translation>
@@ -6324,6 +6336,7 @@
 <translation id="7152478047064750137">இந்த நீட்டிப்பிற்குச் சிறப்பு அனுமதிகள் தேவையில்லை</translation>
 <translation id="7154130902455071009">உங்கள் தொடக்கப் பக்கத்தை இதற்கு மாற்றவும்: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">கேமரா அல்லது ஃபைலில் இருக்கும் படம்</translation>
+<translation id="7160182524506337403">இப்போது, உங்கள் மொபைலில் உள்ள அறிவிப்புகளைப் பார்க்கலாம்</translation>
 <translation id="7163202347044721291">செயல்படுத்தல் குறியீட்டைச் சரிபார்க்கிறது...</translation>
 <translation id="716640248772308851">தேர்வுசெய்யப்பட்ட இடங்களில் உள்ள படங்கள், வீடியோ மற்றும் ஒலி ஃபைல்கள்  ஆகியவற்றை "<ph name="EXTENSION" />" ஆல் படிக்க முடியும்.</translation>
 <translation id="7167486101654761064">&amp;எப்போதும் இந்த வகை ஃபைல்களைத் திற</translation>
@@ -7339,6 +7352,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> நிலை</translation>
 <translation id="8139447493436036221">Google Drive ஃபைல்கள் </translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">ஃபோன் ஹப் அமைப்புகளில் இன்னும் கூடுதலான அம்சங்களை அமைக்கலாம்</translation>
 <translation id="8141584439523427891">மாற்று உலாவியில் இப்போது திறக்கிறது</translation>
 <translation id="8141725884565838206">உங்கள் கடவுச்சொற்களை நிர்வகிக்கவும்</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{ஒரு வீடியோவை}other{# வீடியோக்களை}}</translation>
@@ -7546,6 +7560,7 @@
 <translation id="833986336429795709">இந்த இணைப்பைத் திறக்க, ஆப்ஸைத் தேர்வுசெய்யும்</translation>
 <translation id="8342221978608739536">பயன்படுத்திப் பார்க்கவில்லை</translation>
 <translation id="8342861492835240085">தொகுப்பைத் தேர்ந்தெடு</translation>
+<translation id="8345848587667658367">இப்போது, உங்கள் மொபைலில் உள்ள சமீபத்திய படங்கள், மீடியா, அறிவிப்புகள், ஆப்ஸ் ஆகியவற்றைப் பார்க்கலாம்</translation>
 <translation id="8347227221149377169">அச்சுப் பணிகள்</translation>
 <translation id="834785183489258869">மறைநிலையில் உள்ளபோது, விளம்பரங்களைப் பிரத்தியேகமாக்குவது போன்ற செயல்களைச் செய்வதற்காக வெவ்வேறு தளங்களில் உங்கள் உலாவல் செயல்பாட்டைப் பார்க்க, தளங்களால் குக்கீகளைப் பயன்படுத்த முடியாது. சில தளங்களில் உள்ள குறிப்பிட்ட அம்சங்கள் செயல்படாமல் போகக்கூடும்.</translation>
 <translation id="8350789879725387295">டாக்கிலுள்ள ஸ்டைலஸ் கருவிகள்</translation>
@@ -7821,6 +7836,7 @@
 <translation id="8642947597466641025">உரையை இன்னும் பெரிதாக்கு</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> ஆபத்தானதாக இருக்கக்கூடும். ஸ்கேன் செய்வதற்கு Google மேம்பட்ட பாதுகாப்புக்கு அனுப்ப வேண்டுமா?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{குக்கீகள் எதுவுமில்லை}=1{1 குக்கீ தடுக்கப்பட்டுள்ளது}other{# குக்கீகள் தடுக்கப்பட்டுள்ளன}}</translation>
+<translation id="864423554496711319">உங்கள் கணக்கில் சேமிக்கப்பட்டுள்ள சாதனங்கள்</translation>
 <translation id="8644655801811752511">இந்தப் பாதுகாப்பு விசையை மீட்டமைக்க முடியவில்லை. விசையைச் செருகிய உடனே அதை மீட்டமைக்க முயலவும்.</translation>
 <translation id="8645354835496065562">தொடர்ந்து சென்சார் அணுகலை அனுமதி</translation>
 <translation id="8645920082661222035">ஆபத்தான நிகழ்வுகள் ஏற்படுவதற்கு முன்பு அவற்றைக் கணித்து உங்களை எச்சரிக்கும்</translation>
@@ -8150,6 +8166,7 @@
 <translation id="8957757410289731985">சுயவிவரத்தைப் பிரத்தியேகமாக்கலாம்</translation>
 <translation id="895944840846194039">JavaScript நினைவகம்</translation>
 <translation id="8960208913905765425">‘விரைவான பதில்கள்’ அம்சம் வழங்கும் அலகு மாற்றம்</translation>
+<translation id="8960638196855923532">இப்போது, உங்கள் மொபைலில் உள்ள அறிவிப்புகள், ஆப்ஸ் ஆகியவற்றைப் பார்க்கலாம்</translation>
 <translation id="8962051932294470566">ஒரே நேரத்தில் ஒரு ஃபைலை மட்டுமே பகிர முடியும். தற்போதைய பகிர்வு முடிந்த பிறகு மீண்டும் முயலவும்.</translation>
 <translation id="8962083179518285172">விவரங்களை மறை</translation>
 <translation id="8962918469425892674">நகர்வு அல்லது ஒளி சென்சார்களை இந்தத் தளம் பயன்படுத்துகிறது.</translation>
@@ -8301,6 +8318,7 @@
 <translation id="9103868373786083162">பின்னே செல்ல அழுத்தவும், வரலாற்றைக் காட்டும் சூழல் மெனு</translation>
 <translation id="9108035152087032312">சாளரத்திற்குப் பெயரிடுக...</translation>
 <translation id="9108072915170399168">தற்போது டேட்டா உபயோக அமைப்பு ‘இணைய இணைப்பு இல்லாமல்’ என அமைக்கப்பட்டுள்ளது</translation>
+<translation id="9108294543511800041">இப்போது, உங்கள் மொபைலில் உள்ள சமீபத்திய படங்கள், மீடியா, அறிவிப்புகள் ஆகியவற்றைப் பார்க்கலாம்</translation>
 <translation id="9108674852930645435"><ph name="DEVICE_TYPE" /> இல் புதிதாகச் சேர்க்கப்பட்டுள்ளவை</translation>
 <translation id="9108808586816295166">பாதுகாப்பான DNS எப்போதும் கிடைக்காமல் போகலாம்</translation>
 <translation id="9109122242323516435">இடத்தைக் காலியாக்க, சாதனத்தின் சேமிப்பகத்தில் இருந்து கோப்புகளை நீக்கவும்.</translation>
@@ -8425,7 +8443,6 @@
 <translation id="934503638756687833">தேவைப்பட்டால், இங்கே பட்டியலிடப்படாத உருப்படிகளும் அகற்றப்படும். Chrome தனியுரிமைத் தகவல் கையேட்டில் &lt;a href="<ph name="URL" />"&gt;தேவையற்ற மென்பொருளிலிருந்து பாதுகாப்பு&lt;/a&gt; பற்றி மேலும் அறிக.</translation>
 <translation id="93480724622239549">சிக்கல் அல்லது பிழை</translation>
 <translation id="935854577147268200">Smart Lock மொபைல் மாற்றப்பட்டது. Smart Lockகைப் புதுப்பிக்க, கடவுச்சொல்லை உள்ளிடவும். அடுத்த முறை, உங்கள் மொபைலானது <ph name="DEVICE_TYPE" /> சாதனத்தை அன்லாக் செய்யும். அமைப்புகளுக்குச் சென்று, Smart Lockகை முடக்கலாம்</translation>
-<translation id="93610034168535821">தளங்கள் பயன்படுத்தும் மொத்தச் சேமிப்பகம்:</translation>
 <translation id="936646668635477464">கேமரா &amp; மைக்ரோஃபோன்</translation>
 <translation id="936801553271523408">முறைமை பகுப்பாய்வு தரவு</translation>
 <translation id="93766956588638423">நீட்டிப்பைப் பழுதுநீக்கு</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb
index 18dc893..345ae243 100644
--- a/chrome/app/resources/generated_resources_te.xtb
+++ b/chrome/app/resources/generated_resources_te.xtb
@@ -1557,6 +1557,7 @@
 <translation id="2433836460518180625">పరికరాన్ని మాత్రం అన్‌లాక్ చేయండి</translation>
 <translation id="2434449159125086437">ప్రింటర్‌ను సెటప్ చేయలేకపోయింది. దయచేసి కాన్ఫిగరేషన్‌ను సరిచూసుకుని, ఆపై మళ్లీ ప్రయత్నించండి.</translation>
 <translation id="2434758125294431199">మీతో ఎవరు షేర్ చేయవచ్చో ఎంచుకోండి</translation>
+<translation id="2434915728183570229">మీరు ఇప్పుడు మీ ఫోన్ యాప్‌లను చూడవచ్చు</translation>
 <translation id="2435137177546457207">Google Chrome, ChromeOS Flexల అదనపు నియమాలు</translation>
 <translation id="2435248616906486374">నెట్‌వర్క్ డిస్‌కనెక్ట్ అయింది</translation>
 <translation id="2435457462613246316">పాస్‌వర్డ్‌ను చూపించు</translation>
@@ -1922,6 +1923,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{సపోర్ట్ చేయని 1 యాప్‌ను తీసివేయండి}other{సపోర్ట్ చేయని # యాప్‌లను తీసివేయండి}}</translation>
 <translation id="2776560192867872731"><ph name="DEVICE_NAME" /> పరికర పేరును మార్చండి</translation>
 <translation id="2777251078198759550">ఈ కంటైనర్‌ను తొలగించండి</translation>
+<translation id="2778471504622896352">ChromeOS లాంచర్‌కు రిమోట్ యాప్‌లను జోడించండి</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Linux అప్లికేషన్‌ను ఇన్‌స్టాల్ చేయడంలో ఎర్రర్</translation>
 <translation id="2783298271312924866">డౌన్‌లోడ్ చేయబడింది</translation>
@@ -2237,6 +2239,7 @@
 <translation id="3067198360141518313">ఈ ప్లగ్ఇన్‌ను అమలు చేయి</translation>
 <translation id="3071624960923923138">మీరు కొత్త ట్యాబ్‌ను తెరవడానికి ఇక్కడ క్లిక్ చేయవచ్చు</translation>
 <translation id="3072775339180057696"><ph name="FILE_NAME" />ను చూడటానికి సైట్‌ను అనుమతించాలనుకుంటున్నారా?</translation>
+<translation id="3074499504015191586">మొత్తం పేజీని అనువదించండి</translation>
 <translation id="3075874217500066906">పవర్‌వాష్ ప్రక్రియను మొదలుపెట్టడానికి పునఃప్రారంభించడం అవసరం. పునఃప్రారంభించిన తర్వాత మీరు కొనసాగించాలనుకుంటున్నారో లేదో నిర్ధారించమని మిమ్మల్ని అడగడం జరుగుతుంది.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">ఈ పరికరంలో మాత్రమే సేవ్ చేయండి</translation>
@@ -3328,7 +3331,7 @@
 <translation id="4144468798716165316">క్విక్ కమాండ్స్</translation>
 <translation id="4146026355784316281">ఎల్లప్పుడూ సిస్టమ్ వ్యూయర్‌తో తెరువు</translation>
 <translation id="4146785383423576110">రీసెట్ చేసి హానికరమైన వాటిని తీసివేయండి</translation>
-<translation id="4147897805161313378">Google ఫోటోలు</translation>
+<translation id="4147897805161313378">Google Photos</translation>
 <translation id="4147911968024186208">దయచేసి మళ్లీ ప్రయత్నించండి. మీకు ఈ ఎర్రర్ మళ్లీ కనిపిస్తే, దయచేసి మీ మద్దతు ప్రతినిధిని సంప్రదించండి.</translation>
 <translation id="4150201353443180367">డిస్‌ప్లే</translation>
 <translation id="4150569944729499860">స్క్రీన్ కాంటెక్ట్స్</translation>
@@ -3557,6 +3560,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" />, మరో <ph name="NUMBER_OF_OTHER_SWITCHES" /> స్విచ్‌లు</translation>
 <translation id="439266289085815679">బ్లూటూత్ కాన్ఫిగరేషన్ <ph name="USER_EMAIL" /> ద్వారా నియంత్రించబడుతుంది.</translation>
 <translation id="4392896746540753732">కాన్ఫిగరేషన్ ఫైల్‌ను ఎడిట్ చేయండి</translation>
+<translation id="4393713825278446281">ఫాస్ట్ పెయిర్ పరికరాలు <ph name="PRIMARY_EMAIL" />‌లో సేవ్ చేయబడ్డాయి</translation>
 <translation id="4394049700291259645">నిలిపివేయి</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{అన్నింటినీ &amp;తెరువు}=1{బుక్‌మార్క్‌ను &amp;తెరువు}other{అన్నింటినీ ({COUNT}) &amp;తెరువు}}</translation>
 <translation id="4397372003838952832">మీరు ఈ పాస్‌వర్డ్‌ను గుర్తుపెట్టుకోవాల్సిన అవసరం లేదు. ఇది <ph name="EMAIL" /> కోసం <ph name="GOOGLE_PASSWORD_MANAGER" />‌కు సేవ్ చేయబడుతుంది.</translation>
@@ -3787,6 +3791,7 @@
 <translation id="4615586811063744755">కుక్కీలను ఎంచుకోలేదు</translation>
 <translation id="461661862154729886">పవర్ సోర్స్</translation>
 <translation id="4617001782309103936">ఇది మరీ చిన్నది</translation>
+<translation id="4617019240346358451">"<ph name="EXTENSION_NAME" />"‌ను ఉపయోగించడానికి పేజీని రీలోడ్ చేయండి</translation>
 <translation id="4617270414136722281">ఎక్స్‌టెన్షన్ ఆప్షన్‌లు</translation>
 <translation id="4617880081511131945">కనెక్షన్‌ను ఏర్పాటు చేయడం సాధ్యపడలేదు</translation>
 <translation id="4619564267100705184">ఇది మీరే అని వెరిఫై చేయండి</translation>
@@ -4002,6 +4007,7 @@
 <translation id="4833683849865011483">ప్రింట్ సర్వర్ నుండి 1 ప్రింటర్ కనుగొనబడింది</translation>
 <translation id="4836504898754963407">వేలిముద్రలను నిర్వహించండి</translation>
 <translation id="4837128290434901661">తిరిగి Google Searchకు మార్చాలా?</translation>
+<translation id="4837165100461973682">మీ మార్పులను వర్తింపజేయడానికి పేజీని రీలోడ్ చేయండి</translation>
 <translation id="4837926214103741331">ఈ పరికరాన్ని ఉపయోగించడానికి మీకు అధికారం లేదు. దయచేసి సైన్-ఇన్ అనుమతి కోసం పరికర యజమానిని సంప్రదించండి.</translation>
 <translation id="4837952862063191349">మీ స్థానిక డేటాను అన్‌లాక్ చేసి పునరుద్ధరించడానికి, దయచేసి మీ పాత <ph name="DEVICE_TYPE" /> పాస్‌వర్డ్‌ను నమోదు చేయండి.</translation>
 <translation id="4838170306476614339">మీ ఫోన్‌లోని ఫోటోలు, మీడియా, నోటిఫికేషన్‌లను చూడండి</translation>
@@ -4237,6 +4243,7 @@
 <translation id="5072900412896857127">Google Play సర్వీస్ నియమాలను లోడ్ చేయడం సాధ్యపడదు. దయచేసి మీ నెట్‌వర్క్ కనెక్షన్‌ను చెక్ చేసి, ఆపై మళ్లీ ట్రై చేయండి.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" />, మరియు మరో #}}</translation>
 <translation id="5074318175948309511">కొత్త సెట్టింగ్‌లు ప్రభావంలోకి రావడానికి ముందు ఈ పేజీని మళ్లీ లోడ్ చేయాల్సి ఉండవచ్చు.</translation>
+<translation id="5074761966806028321">సెటప్‌ను పూర్తి చేయడానికి ఇప్పటికీ అనుమతి అవసరం</translation>
 <translation id="5075910247684008552">సురక్షితమైన సైట్‌లలో డిఫాల్ట్‌గానే అసురక్షితమైన కంటెంట్ బ్లాక్ చేయబడుతుంది</translation>
 <translation id="5078638979202084724">అన్ని ట్యాబ్‌లను బుక్‌మార్క్ చేయండి</translation>
 <translation id="5078796286268621944"> సరి కానటువంటి PIN</translation>
@@ -4311,6 +4318,7 @@
 <translation id="5150254825601720210">Netscape సర్టిఫికెట్ SSL సర్వర్ పేరు</translation>
 <translation id="5151354047782775295">డిస్క్ స్థలాన్ని ఖాళీ చేయండి, లేదంటే ఎంపిక చేసిన డేటా ఆటోమేటిక్‌గా తొలగించబడవచ్చు</translation>
 <translation id="5153234146675181447">ఫోన్‌ని మర్చిపో</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722"><ph name="PRINTING_DESTINATION" /> కోసం అధునాతన సెట్టింగ్‌లు</translation>
 <translation id="5154702632169343078">విషయం</translation>
 <translation id="5155327081870541046">అడ్రస్ బార్‌లో, మీరు సెర్చ్ చేయాలనుకుంటున్న సైట్‌ షార్ట్‌కట్‌ను ఎంటర్ చేయండి, ఉదాహరణకు "@bookmarks". అప్పుడు, మీ ప్రాధాన్య కీబోర్డ్ షార్ట్‌కట్‌ను నొక్కి, ఆపై మీ సెర్చ్ క్వెరీని ఎంటర్ చేయండి.</translation>
@@ -4599,6 +4607,7 @@
 <translation id="5449551289610225147">పాస్‌వర్డ్ చెల్లదు</translation>
 <translation id="5449588825071916739">అన్ని ట్యాబ్‌లను బుక్‌మార్క్ చేయి</translation>
 <translation id="5449716055534515760">&amp;విండో మూసివెయ్యి</translation>
+<translation id="5452446625764825792">మీరు ఇప్పుడు మీ ఫోన్‌లోని ఇటీవలి ఫోటోలు, మీడియా, ఇంకా యాప్‌లను చూడవచ్చు</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (ఆఫ్‌లైన్‌లో పని చేస్తుంది)</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" />తో</translation>
 <translation id="545484289444831485">మరిన్ని సెర్చ్ ఫలితాలను చూడండి</translation>
@@ -4659,6 +4668,7 @@
 <translation id="5499211612787418966">ప్రస్తుతానికి ఈ డైలాగ్ ఫోకస్ చేయబడలేదు. ఈ డైలాగ్‌ను ఫోకస్ చేయడానికి Alt-Shift A కీని నొక్కండి.</translation>
 <translation id="5499313591153584299">ఈ ఫైల్ మీ కంప్యూటర్‌కు హానికరం కావచ్చు.</translation>
 <translation id="5499453227627332024">మీ Linux కంటెయినర్ కోసం అప్‌గ్రేడ్ అందుబాటులో ఉంది. మీరు సెట్టింగ్‌ల యాప్ నుండి తర్వాత కూడా అప్‌గ్రేడ్ చేయవచ్చు.</translation>
+<translation id="5499476581866658341">మీరు ఇప్పుడు మీ ఫోన్‌లోని ఇటీవలి ఫోటోలు, మీడియాను చూడవచ్చు</translation>
 <translation id="549957179819296104">కొత్త చిహ్నం</translation>
 <translation id="5500168250243071806">మీరు సైన్ ఇన్ చేసినప్పుడు, <ph name="BEGIN_LINK_SEARCH" />సెర్చ్ హిస్టరీ<ph name="END_LINK_SEARCH" />, <ph name="BEGIN_LINK_GOOGLE" />ఇతర రకాల యాక్టివిటీ<ph name="END_LINK_GOOGLE" /> మీ Google ఖాతాలో సేవ్ చేయబడవచ్చు. మీరు వాటిని ఎప్పుడైనా తొలగించవచ్చు.</translation>
 <translation id="5500709606820808700">భద్రతా తనిఖీ నేడు రన్ చేయబడింది</translation>
@@ -5086,6 +5096,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> మీ కెమెరా, మైక్రోఫోన్‌ను ఉపయోగిస్తోంది</translation>
 <translation id="5935158534896975820">సర్టిఫికెట్ సైనింగ్ రిక్వెస్ట్‌ను సిద్ధం చేస్తోంది (సర్వర్‌లో వేచి ఉంది)</translation>
 <translation id="5935656526031444304">సురక్షిత బ్రౌజింగ్‌ను మేనేజ్ చేయండి</translation>
+<translation id="5936065461722368675">మొత్తం పేజీని అనువదించండి</translation>
 <translation id="5938002010494270685">భద్రతా అప్‌గ్రేడ్ అందుబాటులో ఉంది</translation>
 <translation id="5939518447894949180">రీసెట్ చేయి</translation>
 <translation id="5939719276406088041">షార్ట్‌కట్‌ను క్రియేట్ చేయడం సాధ్యపడదు</translation>
@@ -5654,7 +5665,7 @@
 <translation id="6499143127267478107">ప్రాక్సీ స్క్రిప్ట్‌లో హోస్ట్‌ను పరిష్కరిస్తోంది...</translation>
 <translation id="6499764981457476645">సమీపంలో పరికరాలు ఏవీ కనుగొనబడలేదు</translation>
 <translation id="6501957628055559556">అన్ని కంటైనర్లు</translation>
-<translation id="650266656685499220">ఆల్బమ్‌లను క్రియేట్ చేయడానికి, 'Google ఫోటోలు'కు వెళ్లండి</translation>
+<translation id="650266656685499220">ఆల్బమ్‌లను క్రియేట్ చేయడానికి, 'Google Photos'కు వెళ్లండి</translation>
 <translation id="6503077044568424649">ఎక్కువగా సందర్శించేవి</translation>
 <translation id="650457560773015827">ఎడమవైపు బటన్</translation>
 <translation id="6504601948739128893">మీ పరికరంలో ఇన్‌స్టాల్ చేయబడిన ఫాంట్‌లను ఉపయోగించడానికి సైట్‌లకు అనుమతి లేదు</translation>
@@ -5946,6 +5957,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> రిమోట్ విధానంలో జోడించబడింది</translation>
 <translation id="6790820461102226165">వ్యక్తిని జోడించు...</translation>
 <translation id="6793604637258913070">వచన కేరెట్‌ కనిపించినప్పుడు లేదా అది కదలికలో ఉన్నప్పుడు, దానిని హైలైట్ చేస్తుంది</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">స్క్రీన్‌పై ఉన్న ఐటెమ్‌ల మధ్య ఆటోమేటిక్‌గా కదలడానికి ఆటో-స్కాన్ మిమ్మల్ని అనుమతిస్తుంది. ఒక ఐటెమ్ హైలైట్ అయినప్పుడు, దాన్ని యాక్టివేట్ చేయడానికి "ఎంచుకోండి"ని నొక్కండి.</translation>
 <translation id="6795884519221689054">పాండా</translation>
 <translation id="6797493596609571643">అయ్యో, ఏదో తప్పు జరిగింది.</translation>
@@ -6322,6 +6334,7 @@
 <translation id="7152478047064750137">ఈ పొడిగింపునకు ప్రత్యేక అనుమతులు అవసరం లేదు</translation>
 <translation id="7154130902455071009">మీ ప్రారంభ పేజీని దీనికి మార్చండి: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">కెమెరా లేదా ఫైల్‌లో ఉన్న ఫోటో</translation>
+<translation id="7160182524506337403">మీరు ఇప్పుడు మీ ఫోన్ నోటిఫికేషన్‌లను చూడవచ్చు</translation>
 <translation id="7163202347044721291">యాక్టివేషన్ కోడ్‌ను వెరిఫై చేస్తోంది...</translation>
 <translation id="716640248772308851">తనిఖీ చేయబడిన స్థానాల్లో "<ph name="EXTENSION" />" చిత్రాలను, వీడియోను, సౌండ్ ఫైల్స్‌ను చదవగలదు.</translation>
 <translation id="7167486101654761064">&amp;ఎల్లప్పుడూ ఈ రకం ఫైళ్ళను తెరువు</translation>
@@ -7333,6 +7346,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> స్టేటస్</translation>
 <translation id="8139447493436036221">Google Drive ఫైళ్లు</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">మీరు ఫోన్ హబ్ సెట్టింగ్‌లలో మరిన్ని ఫీచర్‌లను సెటప్ చేయవచ్చు</translation>
 <translation id="8141584439523427891">ఇప్పుడు ప్రత్యామ్నాయ బ్రౌజర్‌లో తెరుస్తోంది</translation>
 <translation id="8141725884565838206">మీ పాస్‌వర్డ్‌లను నిర్వహించండి</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{వీడియో}other{# వీడియోలు}}</translation>
@@ -7540,6 +7554,7 @@
 <translation id="833986336429795709">ఈ లింక్‌ను తెరవడానికి, ఒక యాప్‌ను ఎంచుకోండి</translation>
 <translation id="8342221978608739536">ట్రై చేయలేదు</translation>
 <translation id="8342861492835240085">సేకరణను ఎంచుకోండి</translation>
+<translation id="8345848587667658367">మీరు ఇప్పుడు మీ ఫోన్‌లోని ఇటీవలి ఫోటోలు, మీడియా, నోటిఫికేషన్‌లు, ఇంకా యాప్‌లను చూడవచ్చు</translation>
 <translation id="8347227221149377169">ప్రింట్ టాస్క్‌లు</translation>
 <translation id="834785183489258869">అజ్ఞాతం మోడ్‌లో ఉండగా, వివిధ సైట్‌లలో మీ బ్రౌజింగ్ యాక్టివిటీని చూడటానికి సైట్‌లు మీ కుక్కీలను ఉపయోగించలేవు, ఉదాహరణకు, యాడ్‌లను వ్యక్తిగతీకరించడం. కొన్ని సైట్‌లలోని ఫీచర్‌లు సరిగ్గా పని చేయకపోవచ్చు.</translation>
 <translation id="8350789879725387295">డాక్‌లో స్టైలస్ టూల్స్</translation>
@@ -7815,6 +7830,7 @@
 <translation id="8642947597466641025">టెక్స్ట్‌ని పెద్దదిగా చేయి</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> ప్రమాదకరమైనది కావచ్చు. స్కాన్ చేయడానికి Google అధునాతన రక్షణకు పంపాలా?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{కుక్కీలు లేవు}=1{1 కుక్కీ బ్లాక్ చేయబడింది}other{# కుక్కీలు బ్లాక్ చేయబడ్డాయి}}</translation>
+<translation id="864423554496711319">మీ ఖాతాలో సేవ్ చేసిన పరికరాలు</translation>
 <translation id="8644655801811752511">ఈ సెక్యూరిటీ కీని రీసెట్ చేయలేకపోయింది. కీని ఇన్‌సర్ట్ చేసిన తక్షణం రీసెట్ చేయడానికి ప్రయత్నించండి.</translation>
 <translation id="8645354835496065562">సెన్సార్ యాక్సెన్‌ను అనుమతించడం కొనసాగించు</translation>
 <translation id="8645920082661222035">ప్రమాదకరమైన సంఘటనలు జరగడానికి ముందే, వాటిని పసిగట్టి మిమ్మల్ని హెచ్చరిస్తుంది</translation>
@@ -8144,6 +8160,7 @@
 <translation id="8957757410289731985">ప్రొఫైల్‌ను అనుకూలంగా మార్చు</translation>
 <translation id="895944840846194039">JavaScript మెమరీ</translation>
 <translation id="8960208913905765425">త్వరిత సమాధానాల యూనిట్ మార్పిడి</translation>
+<translation id="8960638196855923532">మీరు ఇప్పుడు మీ ఫోన్ నోటిఫికేషన్‌లు, యాప్‌లను చూడవచ్చు</translation>
 <translation id="8962051932294470566">మీరు ఒకసారి ఒక ఫైల్‌ను మాత్రమే షేర్ చేయగలరు. ప్రస్తుత బదిలీ పూర్తయినప్పుడు మీరు మళ్లీ ట్రై చేయండి.</translation>
 <translation id="8962083179518285172">వివరాలను దాచిపెట్టు</translation>
 <translation id="8962918469425892674">ఈ సైట్ మోషన్ లేదా లైట్ సెన్సార్‌లను ఉపయోగిస్తోంది.</translation>
@@ -8295,6 +8312,7 @@
 <translation id="9103868373786083162">చరిత్రను చూసేందుకు వెనుకకు వెళ్లు, సందర్భ మెనూ నొక్కండి</translation>
 <translation id="9108035152087032312">పేరు &amp;విండో...</translation>
 <translation id="9108072915170399168">ప్రస్తుతం డేటా వినియోగం ఇంటర్నెట్ లేనప్పుడు జరిగేలా సెట్ చేయబడి ఉంది</translation>
+<translation id="9108294543511800041">మీరు ఇప్పుడు మీ ఫోన్‌లోని ఇటీవలి ఫోటోలు, మీడియా, ఇంకా నోటిఫికేషన్‌లను చూడవచ్చు</translation>
 <translation id="9108674852930645435">మీ <ph name="DEVICE_TYPE" />‌లో కొత్తగా ఏమి ఉన్నాయో చూడండి</translation>
 <translation id="9108808586816295166">సురక్షితమైన DNS ఎల్లవేళలా అందుబాటులో ఉండకపోవచ్చు</translation>
 <translation id="9109122242323516435">స్థలాన్ని ఖాళీ చేయడానికి, పరికర నిల్వ నుండి ఫైళ్లను తొలగించండి.</translation>
@@ -8419,7 +8437,6 @@
 <translation id="934503638756687833">అవసరమైతే ఇక్కడ లిస్ట్‌ చేయబడని అంశాలను కూడా తీసివేయవచ్చు. Chrome గోప్యత విధాన డాక్యుమెంట్‌లో &lt;a href="<ph name="URL" />"&gt;అవాంఛిత సాఫ్ట్‌వేర్ రక్షణ&lt;/a&gt; గురించి మరింత తెలుసుకోండి.</translation>
 <translation id="93480724622239549">బగ్ లేదా ఎర్రర్</translation>
 <translation id="935854577147268200">Smart Lock ఫోన్ మారింది. Smart Lockను అప్‌డేట్ చేయడానికి మీ పాస్‌వర్డ్‌ను నమోదు చేయండి. తదుపరిసారి, మీ ఫోన్ మీ <ph name="DEVICE_TYPE" />‌ను అన్‌లాక్ చేస్తుంది. మీరు సెట్టింగ్‌లలో Smart Lockను ఆఫ్ చేయవచ్చు</translation>
-<translation id="93610034168535821">సైట్‌లు ఉపయోగించిన మొత్తం నిల్వ:</translation>
 <translation id="936646668635477464">కెమెరా &amp; మైక్రోఫోన్</translation>
 <translation id="936801553271523408">సిస్టమ్ విశ్లేషణ డేటా</translation>
 <translation id="93766956588638423">ఎక్స్‌టెన్షన్‌ను సరి చేయి</translation>
diff --git a/chrome/app/resources/generated_resources_th.xtb b/chrome/app/resources/generated_resources_th.xtb
index 3112cf3..f679ede 100644
--- a/chrome/app/resources/generated_resources_th.xtb
+++ b/chrome/app/resources/generated_resources_th.xtb
@@ -8413,7 +8413,6 @@
 <translation id="934503638756687833">หากจำเป็น ระบบจะนำรายการที่ไม่ได้แสดงไว้ที่นี่ออกด้วย ดูข้อมูลเพิ่มเติมเกี่ยวกับ&lt;a href="<ph name="URL" />"&gt;การป้องกันซอฟต์แวร์ไม่พึงประสงค์&lt;/a&gt;ในสมุดปกขาวเกี่ยวกับความเป็นส่วนตัวของ Chrome</translation>
 <translation id="93480724622239549">ข้อบกพร่องหรือข้อผิดพลาด</translation>
 <translation id="935854577147268200">เปลี่ยนโทรศัพท์ที่เปิด Smart Lock แล้ว โปรดป้อนรหัสผ่านเพื่ออัปเดต Smart Lock โทรศัพท์จะปลดล็อก <ph name="DEVICE_TYPE" /> ของคุณในครั้งถัดไป คุณปิด Smart Lock ได้ในการตั้งค่า</translation>
-<translation id="93610034168535821">พื้นที่เก็บข้อมูลทั้งหมดที่เว็บไซต์ต่างๆ ใช้:</translation>
 <translation id="936646668635477464">กล้องถ่ายรูปและไมโครโฟน</translation>
 <translation id="936801553271523408">ข้อมูลวินิจฉัยระบบ</translation>
 <translation id="93766956588638423">ซ่อมส่วนขยาย</translation>
diff --git a/chrome/app/resources/generated_resources_tr.xtb b/chrome/app/resources/generated_resources_tr.xtb
index 82b81978..494b2912 100644
--- a/chrome/app/resources/generated_resources_tr.xtb
+++ b/chrome/app/resources/generated_resources_tr.xtb
@@ -1541,6 +1541,7 @@
 <translation id="2433836460518180625">Yalnızca cihazın kilidini aç</translation>
 <translation id="2434449159125086437">Yazıcı kurulamıyor. Lütfen yapılandırmayı kontrol edip tekrar deneyin.</translation>
 <translation id="2434758125294431199">Sizinle kimlerin içerik paylaşabileceğini seçin</translation>
+<translation id="2434915728183570229">Artık telefonunuzdaki uygulamaları görüntüleyebilirsiniz</translation>
 <translation id="2435137177546457207">Google Chrome ve ChromeOS Flex Ek Şartları</translation>
 <translation id="2435248616906486374">Ağ bağlantısı kesildi</translation>
 <translation id="2435457462613246316">Şifreyi göster</translation>
@@ -1905,6 +1906,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Desteklenmeyen 1 uygulamayı kaldırın}other{Desteklenmeyen # uygulamayı kaldırın}}</translation>
 <translation id="2776560192867872731"><ph name="DEVICE_NAME" /> cihazının cihaz adını değiştir</translation>
 <translation id="2777251078198759550">Bu kapsayıcıyı sil</translation>
+<translation id="2778471504622896352">ChromeOS başlatıcıya uzaktan uygulama ekleme</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Linux uygulaması yüklenirken hata oluştu</translation>
 <translation id="2783298271312924866">İndirildi</translation>
@@ -3540,6 +3542,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> ve <ph name="NUMBER_OF_OTHER_SWITCHES" /> düğme tuşu daha</translation>
 <translation id="439266289085815679">Bluetooth yapılandırması <ph name="USER_EMAIL" /> tarafından kontrol ediliyor.</translation>
 <translation id="4392896746540753732">Yapılandırma dosyasını düzenleyin</translation>
+<translation id="4393713825278446281">Hızlı Eşleme cihazları <ph name="PRIMARY_EMAIL" /> hesabına kaydedilir</translation>
 <translation id="4394049700291259645">Devre dışı bırak</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{Tümünü &amp;aç}=1{Yer işaretini &amp;aç}other{Tümünü &amp;aç ({COUNT})}}</translation>
 <translation id="4397372003838952832">Bu şifreyi hatırlamanız gerekmez. <ph name="EMAIL" /> için <ph name="GOOGLE_PASSWORD_MANAGER" /> uygulamasına kaydedilir.</translation>
@@ -3769,6 +3772,7 @@
 <translation id="4615586811063744755">çerez seçilmedi</translation>
 <translation id="461661862154729886">Enerji kaynağı</translation>
 <translation id="4617001782309103936">Çok kısa</translation>
+<translation id="4617019240346358451">"<ph name="EXTENSION_NAME" />" uzantısını kullanmak için sayfayı yenileyin</translation>
 <translation id="4617270414136722281">Uzantı seçenekleri</translation>
 <translation id="4617880081511131945">Bağlantı kurulamıyor</translation>
 <translation id="4619564267100705184">Kimliğinizi doğrulayın</translation>
@@ -3984,6 +3988,7 @@
 <translation id="4833683849865011483">Yazdırma sunucusunda 1 yazıcı bulundu</translation>
 <translation id="4836504898754963407">Parmak izi yönetimi</translation>
 <translation id="4837128290434901661">Google Arama’ya geri dönmek ister misiniz?</translation>
+<translation id="4837165100461973682">Değişikliklerinizin uygulanması için sayfayı yeniden yükleyin</translation>
 <translation id="4837926214103741331">Bu cihazı kullanma yetkiniz yok. Oturum açma izni almak için lütfen cihaz sahibiyle iletişime geçin.</translation>
 <translation id="4837952862063191349">Kilidi açmak ve yerel verilerinizi geri yüklemek için lütfen eski <ph name="DEVICE_TYPE" /> şifrenizi girin.</translation>
 <translation id="4838170306476614339">Telefonunuzdaki fotoğrafları, medya içeriklerini ve bildirimleri görün.</translation>
@@ -4219,6 +4224,7 @@
 <translation id="5072900412896857127">Google Play Hizmet Şartları yüklenemiyor. Lütfen ağ bağlantınızı kontrol edip tekrar deneyin.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" /> ve # tane daha}}</translation>
 <translation id="5074318175948309511">Yeni ayarların geçerli olması için bu sayfanın tekrar yüklenmesi gerekebilir.</translation>
+<translation id="5074761966806028321">Kurulumu tamamlamak için hâlâ izin gerekiyor</translation>
 <translation id="5075910247684008552">Güvenli sitelerde güvenli olmayan içerik varsayılan olarak engellenir</translation>
 <translation id="5078638979202084724">Tüm sekmelere yer işareti koy</translation>
 <translation id="5078796286268621944">Yanlış PIN</translation>
@@ -4293,6 +4299,7 @@
 <translation id="5150254825601720210">Netscape Sertifikası SSL Sunucu Adı</translation>
 <translation id="5151354047782775295">Disk alanını boşaltmazsanız bazı veriler otomatik olarak silinebilir</translation>
 <translation id="5153234146675181447">Telefonu unutma</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722"><ph name="PRINTING_DESTINATION" /> için gelişmiş ayarlar</translation>
 <translation id="5154702632169343078">Konu</translation>
 <translation id="5155327081870541046">Adres çubuğuna arama yapmak istediğiniz sitenin kısayolunu (ör. "@bookmarks") girin. Ardından, tercih ettiğiniz klavye kısayoluna basın ve arama teriminizi girin.</translation>
@@ -4581,6 +4588,7 @@
 <translation id="5449551289610225147">Geçersiz şifre</translation>
 <translation id="5449588825071916739">Tüm Sekmelere Yer İşareti Koy</translation>
 <translation id="5449716055534515760">Pencereyi &amp;Kapat</translation>
+<translation id="5452446625764825792">Artık telefonunuzdaki son fotoğrafları, medya içeriklerini ve uygulamaları görüntüleyebilirsiniz</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (çevrimdışı çalışır)</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" /> ile</translation>
 <translation id="545484289444831485">Daha fazla arama sonucu göster</translation>
@@ -4641,6 +4649,7 @@
 <translation id="5499211612787418966">Bu iletişim kutusu şu anda odaklanmamış. İletişim kutusunu odaklamak için Alt-Üst Karakter A tuşlarına basın</translation>
 <translation id="5499313591153584299">Bu dosya bilgisayarınıza zarar verebilir.</translation>
 <translation id="5499453227627332024">Linux Kapsayıcınız için yeni sürüm mevcut. Daha sonra Ayarlar uygulamasından da yeni sürüme geçebilirsiniz.</translation>
+<translation id="5499476581866658341">Artık telefonunuzdaki son fotoğrafları ve medya içeriklerini görüntüleyebilirsiniz</translation>
 <translation id="549957179819296104">Yeni simge</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />Arama geçmişi<ph name="END_LINK_SEARCH" /> ve <ph name="BEGIN_LINK_GOOGLE" />diğer etkinlik biçimleri<ph name="END_LINK_GOOGLE" />, oturum açtığınızda Google Hesabınıza kaydedilebilir. Bunları istediğiniz zaman silebilirsiniz.</translation>
 <translation id="5500709606820808700">Güvenlik kontrolü bugün çalıştırıldı</translation>
@@ -5929,6 +5938,7 @@
 <translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> eklentisi uzaktan eklendi</translation>
 <translation id="6790820461102226165">Kişi Ekle...</translation>
 <translation id="6793604637258913070">Görüntülendiğinde veya hareket ettiğinde metin imlecini vurgula</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">Otomatik tarama özelliği, ekrandaki öğeler arasında otomatik olarak gezinmenizi sağlar. Vurgulanan bir öğeyi etkinleştirmek için "Seç"e basabilirsiniz.</translation>
 <translation id="6795884519221689054">Panda</translation>
 <translation id="6797493596609571643">Hata. Bir şeyler ters gitti.</translation>
@@ -6305,6 +6315,7 @@
 <translation id="7152478047064750137">Bu uzantı herhangi bir özel izin gerektirmiyor</translation>
 <translation id="7154130902455071009">Başlangıç sayfanızı <ph name="START_PAGE" /> olarak değiştirme</translation>
 <translation id="7155171745945906037">Kameradan veya dosyadan mevcut fotoğraf</translation>
+<translation id="7160182524506337403">Artık telefonunuzdaki bildirimleri görüntüleyebilirsiniz</translation>
 <translation id="7163202347044721291">Etkinleştirme kodu doğrulanıyor...</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" işaretli konumlardaki resimleri, video ve ses dosyalarını okuyabilir.</translation>
 <translation id="7167486101654761064">&amp;Bu tür dosyaları her zaman aç</translation>
@@ -7319,6 +7330,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> durumu</translation>
 <translation id="8139447493436036221">Google Drive dosyaları</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Telefon Merkezi ayarlarında daha fazla özellik belirleyebilirsiniz</translation>
 <translation id="8141584439523427891">Şu anda alternatif tarayıcıda açılıyor</translation>
 <translation id="8141725884565838206">Şifrelerinizi yönetin</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{bir video}other{# video}}</translation>
@@ -7526,6 +7538,7 @@
 <translation id="833986336429795709">Bu bağlantıyı açmak için bir uygulama seçin</translation>
 <translation id="8342221978608739536">Denemedim</translation>
 <translation id="8342861492835240085">Koleksiyon seçin</translation>
+<translation id="8345848587667658367">Artık telefonunuzdaki son fotoğrafları, medya içeriklerini, bildirimleri ve uygulamaları görüntüleyebilirsiniz</translation>
 <translation id="8347227221149377169">Yazdırma işleri</translation>
 <translation id="834785183489258869">Gizli moddayken siteler, örneğin reklamları kişiselleştirmek amacıyla farklı sitelerde tarama etkinliğinizi görmek için çerezlerinizi kullanamaz. Bazı sitelerdeki özellikler çalışmayabilir.</translation>
 <translation id="8350789879725387295">Yuvadayken ekran kalemi aracı</translation>
@@ -7801,6 +7814,7 @@
 <translation id="8642947597466641025">Metni Büyüt</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> tehlikeli olabilir. Dosya taranmak üzere Google Gelişmiş Koruma'ya gönderilsin mi?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Çerez yok}=1{1 çerez engellendi}other{# çerez engellendi}}</translation>
+<translation id="864423554496711319">Hesabınıza kaydedilen cihazlar</translation>
 <translation id="8644655801811752511">Bu güvenlik anahtarı sıfırlanamıyor Anahtarı, takar takmaz hemen sıfırlamayı deneyin.</translation>
 <translation id="8645354835496065562">Sensör erişimine izin vermeye devam et</translation>
 <translation id="8645920082661222035">Tehlikeli etkinlikleri meydana gelmeden önce tahmin ederek sizi uyarır</translation>
@@ -8130,6 +8144,7 @@
 <translation id="8957757410289731985">Profili özelleştir</translation>
 <translation id="895944840846194039">JavaScript Belleği</translation>
 <translation id="8960208913905765425">Bil bakalım birim dönüştürmesi</translation>
+<translation id="8960638196855923532">Artık telefonunuzdaki bildirimleri ve uygulamaları görüntüleyebilirsiniz</translation>
 <translation id="8962051932294470566">Tek seferde sadece bir dosya paylaşabilirsiniz. Şu anki aktarım tamamlandıktan sonra tekrar deneyin.</translation>
 <translation id="8962083179518285172">Ayrıntıları Gizle</translation>
 <translation id="8962918469425892674">Bu site hareket veya ışık sensörlerini kullanıyor.</translation>
@@ -8281,6 +8296,7 @@
 <translation id="9103868373786083162">Geri gitmek için içerik menüsüne basarak geçmişi görüntüleyin</translation>
 <translation id="9108035152087032312">&amp;Pencereye ad ver...</translation>
 <translation id="9108072915170399168">Mevcut veri kullanımı, internet olmadan olarak ayarlı</translation>
+<translation id="9108294543511800041">Artık telefonunuzdaki son fotoğrafları, medya içeriklerini ve bildirimleri görüntüleyebilirsiniz</translation>
 <translation id="9108674852930645435"><ph name="DEVICE_TYPE" /> cihazınızdaki yenilikleri öğrenin</translation>
 <translation id="9108808586816295166">Güvenli DNS her zaman kullanılamayabilir</translation>
 <translation id="9109122242323516435">Yer açmak için cihaz depolama alanındaki dosyaları silin.</translation>
@@ -8405,7 +8421,6 @@
 <translation id="934503638756687833">Gerekirse burada listelenmeyen öğeler de kaldırılabilir. &lt;a href="<ph name="URL" />"&gt;İstenmeyen yazılım koruması&lt;/a&gt; hakkında daha fazla bilgiyi Chrome gizliliği tanıtım yazısında bulabilirsiniz.</translation>
 <translation id="93480724622239549">Sorun veya Hata</translation>
 <translation id="935854577147268200">Smart Lock telefonu değişti. Smart Lock'u güncellemek için şifrenizi girin. Böylece, bir dahaki sefere telefonunuzu kullanarak <ph name="DEVICE_TYPE" /> cihazınızın kilidini açabilirsiniz. Ayarlar'dan Smart Lock'u kapatabilirsiniz.</translation>
-<translation id="93610034168535821">Siteler tarafından kullanılan toplam depolama alanı:</translation>
 <translation id="936646668635477464">Kamera ve mikrofon</translation>
 <translation id="936801553271523408">Sistem teşhis verileri</translation>
 <translation id="93766956588638423">Uzantıyı onar</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb
index 6d8bc86..fe4dcba0 100644
--- a/chrome/app/resources/generated_resources_uk.xtb
+++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -1926,6 +1926,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{Вилучити 1 додаток, що не підтримується}one{Вилучити # додаток, що не підтримується}few{Вилучити # додатки, що не підтримуються}many{Вилучити # додатків, що не підтримуються}other{Вилучити # додатка, що не підтримуються}}</translation>
 <translation id="2776560192867872731">Змінити назву пристрою "<ph name="DEVICE_NAME" />"</translation>
 <translation id="2777251078198759550">Видалити цей контейнер</translation>
+<translation id="2778471504622896352">Додайте віддалені додатки на панель запуску ОС Chrome</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">Не вдалося встановити додаток Linux</translation>
 <translation id="2783298271312924866">Завантажено</translation>
@@ -3561,6 +3562,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />, <ph name="SECOND_SWITCH" />, <ph name="THIRD_SWITCH" /> і ще <ph name="NUMBER_OF_OTHER_SWITCHES" /></translation>
 <translation id="439266289085815679">Налаштуваннями Bluetooth керує <ph name="USER_EMAIL" />.</translation>
 <translation id="4392896746540753732">Змінити файл конфігурації</translation>
+<translation id="4393713825278446281">Пристрої з функцією "Швидка пара" збережено в обліковому записі <ph name="PRIMARY_EMAIL" /></translation>
 <translation id="4394049700291259645">Вимкнути</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{&amp;Відкрити всі}=1{&amp;Відкрити закладку}one{&amp;Відкрити всі ({COUNT})}few{&amp;Відкрити всі ({COUNT})}many{&amp;Відкрити всі ({COUNT})}other{&amp;Відкрити всі ({COUNT})}}</translation>
 <translation id="4397372003838952832">Пароль не потрібно запам’ятовувати. Його буде збережено в сервісі <ph name="GOOGLE_PASSWORD_MANAGER" /> для адреси <ph name="EMAIL" />.</translation>
@@ -3791,6 +3793,7 @@
 <translation id="4615586811063744755">файли cookie не вибрано</translation>
 <translation id="461661862154729886">Джерело живлення</translation>
 <translation id="4617001782309103936">Закороткий</translation>
+<translation id="4617019240346358451">Щоб використовувати розширення "<ph name="EXTENSION_NAME" />", оновіть сторінку</translation>
 <translation id="4617270414136722281">Параметри розширень</translation>
 <translation id="4617880081511131945">Не вдалося підключитися до телефона</translation>
 <translation id="4619564267100705184">Підтвердити особу</translation>
@@ -4006,6 +4009,7 @@
 <translation id="4833683849865011483">На сервері для друку знайдено 1 принтер</translation>
 <translation id="4836504898754963407">Керувати відбитками</translation>
 <translation id="4837128290434901661">Знову ввімкнути Пошук Google?</translation>
+<translation id="4837165100461973682">Щоб застосувати зміни, оновіть сторінку</translation>
 <translation id="4837926214103741331">Ви не маєте права використовувати цей пристрій. Зверніться до його власника, щоб отримати дозвіл на вхід.</translation>
 <translation id="4837952862063191349">Щоб розблокувати пристрій <ph name="DEVICE_TYPE" /> і відновити локальні дані, введіть старий пароль.</translation>
 <translation id="4838170306476614339">Переглядайте фотографії, медіафайли й сповіщення з телефона</translation>
@@ -4315,6 +4319,7 @@
 <translation id="5150254825601720210">Ім'я SSL-сервера сертифіката Netscape</translation>
 <translation id="5151354047782775295">Звільніть місце на диску, інакше деякі дані буде автоматично видалено</translation>
 <translation id="5153234146675181447">Забути телефон</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722"><ph name="PRINTING_DESTINATION" />: розширені налаштування</translation>
 <translation id="5154702632169343078">Тема</translation>
 <translation id="5155327081870541046">В адресному рядку введіть команду для веб-сайту, на якому потрібно шукати, наприклад "@bookmarks". Потім натисніть вибрану комбінацію клавіш і введіть пошуковий термін.</translation>
@@ -5953,6 +5958,7 @@
 <translation id="6790497603648687708">Розширення <ph name="EXTENSION_NAME" /> додано віддалено</translation>
 <translation id="6790820461102226165">Додати користувача…</translation>
 <translation id="6793604637258913070">Виділяти місце введення тексту, коли воно з’являється або рухається</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">За допомогою автосканування можна автоматично переміщатися між елементами на екрані. Щоб активувати елемент, натисніть "Вибрати", коли його буде виділено.</translation>
 <translation id="6795884519221689054">Панда</translation>
 <translation id="6797493596609571643">На жаль, сталася помилка.</translation>
@@ -7826,6 +7832,7 @@
 <translation id="8642947597466641025">Збільшити розмір тексту</translation>
 <translation id="8643443571868262066">Файл <ph name="FILE_NAME" /> може бути небезпечним. Надіслати його в Додатковий захист Google на перевірку?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{Немає файлів cookie}=1{1 файл cookie заблоковано}one{# файл cookie заблоковано}few{# файли cookie заблоковано}many{# файлів cookie заблоковано}other{# файлу cookie заблоковано}}</translation>
+<translation id="864423554496711319">Пристрої, збережені в обліковому записі</translation>
 <translation id="8644655801811752511">Не вдається скинути цей ключ безпеки. Спробуйте зробити це, щойно вставите ключ.</translation>
 <translation id="8645354835496065562">Дозволяти доступ до датчиків</translation>
 <translation id="8645920082661222035">Передбачає небезпечні події та повідомляє про них ще до того, як вони відбудуться</translation>
@@ -8433,7 +8440,6 @@
 <translation id="934503638756687833">Якщо потрібно, можна також видалити елементи, не перелічені тут. Докладніше про &lt;a href="<ph name="URL" />"&gt;захист від небажаних програм&lt;/a&gt; читайте в інформаційному документі про конфіденційність Chrome.</translation>
 <translation id="93480724622239549">Помилка</translation>
 <translation id="935854577147268200">Телефон для Smart Lock змінено. Щоб оновити Smart Lock, введіть пароль. Наступного разу ви зможете розблокувати пристрій <ph name="DEVICE_TYPE" /> за допомогою свого телефона. Smart Lock можна вимкнути в налаштуваннях</translation>
-<translation id="93610034168535821">Загальний обсяг пам'яті, використаний сайтами:</translation>
 <translation id="936646668635477464">Камера та мікрофон</translation>
 <translation id="936801553271523408">Дані діагностики системи</translation>
 <translation id="93766956588638423">Полагодити розширення</translation>
diff --git a/chrome/app/resources/generated_resources_ur.xtb b/chrome/app/resources/generated_resources_ur.xtb
index 6c29cdb..1172a532 100644
--- a/chrome/app/resources/generated_resources_ur.xtb
+++ b/chrome/app/resources/generated_resources_ur.xtb
@@ -2226,6 +2226,7 @@
 <translation id="3067198360141518313">یہ پلگ ان چلائیں</translation>
 <translation id="3071624960923923138">ایک نیا ٹیب کھولنے کے لئے آپ یہاں کلک کر سکتے ہیں</translation>
 <translation id="3072775339180057696">سائٹ کو <ph name="FILE_NAME" /> دیکھنے دیں؟</translation>
+<translation id="3074499504015191586">مکمل صفحے کا ترجمہ کریں</translation>
 <translation id="3075874217500066906">‏Powerwash کارروائی شروع کرنے کیلئے ایک بار دوبارہ شروع کرنا درکار ہے۔ دوبارہ شروع کرنے کے بعد آپ سے یہ توثیق کرنے کیلئے پوچھا جائے گا کہ آپ جاری رکھنا چاہتے ہیں۔</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">صرف اس آلے پر محفوظ کریں</translation>
@@ -5080,6 +5081,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> آپ کا کیمرا اور مائیکروفون استعمال کر رہی ہے</translation>
 <translation id="5935158534896975820">سرٹیفکیٹ پر دستخط کرنے کی درخواست کی تیاری ہو رہی ہے (سرور پر انتظار)</translation>
 <translation id="5935656526031444304">محفوظ براؤزنگ کا نظم کریں</translation>
+<translation id="5936065461722368675">مکمل صفحے کا ترجمہ کریں</translation>
 <translation id="5938002010494270685">سیکورٹی اپ گریڈ دستیاب ہے</translation>
 <translation id="5939518447894949180">دوبارہ ترتیب دیں</translation>
 <translation id="5939719276406088041">شارٹ کٹ تخلیق نہیں کیا جا سکتا</translation>
@@ -8422,7 +8424,6 @@
 <translation id="934503638756687833">‏ضرورت پڑنے پر، یہاں غیر مندرج آئٹمز کو بھی ہٹا دیا جائے گا۔ Chrome رازداری کے وہائٹ پیپر میں &lt;a href‎="<ph name="URL" />"‎&gt;غیر مطلوبہ سافٹ وئیر کے تحفظ&lt;/a&gt; کے بارے میں مزید جانیں۔</translation>
 <translation id="93480724622239549">بگ یا خرابی</translation>
 <translation id="935854577147268200">‏Smart Lock کا فون تبدیل ہو گيا ہے۔ Smart Lock اپ ڈیٹ کرنے کے لیے اپنا پاس ورڈ درج کریں۔ اگلی بار آپ کے فون سے آپ کا <ph name="DEVICE_TYPE" /> غیر مقفل ہوگا۔ آپ ترتیبات میں Smart Lock کو آف کر سکتے ہیں</translation>
-<translation id="93610034168535821">سائٹس کے ذریعے استعمال کردہ کل اسٹوریج:</translation>
 <translation id="936646668635477464">کیمرا اور مائیکروفون</translation>
 <translation id="936801553271523408">سسٹم ڈائیگناسٹک ڈیٹا</translation>
 <translation id="93766956588638423">ایکسٹینشن کو درست کریں</translation>
diff --git a/chrome/app/resources/generated_resources_uz.xtb b/chrome/app/resources/generated_resources_uz.xtb
index 9ddce10..80ab5e8 100644
--- a/chrome/app/resources/generated_resources_uz.xtb
+++ b/chrome/app/resources/generated_resources_uz.xtb
@@ -1545,6 +1545,7 @@
 <translation id="2433836460518180625">Faqat qurilmani qulfdan chiqarsin</translation>
 <translation id="2434449159125086437">Printer sozlanmadi. Sozlamalarni tekshiring va qaytadan urining.</translation>
 <translation id="2434758125294431199">Sizga kim fayl yubora olishini tanlang</translation>
+<translation id="2434915728183570229">Endi siz telefoningizdagi ilovalarni koʻra olasiz</translation>
 <translation id="2435137177546457207">Google Chrome va ChromeOS Flex qoʻshimcha shartlari</translation>
 <translation id="2435248616906486374">Tarmoqqa ulanish yo‘q</translation>
 <translation id="2435457462613246316">Parolni ko‘rsatish</translation>
@@ -2226,6 +2227,7 @@
 <translation id="3067198360141518313">Bu plaginni ishga tushirish</translation>
 <translation id="3071624960923923138">Yangi varaq ochish uchun bu yerni bosing</translation>
 <translation id="3072775339180057696">Saytga <ph name="FILE_NAME" /> faylini ochiga ruxsat berasizmi?</translation>
+<translation id="3074499504015191586">Toʻliq sahifani tarjima qilish</translation>
 <translation id="3075874217500066906">Powerwash amalini boshlash uchun qurilmani o‘chirib yoqish zarur. Keyin tasdiqlash so‘rovi paydo bo‘ladi.</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">Faqat shu qurilmada saqlansin</translation>
@@ -4229,6 +4231,7 @@
 <translation id="5072900412896857127">Google Play xizmat shartlari yuklanmadi. Internetga ulanishni tekshiring va qaytadan urining.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" />, va yana # ta}}</translation>
 <translation id="5074318175948309511">Sozlamalar kuchga kirishi uchun sahifani qayta yuklash kerak.</translation>
+<translation id="5074761966806028321">Sozlashni yakunlash uchun ruxsat kerak</translation>
 <translation id="5075910247684008552">Himoyalangan saytlarda zararli kontent avtomatik bloklanadi</translation>
 <translation id="5078638979202084724">Barcha ichki oynalarni xatcho‘plarga qo‘shish</translation>
 <translation id="5078796286268621944">Noto‘g‘ri PIN-kod</translation>
@@ -4592,6 +4595,7 @@
 <translation id="5449551289610225147">Parol noto‘g‘ri</translation>
 <translation id="5449588825071916739">Barcha ichki oynalarni xatcho‘pga qo‘shish</translation>
 <translation id="5449716055534515760">Oynani &amp;yopish</translation>
+<translation id="5452446625764825792">Endi siz telefoningizdagi oxirgi rasmlar, multimedia va ilovalarni koʻra olasiz</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (internetsiz ishlaydi)</translation>
 <translation id="5454166040603940656"><ph name="PROVIDER" /> yordamida</translation>
 <translation id="545484289444831485">Boshqa qidiruv natijalari</translation>
@@ -4652,6 +4656,7 @@
 <translation id="5499211612787418966">Bu suhbat hozir fokuslanmagan. Bu suhbatni fokuslash uchun Alt+Shift+A tugmalarini bosing.</translation>
 <translation id="5499313591153584299">Bu fayl kompyuteringiz uchun zararli bo‘lishi mumkin.</translation>
 <translation id="5499453227627332024">Linux konteyneringiz uchun yangilanish chiqqan. Uni keyinroq Sozlamalar ilovasi orqali ham yangilash mumkin.</translation>
+<translation id="5499476581866658341">Endi siz telefoningizdagi oxirgi rasm va multimedia fayllarini koʻra olasiz</translation>
 <translation id="549957179819296104">Yangi belgi</translation>
 <translation id="5500168250243071806">Google hisobingizga kirganingizda <ph name="BEGIN_LINK_SEARCH" />Qidiruv tarixi<ph name="END_LINK_SEARCH" /> va <ph name="BEGIN_LINK_GOOGLE" />boshqa shakldagi harakatlaringiz<ph name="END_LINK_GOOGLE" /> hisobingizga saqlanishi mumkin. Ularni istalgan vaqt oʻchirish mumkin.</translation>
 <translation id="5500709606820808700">Xavfsizlik tekshiruvi bugun bajarilgan</translation>
@@ -5079,6 +5084,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> kamera va mikrofondan foydalanmoqda</translation>
 <translation id="5935158534896975820">Sertifikatni imzolash talabi tayyorlanmoqda (server javobi kutilmoqda)</translation>
 <translation id="5935656526031444304">Saytlarni xavfsiz kezish rejimini boshqarish</translation>
+<translation id="5936065461722368675">Toʻliq sahifani tarjima qilish</translation>
 <translation id="5938002010494270685">Xavfsizlikka oid yangilanish mavjud</translation>
 <translation id="5939518447894949180">Asliga qaytarish</translation>
 <translation id="5939719276406088041">Yorliq yaratilmadi</translation>
@@ -6316,6 +6322,7 @@
 <translation id="7152478047064750137">Bu kengaytma hech qanday maxsus ruxsat talab qilmaydi</translation>
 <translation id="7154130902455071009">Boshlash sahifani quyidagisiga almashtirish: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Kamera yoki galereyadan olingan surat</translation>
+<translation id="7160182524506337403">Endi siz telefoningizdagi bildirishnomalarni koʻra olasiz</translation>
 <translation id="7163202347044721291">Aktivatsiya kodi tasdiqlanmoqda…</translation>
 <translation id="716640248772308851">“<ph name="EXTENSION" />” kengaytmasi belgilangan jildlardan rasm, audio va video fayllarni o‘qishi mumkin.</translation>
 <translation id="7167486101654761064">&amp;Bu turdagi fayllar har doim ochilsin</translation>
@@ -7329,6 +7336,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> holati</translation>
 <translation id="8139447493436036221">Google Drive fayllari</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Phone Hub sozlamalari orqali koʻplab funksiyalarni sozlashingiz mumkin</translation>
 <translation id="8141584439523427891">Hozir muqobil brauzerda ochiladi</translation>
 <translation id="8141725884565838206">Parollarni boshqarish</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{video}other{# ta video}}</translation>
@@ -7536,6 +7544,7 @@
 <translation id="833986336429795709">Havolani ochish uchun ilova tanlang</translation>
 <translation id="8342221978608739536">Sinab koʻrmadim</translation>
 <translation id="8342861492835240085">To‘plamni tanlang</translation>
+<translation id="8345848587667658367">Endi siz telefoningizdagi oxirgi rasmlar, multimedia, bildirishnomalar va ilovalarni koʻra olasiz</translation>
 <translation id="8347227221149377169">Chop etish vazifalari</translation>
 <translation id="834785183489258869">Inkognito rejimida cookie fayllaringiz yopiq boʻladi va saytlar reklamalarni sizga moslashtirish uchun brauzerdagi faoliyatingizni kuzata olmaydi. Ayrim saytlardagi funksiyalar ishlamay qolishi mumkin.</translation>
 <translation id="8350789879725387295">Dokdagi stilus vositalari</translation>
@@ -8141,6 +8150,7 @@
 <translation id="8957757410289731985">Profilni moslash</translation>
 <translation id="895944840846194039">JavaScript xotirasi</translation>
 <translation id="8960208913905765425">Tezkor javoblardagi birliklar konvertori</translation>
+<translation id="8960638196855923532">Endi siz telefoningizdagi bildirishnoma va ilovalarni koʻra olasiz</translation>
 <translation id="8962051932294470566">Bir vaqtda faqat bitta fayl yubora olasiz. Joriy uzatish yakunidan keyin qaytadan urining.</translation>
 <translation id="8962083179518285172">Tafsilotlarni yopish</translation>
 <translation id="8962918469425892674">Bu sayt harakat yoki yorug‘lik sensorlaridan foydalanmoqda.</translation>
@@ -8292,6 +8302,7 @@
 <translation id="9103868373786083162">Ortga qaytish uchun bosing, brauzer tarixini ko‘rish uchun kontekst menyusini tanlang</translation>
 <translation id="9108035152087032312">Oynani &amp;nomlash...</translation>
 <translation id="9108072915170399168">Hozir internetsiz trafik sarflanishi sozlangan</translation>
+<translation id="9108294543511800041">Endi siz telefoningizdagi oxirgi rasmlar, multimedia va bildirishnomalarni koʻra olasiz</translation>
 <translation id="9108674852930645435"><ph name="DEVICE_TYPE" /> yangi funksiyalari bilan tanishing</translation>
 <translation id="9108808586816295166">Xavfsiz DNS xizmati har doim ham ishlamasligi mumkin</translation>
 <translation id="9109122242323516435">Joy ochish uchun qurilma xotirasidan fayllarni o‘chiring</translation>
@@ -8416,7 +8427,6 @@
 <translation id="934503638756687833">Ro‘yxatda keltirilmagan fayllar olib tashlangan bo‘lishi mumkin. &lt;a href="<ph name="URL" />"&gt;Keraksiz dasturlardan himoyalanish&lt;/a&gt; haqida batafsil axborot oling.</translation>
 <translation id="93480724622239549">Nosozlik yoki xatolik</translation>
 <translation id="935854577147268200">Smart Lock funksiyasi yoqilgan telefon oʻzgardi. Smart Lock funksiyasini yangilash uchun parolni kiriting. Keyingi safar telefoningiz <ph name="DEVICE_TYPE" /> qurilmasini qulfdan chiqara oladi. Sozlamalar orqali Smart Lock funksiyasini faolsizlantirish mumkin.</translation>
-<translation id="93610034168535821">Saytlar ishlatgan jami xotira:</translation>
 <translation id="936646668635477464">Kamera va mikrofon</translation>
 <translation id="936801553271523408">Tizim diagnostik ma’lumotlari</translation>
 <translation id="93766956588638423">Kengaytmani ta’mirlash</translation>
diff --git a/chrome/app/resources/generated_resources_vi.xtb b/chrome/app/resources/generated_resources_vi.xtb
index e388156..8e84156 100644
--- a/chrome/app/resources/generated_resources_vi.xtb
+++ b/chrome/app/resources/generated_resources_vi.xtb
@@ -1558,6 +1558,7 @@
 <translation id="2433836460518180625">Chỉ mở khóa thiết bị</translation>
 <translation id="2434449159125086437">Không thể thiết lập máy in. Vui lòng kiểm tra cấu hình rồi thử lại.</translation>
 <translation id="2434758125294431199">Chọn người có thể chia sẻ với bạn</translation>
+<translation id="2434915728183570229">Giờ đây, bạn có thể xem các ứng dụng có trên điện thoại của mình</translation>
 <translation id="2435137177546457207">Các điều khoản bổ sung của Google Chrome và ChromeOS Flex</translation>
 <translation id="2435248616906486374">Mạng đã bị ngắt kết nối</translation>
 <translation id="2435457462613246316">Hiện mật khẩu</translation>
@@ -4242,6 +4243,7 @@
 <translation id="5072900412896857127">Không thể tải Điều khoản dịch vụ của Google Play. Vui lòng kiểm tra trạng thái kết nối mạng và thử lại.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}other{<ph name="FILE1" />, <ph name="FILE2" /> và # tệp khác}}</translation>
 <translation id="5074318175948309511">Có thể cần phải tải lại trang này trước khi cài đặt mới có hiệu lực.</translation>
+<translation id="5074761966806028321">Vẫn cần quyền để hoàn tất quá trình thiết lập</translation>
 <translation id="5075910247684008552">Theo mặc định, các trang web an toàn sẽ chặn nội dung không an toàn</translation>
 <translation id="5078638979202084724">Đánh dấu trang tất cả các thẻ</translation>
 <translation id="5078796286268621944">Mã PIN không chính xác</translation>
@@ -4605,6 +4607,7 @@
 <translation id="5449551289610225147">Mật khẩu không hợp lệ</translation>
 <translation id="5449588825071916739">Đánh dấu trang tất cả các thẻ</translation>
 <translation id="5449716055534515760">Đóng cửa &amp;sổ</translation>
+<translation id="5452446625764825792">Giờ đây, bạn có thể xem ứng dụng, nội dung nghe nhìn và ảnh gần đây có trên điện thoại của mình.</translation>
 <translation id="5452976525201205853"><ph name="LANGUAGE" /> (hoạt động khi không có mạng)</translation>
 <translation id="5454166040603940656">với <ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Xem thêm kết quả tìm kiếm</translation>
@@ -4665,6 +4668,7 @@
 <translation id="5499211612787418966">Hộp thoại này hiện không được đặt tiêu điểm. Nhấn tổ hợp phím Alt+Shift+A để đặt hộp thoại này làm tiêu điểm.</translation>
 <translation id="5499313591153584299">Tệp này có thể có hại cho máy tính của bạn.</translation>
 <translation id="5499453227627332024">Hiện đã có bản nâng cấp cho Vùng chứa Linux. Bạn cũng có thể nâng cấp sau trong ứng dụng Cài đặt.</translation>
+<translation id="5499476581866658341">Giờ đây, bạn có thể xem nội dung nghe nhìn và ảnh gần đây có trên điện thoại của mình</translation>
 <translation id="549957179819296104">Biểu tượng mới</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />Nhật ký tìm kiếm<ph name="END_LINK_SEARCH" /> và <ph name="BEGIN_LINK_GOOGLE" />các hình thức hoạt động khác<ph name="END_LINK_GOOGLE" /> có thể được lưu vào Tài khoản Google khi bạn đăng nhập. Bạn có thể xóa những dữ liệu này bất cứ lúc nào.</translation>
 <translation id="5500709606820808700">Tính năng kiểm tra an toàn đã chạy hôm nay</translation>
@@ -6329,6 +6333,7 @@
 <translation id="7152478047064750137">Tiện ích này không yêu cầu quyền đặc biệt</translation>
 <translation id="7154130902455071009">Thay đổi trang chủ của bạn thành: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Ảnh hiện có từ máy ảnh hoặc tệp</translation>
+<translation id="7160182524506337403">Giờ đây, bạn có thể xem thông báo có trên điện thoại của mình</translation>
 <translation id="7163202347044721291">Đang xác minh mã kích hoạt...</translation>
 <translation id="716640248772308851">"<ph name="EXTENSION" />" có thể đọc hình ảnh, video và tệp âm thanh trong các vị trí đã chọn.</translation>
 <translation id="7167486101654761064">&amp;Luôn mở loại tệp này</translation>
@@ -7344,6 +7349,7 @@
 <translation id="8138997515734480534">Trạng thái của <ph name="VM_NAME" /></translation>
 <translation id="8139447493436036221">Tệp trên Google Drive</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Bạn có thể thiết lập thêm các tính năng khác trong phần cài đặt của Trung tâm điều khiển điện thoại</translation>
 <translation id="8141584439523427891">Đang mở trong trình duyệt thay thế</translation>
 <translation id="8141725884565838206">Quản lý mật khẩu của bạn</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{một video}other{# video}}</translation>
@@ -7551,6 +7557,7 @@
 <translation id="833986336429795709">Để mở đường liên kết này, hãy chọn một ứng dụng</translation>
 <translation id="8342221978608739536">Chưa thử</translation>
 <translation id="8342861492835240085">Chọn một bộ sưu tập</translation>
+<translation id="8345848587667658367">Giờ đây, bạn có thể xem ứng dụng, thông báo, nội dung nghe nhìn và ảnh gần đây có trên điện thoại của mình.</translation>
 <translation id="8347227221149377169">Lệnh in</translation>
 <translation id="834785183489258869">Ở chế độ Ẩn danh, các trang web không thể dùng cookie để giám sát hoạt động duyệt web của bạn trên nhiều trang web, chẳng hạn như để điều chỉnh quảng cáo cho phù hợp với bạn. Các tính năng trên một số trang web có thể không hoạt động.</translation>
 <translation id="8350789879725387295">Công cụ bút cảm ứng trong thanh gắn</translation>
@@ -8156,6 +8163,7 @@
 <translation id="8957757410289731985">Tùy chỉnh hồ sơ</translation>
 <translation id="895944840846194039">Bộ nhớ dành cho JavaScript</translation>
 <translation id="8960208913905765425">Tính năng chuyển đổi đơn vị của Thông tin nhanh</translation>
+<translation id="8960638196855923532">Giờ đây, bạn có thể xem các thông báo và ứng dụng có trên điện thoại của mình</translation>
 <translation id="8962051932294470566">Mỗi lần, bạn chỉ có thể chia sẻ một tệp. Hãy thử lại khi quá trình chuyển hiện tại hoàn tất.</translation>
 <translation id="8962083179518285172">Ẩn chi tiết</translation>
 <translation id="8962918469425892674">Trang web này đang sử dụng cảm biến chuyển động hoặc ánh sáng.</translation>
@@ -8307,6 +8315,7 @@
 <translation id="9103868373786083162">Nhấn để quay lại, nhấn menu ngữ cảnh để xem lịch sử</translation>
 <translation id="9108035152087032312">Đặt tên cho &amp;cửa sổ...</translation>
 <translation id="9108072915170399168">Chế độ sử dụng dữ liệu hiện tại là Không dùng Internet</translation>
+<translation id="9108294543511800041">Giờ đây, bạn có thể xem thông báo, nội dung nghe nhìn và ảnh gần đây có trên điện thoại của mình.</translation>
 <translation id="9108674852930645435">Khám phá tính năng mới trên <ph name="DEVICE_TYPE" /></translation>
 <translation id="9108808586816295166">DNS bảo mật có thể không phải lúc nào cũng hoạt động</translation>
 <translation id="9109122242323516435">Để giải phóng dung lượng, hãy xóa tệp khỏi bộ nhớ thiết bị.</translation>
@@ -8431,7 +8440,6 @@
 <translation id="934503638756687833">Các mục không liệt kê ở đây cũng có thể bị xóa, nếu cần. Hãy tìm hiểu thêm về cách &lt;a href="<ph name="URL" />"&gt;bảo vệ khỏi phần mềm không mong muốn&lt;/a&gt; trong sách trắng về bảo mật của Chrome.</translation>
 <translation id="93480724622239549">Trục trặc hoặc lỗi</translation>
 <translation id="935854577147268200">Đã thay đổi điện thoại Smart Lock. Hãy nhập mật khẩu để cập nhật Smart Lock. Vào lần tới, điện thoại của bạn sẽ mở khóa <ph name="DEVICE_TYPE" />. Bạn có thể tắt tính năng Smart Lock trong phần Cài đặt.</translation>
-<translation id="93610034168535821">Tổng bộ nhớ mà các trang web sử dụng:</translation>
 <translation id="936646668635477464">Máy ảnh và micrô</translation>
 <translation id="936801553271523408">Dữ liệu chẩn đoán hệ thống</translation>
 <translation id="93766956588638423">Sửa tiện ích</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index 7582c851..1c8ce40 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -1899,6 +1899,7 @@
 <translation id="2775858145769350417">{NUM_APPS,plural, =1{移除 1 款不受支持的应用}other{移除 # 款不受支持的应用}}</translation>
 <translation id="2776560192867872731">更改“<ph name="DEVICE_NAME" />”的设备名称</translation>
 <translation id="2777251078198759550">删除此容器</translation>
+<translation id="2778471504622896352">将远程应用添加到 ChromeOS 启动器</translation>
 <translation id="2781692009645368755">Google Pay</translation>
 <translation id="2782104745158847185">安装 Linux 应用时出错</translation>
 <translation id="2783298271312924866">已下载</translation>
@@ -2214,6 +2215,7 @@
 <translation id="3067198360141518313">运行此插件</translation>
 <translation id="3071624960923923138">只需点击此处,即可打开一个新标签页</translation>
 <translation id="3072775339180057696">允许此网站查看“<ph name="FILE_NAME" />”?</translation>
+<translation id="3074499504015191586">翻译整页内容</translation>
 <translation id="3075874217500066906">必须重启才能开始 Powerwash 操作。重启后,系统将提示您确认是否要继续。</translation>
 <translation id="3076909148546628648"><ph name="DOWNLOAD_RECEIVED" />/<ph name="DOWNLOAD_TOTAL" /></translation>
 <translation id="3076966043108928831">仅保存到此设备上</translation>
@@ -3531,6 +3533,7 @@
 <translation id="4390396490617716185"><ph name="FIRST_SWITCH" />、<ph name="SECOND_SWITCH" />、<ph name="THIRD_SWITCH" /> 和另外 <ph name="NUMBER_OF_OTHER_SWITCHES" /> 个开关键</translation>
 <translation id="439266289085815679">蓝牙配置由 <ph name="USER_EMAIL" /> 控制。</translation>
 <translation id="4392896746540753732">修改配置文件</translation>
+<translation id="4393713825278446281">快速配对设备已保存到 <ph name="PRIMARY_EMAIL" /> 中</translation>
 <translation id="4394049700291259645">停用</translation>
 <translation id="4396956294839002702">{COUNT,plural, =0{打开全部书签(&amp;O)}=1{打开书签(&amp;O)}other{打开全部({COUNT} 个)书签(&amp;O)}}</translation>
 <translation id="4397372003838952832">您不需要记住此密码。系统会将它保存到 <ph name="EMAIL" /> 的 <ph name="GOOGLE_PASSWORD_MANAGER" />中。</translation>
@@ -3760,6 +3763,7 @@
 <translation id="4615586811063744755">未选择任何 Cookie</translation>
 <translation id="461661862154729886">电源</translation>
 <translation id="4617001782309103936">太短</translation>
+<translation id="4617019240346358451">刷新网页才能使用“<ph name="EXTENSION_NAME" />”</translation>
 <translation id="4617270414136722281">扩展程序选项</translation>
 <translation id="4617880081511131945">无法建立连接</translation>
 <translation id="4619564267100705184">请验证是您本人在操作</translation>
@@ -3975,6 +3979,7 @@
 <translation id="4833683849865011483">通过打印服务器找到了 1 台打印机</translation>
 <translation id="4836504898754963407">管理指纹</translation>
 <translation id="4837128290434901661">改回 Google 搜索?</translation>
+<translation id="4837165100461973682">请重新加载页面以应用更改</translation>
 <translation id="4837926214103741331">您无权使用此设备。请向此设备的所有者申请登录权限。</translation>
 <translation id="4837952862063191349">要解锁并恢复您的本地数据,请输入旧的<ph name="DEVICE_TYPE" />密码。</translation>
 <translation id="4838170306476614339">查看您手机上的照片、媒体内容和通知</translation>
@@ -4284,6 +4289,7 @@
 <translation id="5150254825601720210">Netscape 证书 SSL 服务器名称</translation>
 <translation id="5151354047782775295">请释放磁盘空间,否则系统可能会自动删除某些数据</translation>
 <translation id="5153234146675181447">移除手机</translation>
+<translation id="5153907427821264830"><ph name="STATUS" /> • <ph name="MESSAGE" /></translation>
 <translation id="5154108062446123722"><ph name="PRINTING_DESTINATION" />高级设置</translation>
 <translation id="5154702632169343078">主题背景</translation>
 <translation id="5155327081870541046">在地址栏中,输入与您要用作搜索范围的网站对应的快捷字词,例如“@bookmarks”。然后,按您的首选键盘快捷键,并输入搜索字词。</translation>
@@ -5057,6 +5063,7 @@
 <translation id="5933522550144185133"><ph name="APP_NAME" /> 正在使用您的摄像头和麦克风</translation>
 <translation id="5935158534896975820">正在准备证书签名请求(正在等待服务器的帮助)</translation>
 <translation id="5935656526031444304">管理安全浏览设置</translation>
+<translation id="5936065461722368675">翻译整页内容</translation>
 <translation id="5938002010494270685">可进行安全性升级</translation>
 <translation id="5939518447894949180">重置</translation>
 <translation id="5939719276406088041">无法创建快捷方式</translation>
@@ -5916,6 +5923,7 @@
 <translation id="6790497603648687708">已远程添加“<ph name="EXTENSION_NAME" />”</translation>
 <translation id="6790820461102226165">添加用户…</translation>
 <translation id="6793604637258913070">文本插入符号出现或移动时突出显示</translation>
+<translation id="6793879402816827484">↓ <ph name="STATUS" /></translation>
 <translation id="6795371939514004514">“自动扫描”功能让您能够自动在屏幕上的各项内容之间移动。当某项内容处于突出显示状态时,按“选择”即可启用它。</translation>
 <translation id="6795884519221689054">熊猫</translation>
 <translation id="6797493596609571643">糟糕,出问题了。</translation>
@@ -7788,6 +7796,7 @@
 <translation id="8642947597466641025">放大文字</translation>
 <translation id="8643443571868262066"><ph name="FILE_NAME" /> 可能含有危险内容。发送给 Google 高级保护进行扫描?</translation>
 <translation id="8644047503904673749">{COUNT,plural, =0{无 Cookie}=1{屏蔽了 1 个 Cookie}other{屏蔽了 # 个 Cookie}}</translation>
+<translation id="864423554496711319">设备已保存到您的帐号中</translation>
 <translation id="8644655801811752511">无法重置此安全密钥。请尝试在插入此密钥后立即重置它。</translation>
 <translation id="8645354835496065562">继续允许使用传感器</translation>
 <translation id="8645920082661222035">预测危险事件并在此类事件发生前向您发出警告</translation>
@@ -8392,7 +8401,6 @@
 <translation id="934503638756687833">如有必要,此处未列出的内容也会被移除。请参阅 Chrome 隐私权政策白皮书,详细了解&lt;a href="<ph name="URL" />"&gt;垃圾软件防护&lt;/a&gt;。</translation>
 <translation id="93480724622239549">问题或错误</translation>
 <translation id="935854577147268200">Smart Lock 所用的配对手机已更改。请输入您的密码以更新 Smart Lock。下次,您就能使用新的配对手机解锁您的 <ph name="DEVICE_TYPE" /> 了。您可在“设置”中关闭 Smart Lock。</translation>
-<translation id="93610034168535821">网站占用的总存储空间:</translation>
 <translation id="936646668635477464">摄像头和麦克风</translation>
 <translation id="936801553271523408">系统诊断数据</translation>
 <translation id="93766956588638423">修复扩展程序</translation>
diff --git a/chrome/app/resources/generated_resources_zh-HK.xtb b/chrome/app/resources/generated_resources_zh-HK.xtb
index a08fe91..85611cf 100644
--- a/chrome/app/resources/generated_resources_zh-HK.xtb
+++ b/chrome/app/resources/generated_resources_zh-HK.xtb
@@ -8431,7 +8431,6 @@
 <translation id="934503638756687833">視乎情況,在此未有列出的項目也會一併移除。有關&lt;a href="<ph name="URL" />"&gt;垃圾軟件防護&lt;/a&gt;的詳情,請參閱 Chrome 私隱權白皮書。</translation>
 <translation id="93480724622239549">問題或錯誤</translation>
 <translation id="935854577147268200">Smart Lock 手機已變更,請輸入密碼以更新 Smart Lock。下次您便可使用手機來解鎖 <ph name="DEVICE_TYPE" />。您可在「設定」中停用 Smart Lock。</translation>
-<translation id="93610034168535821">網站已使用的總儲存空間:</translation>
 <translation id="936646668635477464">攝錄機和麥克風</translation>
 <translation id="936801553271523408">系統診斷數據</translation>
 <translation id="93766956588638423">修復擴充程式</translation>
diff --git a/chrome/app/resources/generated_resources_zh-TW.xtb b/chrome/app/resources/generated_resources_zh-TW.xtb
index 468449a..8bdef93 100644
--- a/chrome/app/resources/generated_resources_zh-TW.xtb
+++ b/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -8411,7 +8411,6 @@
 <translation id="934503638756687833">如有必要,這裡未列出的項目也會一併移除。如要進一步瞭解&lt;a href="<ph name="URL" />"&gt;垃圾軟體防護功能&lt;/a&gt;,請參閱 Chrome 隱私權白皮書。</translation>
 <translation id="93480724622239549">問題或錯誤</translation>
 <translation id="935854577147268200">Smart Lock 手機已變更,請輸入你的密碼以更新 Smart Lock,這樣下次手機就會為你的 <ph name="DEVICE_TYPE" /> 解鎖。你可以在「設定」中停用 Smart Lock</translation>
-<translation id="93610034168535821">網站使用的總儲存空間:</translation>
 <translation id="936646668635477464">攝影機和麥克風</translation>
 <translation id="936801553271523408">系統診斷資料</translation>
 <translation id="93766956588638423">修復擴充功能</translation>
diff --git a/chrome/app/resources/generated_resources_zu.xtb b/chrome/app/resources/generated_resources_zu.xtb
index 253d88f..4422bd41 100644
--- a/chrome/app/resources/generated_resources_zu.xtb
+++ b/chrome/app/resources/generated_resources_zu.xtb
@@ -1559,6 +1559,7 @@
 <translation id="2433836460518180625">Vula idivayisi kuphela</translation>
 <translation id="2434449159125086437">Ayikwazi ukusetha iphrinta. Sicela uhlole ukulungiselelwa uphinde uzame futhi.</translation>
 <translation id="2434758125294431199">Khetha ukuthi obani ongabelana nawe</translation>
+<translation id="2434915728183570229">Manje usungabuka ama-app wefoni yakho</translation>
 <translation id="2435137177546457207">Imigomo Eyengeziwe ye-Google Chrome ne-ChromeOS Flex</translation>
 <translation id="2435248616906486374">Inethiwekhi inqanyuliwe</translation>
 <translation id="2435457462613246316">Bonisa iphasiwedi</translation>
@@ -3737,7 +3738,7 @@
 <translation id="4559617833001311418">Leli sayithi lifinyelela kuzinzwa zakho zokunyakaza noma zokukhanya.</translation>
 <translation id="4561893854334016293">Azikho izimvume ezishintshwe kamuva</translation>
 <translation id="4562155214028662640">Engeza izigxivizo zeminwe</translation>
-<translation id="4563210852471260509">Ulimi lokufaka lasekuqaleni isi-Chinese</translation>
+<translation id="4563210852471260509">Ulimi lokufaka lasekuqaleni Chinese</translation>
 <translation id="4563880231729913339">Umunwe 3</translation>
 <translation id="4564245002465020751">Qedela ukusetha efonini yakho</translation>
 <translation id="4565377596337484307">Fihla iphasiwedi</translation>
@@ -4242,6 +4243,7 @@
 <translation id="5072900412896857127">Imigomo Yesevisi ye-Google Play ayikwazi ukulayishwa. Sicela uhlole ukuxhumeka kwakho kwenethiwekhi uphinde uzame futhi.</translation>
 <translation id="5073956501367595100">{0,plural,offset:2 =1{<ph name="FILE1" />}=2{<ph name="FILE1" />, <ph name="FILE2" />}one{<ph name="FILE1" />, <ph name="FILE2" />, nokuningi okungu-#}other{<ph name="FILE1" />, <ph name="FILE2" />, nokuningi okungu-#}}</translation>
 <translation id="5074318175948309511">Leli khasi kungenzeka lidinge ukuphinda lilayishwe ngaphambi kokuthi izilungiselelo ezintsha zisebenze.</translation>
+<translation id="5074761966806028321">Imvume isadingeka ukuqedela ukusetha</translation>
 <translation id="5075910247684008552">Okuqukethwe okungavikelekile kuvinjelwa ngokuzenzakalela kumasayithi avikelekile</translation>
 <translation id="5078638979202084724">Beka uphawu lokubekisa kuwo wonke amathebhu</translation>
 <translation id="5078796286268621944">Iphinikhodi engalungile</translation>
@@ -4607,6 +4609,7 @@
 <translation id="5449551289610225147">Iphasiwedi engavumelekile</translation>
 <translation id="5449588825071916739">Beka uphawu lokubekisa wonke amathebhu</translation>
 <translation id="5449716055534515760">Vala iwindi</translation>
+<translation id="5452446625764825792">Manje usungabuka izithombe zefoni yakho zakamuva, imidiya, nama-app</translation>
 <translation id="5452976525201205853">Isi-<ph name="LANGUAGE" /> (sisebenza kungaxhunyiwe ku-intanethi)</translation>
 <translation id="5454166040603940656">ne-<ph name="PROVIDER" /></translation>
 <translation id="545484289444831485">Bona imiphumela eyengeziwe yosesho</translation>
@@ -4667,6 +4670,7 @@
 <translation id="5499211612787418966">Leli bhokisi aligxilisiwe okwamanje. Cindezela u-Alt-Shift A ukuze ugxilise leli bhokisi.</translation>
 <translation id="5499313591153584299">Leli fayela lingaba nobungozi kukhompyutha yakho.</translation>
 <translation id="5499453227627332024">Isithuthukisi siyatholakala ku-Linux Container yakho. Ungase futhi uyithuthukise ngemuva kwesikhathi kusuka kuhlelo lokusebenza Lamasethingi.</translation>
+<translation id="5499476581866658341">Manje usungabuka izithombe zakho zakamuva nemidiya</translation>
 <translation id="549957179819296104">Isithonjana esisha</translation>
 <translation id="5500168250243071806"><ph name="BEGIN_LINK_SEARCH" />Umlando wosesho<ph name="END_LINK_SEARCH" /> kanye <ph name="BEGIN_LINK_GOOGLE" />nezinye izindlela zomsebenzi<ph name="END_LINK_GOOGLE" /> kungase kulondolozwe ku-akhawunti yakho ye-Google lapho ungene ngemvume. Ungakusula noma kunini</translation>
 <translation id="5500709606820808700">Ukuhlola kokuphepha kusebenze namuhla</translation>
@@ -6334,6 +6338,7 @@
 <translation id="7152478047064750137">Lesi sandiso asidingi izimvume ezibalulekile</translation>
 <translation id="7154130902455071009">Guqula ikhasi lakho lokuqala ulenze i-: <ph name="START_PAGE" /></translation>
 <translation id="7155171745945906037">Isithombe esikhona kusukela kukhamera noma ifayela</translation>
+<translation id="7160182524506337403">Manje usungabuka izaziso zefoni yakho</translation>
 <translation id="7163202347044721291">Iqinisekisa ikhodi yokwenza kusebenze...</translation>
 <translation id="716640248772308851">I-"<ph name="EXTENSION" />" ingafunda izithombe, ividiyo, namafayela womsindo kuzindawo ezihloliwe.</translation>
 <translation id="7167486101654761064">&amp;Hlala uvule amafayela walolu hlobo</translation>
@@ -7347,6 +7352,7 @@
 <translation id="8138997515734480534"><ph name="VM_NAME" /> isimo</translation>
 <translation id="8139447493436036221">Amafayela we-Google Drive</translation>
 <translation id="8140070492745508800"><ph name="FIRST_DEVICE" />, <ph name="SECOND_DEVICE" /></translation>
+<translation id="8141418916163800697">Ungasetha izakhi eziningi kumasethingi Wehabhu Yefoni</translation>
 <translation id="8141584439523427891">Ivula kwesinye isiphequluli manje</translation>
 <translation id="8141725884565838206">Phatha amaphasiwedi wakho</translation>
 <translation id="814204052173971714">{COUNT,plural, =1{ividiyo}one{amavidiyo angu-#}other{amavidiyo angu-#}}</translation>
@@ -7554,6 +7560,7 @@
 <translation id="833986336429795709">Ukuze uvule lesi sixhumanisi, khetha uhlelo lokusebenza</translation>
 <translation id="8342221978608739536">Ayizamanga</translation>
 <translation id="8342861492835240085">Khetha iqoqo</translation>
+<translation id="8345848587667658367">Manje usungabuka izithombe zefoni yakho zakamuva, imidiya, izaziso, nama-app</translation>
 <translation id="8347227221149377169">Imisebenzi yokuphrinta</translation>
 <translation id="834785183489258869">Lapho uku-incognito, amasayithi awakwazi ukusebenzisa amakhukhi akho ukubona umsebenzi wakho wokuphequlula kumasayithi ahlukahlukene, ngokwesibonelo, ukwenza izikhangiso ngokwezifiso. Izakhi ezikwamanye amasayithi zingase zingasebenzi.</translation>
 <translation id="8350789879725387295">Amathuluzi we-stylus kudokhu</translation>
@@ -7627,7 +7634,7 @@
 <translation id="8418445294933751433">Bonisa njengethebhu</translation>
 <translation id="8419098111404128271">Imiphumela yosesho ye-'<ph name="SEARCH_TEXT" />'</translation>
 <translation id="8420308167132684745">Hlela okufakwa kusichazamazwi</translation>
-<translation id="8421361468937925547">Okushuthwe Bukhoma (I-English kuphela)</translation>
+<translation id="8421361468937925547">Okushuthwe Bukhoma (English kuphela)</translation>
 <translation id="8422787418163030046">Ithreyi alikho</translation>
 <translation id="8424250197845498070">Ivinjwe Ukuvikela Okuthuthukile</translation>
 <translation id="8425213833346101688">Guqula</translation>
@@ -8160,6 +8167,7 @@
 <translation id="8957757410289731985">Enza ngezifiso iphrofayela</translation>
 <translation id="895944840846194039">Imemori ye-JavaScript</translation>
 <translation id="8960208913905765425">Ukuguqulwa kweyunithi Kwezimpendulo Ezisheshayo</translation>
+<translation id="8960638196855923532">Manje usungabuka izaziso zefoni yakho nama-app</translation>
 <translation id="8962051932294470566">Ungabelana ngefayela elilodwa kuphela ngesikhaathi. Zama futhi lapho ukudlulisa kwamanje sekuqedile.</translation>
 <translation id="8962083179518285172">Fihla imininingwane</translation>
 <translation id="8962918469425892674">Leli sayithi lisebenzisa izinzwa zokunyakaza noma zokukhanya.</translation>
@@ -8311,6 +8319,7 @@
 <translation id="9103868373786083162">Cindezela ukuze ubuyele emuva, kumenyu yokuqukethwe ukuze ubone umlando</translation>
 <translation id="9108035152087032312">Igama newindi...</translation>
 <translation id="9108072915170399168">Ukusetshenziswa kwedatha kwamanje Kungaphandle kwe-inthanethi</translation>
+<translation id="9108294543511800041">Manje usungabuka izithombe zefoni yakho zakamuva, imidiya, nezaziso</translation>
 <translation id="9108674852930645435">Hlola ukuthi yini entsha ku-<ph name="DEVICE_TYPE" /> yakho</translation>
 <translation id="9108808586816295166">Ukuvikela i-DNS kungenzeka kungatholakali ngaso sonke isikhathi</translation>
 <translation id="9109122242323516435">Ukuze ukhulule isikhala, susa amafayela kusukela kusitoreji sedivayisi.</translation>
@@ -8435,7 +8444,6 @@
 <translation id="934503638756687833">Izinto ezingafakiwe lapha nazo zizosuswa, uma kudingeka. Funda kabanzi mayelana &lt;a href="<ph name="URL" />"&gt;ukuvikelwa kwesofthiwe okungafuneki&lt;/a&gt; kuphepha elimhlophe lobumfihlo le-Chrome.</translation>
 <translation id="93480724622239549">Isiphazamisi noma iphutha</translation>
 <translation id="935854577147268200">Ifoni ye-Smart Lock ishintshiwe. Faka iphasiwedi yakho ukuze ubuyekeze i-Smart Lock. Ngesikhathi esilandelayo, ifoni yakho izovula i-<ph name="DEVICE_TYPE" /> yakho. Ungavala i-Smart Lock kuzilungiselelo</translation>
-<translation id="93610034168535821">Isitoreji esiphelele esisetshenziswe amasayithi:</translation>
 <translation id="936646668635477464">Ikhamera nemakrofoni</translation>
 <translation id="936801553271523408">Idatha yokuxilonga yesistimu</translation>
 <translation id="93766956588638423">Lungisa isandiso</translation>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index a64782b..be8fe31 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -306,8 +306,6 @@
     "chrome_content_browser_client_parts.h",
     "chrome_content_browser_client_receiver_bindings.cc",
     "chrome_notification_types.h",
-    "chrome_preloading.cc",
-    "chrome_preloading.h",
     "chrome_resource_bundle_helper.cc",
     "chrome_resource_bundle_helper.h",
     "client_hints/client_hints_factory.cc",
@@ -1359,6 +1357,8 @@
     "prefs/profile_pref_store_manager.h",
     "prefs/session_startup_pref.cc",
     "prefs/session_startup_pref.h",
+    "preloading/chrome_preloading.cc",
+    "preloading/chrome_preloading.h",
     "prerender/prerender_manager.cc",
     "prerender/prerender_manager.h",
     "prerender/prerender_utils.cc",
@@ -2994,6 +2994,12 @@
       "enterprise/reporting/reporting_delegate_factory_android.h",
       "enterprise/util/android_enterprise_info.cc",
       "enterprise/util/android_enterprise_info.h",
+      "fast_checkout/fast_checkout_client.cc",
+      "fast_checkout/fast_checkout_client.h",
+      "fast_checkout/fast_checkout_client_impl.cc",
+      "fast_checkout/fast_checkout_client_impl.h",
+      "fast_checkout/fast_checkout_external_action_delegate.cc",
+      "fast_checkout/fast_checkout_external_action_delegate.h",
       "feature_guide/notifications/android/feature_notification_guide_bridge.cc",
       "feature_guide/notifications/android/feature_notification_guide_bridge.h",
       "feature_guide/notifications/android/feature_notification_guide_service_factory_android.cc",
@@ -3013,6 +3019,8 @@
       "feed/android/refresh_task_scheduler_impl.cc",
       "feed/android/refresh_task_scheduler_impl.h",
       "feed/android/web_feed_bridge.cc",
+      "feedback/android/family_info_feedback_source.cc",
+      "feedback/android/family_info_feedback_source.h",
       "file_select_helper_contacts_android.cc",
       "file_select_helper_contacts_android.h",
       "first_run/android/first_run_prefs.cc",
@@ -3277,6 +3285,7 @@
       "//chrome/browser/endpoint_fetcher:jni_headers",
       "//chrome/browser/feed/android:jni_headers",
       "//chrome/browser/feedback/android",
+      "//chrome/browser/feedback/android:jni_headers",
       "//chrome/browser/flags:flags_android",
       "//chrome/browser/language/android:jni_headers",
       "//chrome/browser/long_screenshots:services",
@@ -4430,6 +4439,7 @@
       "//components/user_notes:features",
       "//components/user_notes/browser",
       "//components/user_notes/interfaces",
+      "//components/user_notes/storage",
       "//components/web_modal",
       "//courgette:courgette_lib",
       "//services/device/public/cpp/hid",
@@ -5095,8 +5105,12 @@
       "//chromeos/ash/components/assistant:buildflags",
       "//chromeos/ash/components/dbus/concierge",
       "//chromeos/ash/components/dbus/session_manager",
+      "//chromeos/ash/components/dbus/userdataauth:userdataauth",
+      "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
       "//chromeos/ash/components/memory",
       "//chromeos/ash/services/assistant/public/cpp",
+      "//chromeos/ash/services/cros_healthd/public/cpp",
+      "//chromeos/ash/services/cros_healthd/public/mojom",
       "//chromeos/components/feature_usage",
       "//chromeos/components/local_search_service",
       "//chromeos/components/local_search_service/public/cpp:cpp",
@@ -5117,15 +5131,11 @@
       "//chromeos/dbus/tpm_manager",
       "//chromeos/dbus/tpm_manager:tpm_manager_proto",
       "//chromeos/dbus/update_engine",
-      "//chromeos/dbus/userdataauth:userdataauth",
-      "//chromeos/dbus/userdataauth:userdataauth_proto",
       "//chromeos/dbus/util",
       "//chromeos/login/login_state",
       "//chromeos/network",
       "//chromeos/services/bluetooth_config",
       "//chromeos/services/bluetooth_config/public/mojom",
-      "//chromeos/services/cros_healthd/public/cpp",
-      "//chromeos/services/cros_healthd/public/mojom",
       "//chromeos/services/network_config",
       "//chromeos/services/network_config:in_process_instance",
       "//chromeos/services/network_config/public/mojom",
@@ -5700,6 +5710,10 @@
       "notifications/win/notification_template_builder.cc",
       "notifications/win/notification_template_builder.h",
       "obsolete_system/obsolete_system_win.cc",
+      "os_crypt/app_bound_encryption_metrics_win.cc",
+      "os_crypt/app_bound_encryption_metrics_win.h",
+      "os_crypt/app_bound_encryption_win.cc",
+      "os_crypt/app_bound_encryption_win.h",
       "password_manager/password_manager_util_win.cc",
       "password_manager/password_manager_util_win.h",
       "performance_manager/mechanisms/working_set_trimmer_win.cc",
@@ -5802,7 +5816,7 @@
       "//chrome/chrome_elf:third_party_shared_defines",
       "//chrome/common:version_header",
       "//chrome/credential_provider/common:common_constants",
-      "//chrome/elevation_service:elevation_service_idl",
+      "//chrome/elevation_service:public_headers",
       "//chrome/install_static:install_static_util",
       "//chrome/installer/util:with_no_strings",
       "//chrome/notification_helper:constants",
@@ -7682,7 +7696,7 @@
     }
   }
 
-  if (use_aura && use_nss_certs) {
+  if (enable_webui_certificate_viewer) {
     deps += [ "//chrome/browser/resources/certificate_viewer:build_ts" ]
   }
 
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 523f792..6087edb4 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -578,44 +578,6 @@
      std::size(kForceDark_IncreaseTextContrast), nullptr}};
 #endif  // !BUILDFLAG(IS_CHROMEOS)
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-const FeatureEntry::FeatureParam kShelfSwipeOffset30[] = {
-    {"shelf_swipe_offset", "30"}};
-const FeatureEntry::FeatureParam kShelfSwipeOffset50[] = {
-    {"shelf_swipe_offset", "50"}};
-const FeatureEntry::FeatureParam kShelfSwipeOffset80[] = {
-    {"shelf_swipe_offset", "80"}};
-const FeatureEntry::FeatureParam kShelfSwipeOffset100[] = {
-    {"shelf_swipe_offset", "100"}};
-
-const FeatureEntry::FeatureVariation
-    kShelfPalmRejectionSwipeOffsetVariations[] = {
-        {"30px offset", kShelfSwipeOffset30, std::size(kShelfSwipeOffset30),
-         nullptr},
-        {"50px offset", kShelfSwipeOffset50, std::size(kShelfSwipeOffset50),
-         nullptr},
-        {"80px offset", kShelfSwipeOffset80, std::size(kShelfSwipeOffset80),
-         nullptr},
-        {"100px offset", kShelfSwipeOffset100, std::size(kShelfSwipeOffset100),
-         nullptr}};
-
-const FeatureEntry::FeatureParam kShelfTouchArea100[] = {
-    {"shelf_touch_area", "100"}};
-const FeatureEntry::FeatureParam kShelfTouchArea150[] = {
-    {"shelf_touch_area", "150"}};
-const FeatureEntry::FeatureParam kShelfTouchArea200[] = {
-    {"shelf_touch_area", "200"}};
-const FeatureEntry::FeatureParam kShelfTouchArea250[] = {
-    {"shelf_touch_area", "250"}};
-
-const FeatureEntry::FeatureVariation kShelfPalmRejectionTouchAreaVariations[] =
-    {{"100px area", kShelfTouchArea100, std::size(kShelfTouchArea100), nullptr},
-     {"150px area", kShelfTouchArea150, std::size(kShelfTouchArea150), nullptr},
-     {"200px area", kShelfTouchArea200, std::size(kShelfTouchArea200), nullptr},
-     {"250px area", kShelfTouchArea250, std::size(kShelfTouchArea250),
-      nullptr}};
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
 const FeatureEntry::FeatureParam kMBIModeLegacy[] = {{"mode", "legacy"}};
 const FeatureEntry::FeatureParam kMBIModeEnabledPerRenderProcessHost[] = {
     {"mode", "per_render_process_host"}};
@@ -5647,15 +5609,6 @@
      flag_descriptions::kDownloadAutoResumptionNativeName,
      flag_descriptions::kDownloadAutoResumptionNativeDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(download::features::kDownloadAutoResumptionNative)},
-
-    {"download-later", flag_descriptions::kDownloadLaterName,
-     flag_descriptions::kDownloadLaterDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(download::features::kDownloadLater)},
-
-    {"download-later-debug-on-wifi",
-     flag_descriptions::kDownloadLaterDebugOnWifiName,
-     flag_descriptions::kDownloadLaterDebugOnWifiNameDescription, kOsAndroid,
-     SINGLE_VALUE_TYPE(download::switches::kDownloadLaterDebugOnWifi)},
 #endif
 
     {"enable-new-download-backend",
@@ -7196,6 +7149,10 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(ash::features::kProductivityLauncher,
                                     kProductivityLauncherVariations,
                                     "ProductivityLauncher")},
+    {"autocomplete-extended-suggestions",
+     flag_descriptions::kAutocompleteExtendedSuggestionsName,
+     flag_descriptions::kAutocompleteExtendedSuggestionsDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(ash::features::kAutocompleteExtendedSuggestions)},
     {"compact-bubble-launcher", flag_descriptions::kCompactBubbleLauncherName,
      flag_descriptions::kCompactBubbleLauncherDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(app_list_features::kCompactBubbleLauncher)},
@@ -7209,16 +7166,7 @@
     {"shelf-palm-rejection-swipe-offset",
      flag_descriptions::kShelfPalmRejectionSwipeOffsetName,
      flag_descriptions::kShelfPalmRejectionSwipeOffsetDescription, kOsCrOS,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(
-         ash::features::kShelfPalmRejectionSwipeOffset,
-         kShelfPalmRejectionSwipeOffsetVariations,
-         "ShelfPalmRejectionSwipeOffset")},
-    {"shelf-palm-rejection-touch-area",
-     flag_descriptions::kShelfPalmRejectionTouchAreaName,
-     flag_descriptions::kShelfPalmRejectionTouchAreaDescription, kOsCrOS,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(ash::features::kShelfPalmRejectionTouchArea,
-                                    kShelfPalmRejectionTouchAreaVariations,
-                                    "ShelfPalmRejectionTouchArea")},
+     FEATURE_VALUE_TYPE(ash::features::kShelfPalmRejectionSwipeOffset)},
     {"force-show-continue-section",
      flag_descriptions::kForceShowContinueSectionName,
      flag_descriptions::kForceShowContinueSectionDescription, kOsCrOS,
@@ -8456,11 +8404,6 @@
      flag_descriptions::kLacrosMergeIcuDataFileDescription, kOsCrOS | kOsLacros,
      FEATURE_VALUE_TYPE(base::i18n::kLacrosMergeIcuDataFile)},
 
-    {"lacros-non-syncing-profiles",
-     flag_descriptions::kLacrosNonSyncingProfilesName,
-     flag_descriptions::kLacrosNonSyncingProfilesDescription, kOsAll,
-     FEATURE_VALUE_TYPE(switches::kLacrosNonSyncingProfiles)},
-
     {"lacros-screen-coordinates-enabled",
      flag_descriptions::kLacrosScreenCoordinatesEnabledName,
      flag_descriptions::kLacrosScreenCoordinatesEnabledDescription,
@@ -8790,6 +8733,13 @@
      FEATURE_VALUE_TYPE(device::features::kWebBluetoothConfirmPairingSupport)},
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
 
+    {"quick-intensive-throttling-after-loading",
+     flag_descriptions::kQuickIntensiveWakeUpThrottlingAfterLoadingName,
+     flag_descriptions::kQuickIntensiveWakeUpThrottlingAfterLoadingDescription,
+     kOsAll,
+     FEATURE_VALUE_TYPE(
+         blink::features::kQuickIntensiveWakeUpThrottlingAfterLoading)},
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/accessibility/accessibility_ui.cc b/chrome/browser/accessibility/accessibility_ui.cc
index 8279403..4f66e643 100644
--- a/chrome/browser/accessibility/accessibility_ui.cc
+++ b/chrome/browser/accessibility/accessibility_ui.cc
@@ -240,7 +240,7 @@
   bool show_internal = pref->GetBoolean(prefs::kShowInternalAccessibilityTree);
   data.SetStringKey(kInternal, show_internal ? kOn : kOff);
 
-  std::unique_ptr<base::ListValue> rvh_list(new base::ListValue());
+  std::unique_ptr<base::ListValue> page_list(new base::ListValue());
   std::unique_ptr<content::RenderWidgetHostIterator> widget_iter(
       content::RenderWidgetHost::GetRenderWidgetHosts());
 
@@ -256,6 +256,8 @@
     content::WebContentsDelegate* delegate = web_contents->GetDelegate();
     if (!delegate)
       continue;
+    if (web_contents->GetPrimaryMainFrame()->GetRenderViewHost() != rvh)
+      continue;
     // Ignore views that are never user-visible, like background pages.
     if (delegate->IsNeverComposited(web_contents))
       continue;
@@ -267,9 +269,9 @@
         BuildTargetDescriptor(rvh);
     descriptor->SetBoolKey(kNative, is_native_enabled);
     descriptor->SetBoolKey(kWeb, is_web_enabled);
-    rvh_list->Append(base::Value::FromUniquePtrValue(std::move(descriptor)));
+    page_list->Append(base::Value::FromUniquePtrValue(std::move(descriptor)));
   }
-  data.Set(kPagesField, std::move(rvh_list));
+  data.Set(kPagesField, std::move(page_list));
 
   std::unique_ptr<base::ListValue> browser_list(new base::ListValue());
 #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/accessibility/ax_screen_ai_annotator.cc b/chrome/browser/accessibility/ax_screen_ai_annotator.cc
index 56d93da..22085df 100644
--- a/chrome/browser/accessibility/ax_screen_ai_annotator.cc
+++ b/chrome/browser/accessibility/ax_screen_ai_annotator.cc
@@ -53,6 +53,8 @@
 void AXScreenAIAnnotator::OnAnnotationReceived(
     const ui::AXTreeID& ax_tree_id,
     const ui::AXTreeUpdate& updates) {
+  VLOG(2) << "AxScreenAIAnnotator received:\n" << updates.ToString();
+
   ui::AXTreeManager* manager =
       ui::AXTreeManagerMap::GetInstance().GetManager(ax_tree_id);
 
@@ -62,9 +64,7 @@
     return;
   }
 
-  VLOG(2) << "AxScreenAIAnnotator received:\n" << updates.ToString();
-  // TODO(https://crbug.com/1278249): To keep the ScreenAI related heuristics
-  // centralized, apply |updates| here.
+  // TODO(https://crbug.com/1278249): Use |updates|.
 }
 
 }  // namespace screen_ai
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h
index a8131064c..dd597e5 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h
@@ -47,6 +47,7 @@
 
  private:
   friend class AppPlatformInputMetricsTest;
+  friend class WebsiteMetricsBrowserTest;
 
   // Helper function to check if a new day has arrived.
   void CheckForNewDay();
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.h b/chrome/browser/apps/app_service/metrics/website_metrics.h
index 72732ba..367474ac 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics.h
+++ b/chrome/browser/apps/app_service/metrics/website_metrics.h
@@ -24,6 +24,8 @@
 
 namespace apps {
 
+class WebsiteMetricsBrowserTest;
+
 // WebsiteMetrics monitors creation/deletion of Browser and its
 // TabStripModel to record the website usage time metrics.
 class WebsiteMetrics : public BrowserListObserver,
@@ -59,6 +61,8 @@
       history::HistoryService* history_service) override;
 
  private:
+  friend class WebsiteMetricsBrowserTest;
+
   // This class monitors the activated WebContent for the activated browser
   // window and notifies a navigation to the WebsiteMetrics.
   class ActiveTabWebContentsObserver : public content::WebContentsObserver {
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc b/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
new file mode 100644
index 0000000..2eec710
--- /dev/null
+++ b/chrome/browser/apps/app_service/metrics/website_metrics_browsertest.cc
@@ -0,0 +1,228 @@
+// 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 "base/containers/contains.h"
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
+#include "chrome/browser/web_applications/web_app_id.h"
+#include "chrome/browser/web_applications/web_app_id_constants.h"
+#include "chrome/browser/web_applications/web_app_install_info.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/page_navigator.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/test_navigation_observer.h"
+
+namespace apps {
+
+class WebsiteMetricsBrowserTest : public InProcessBrowserTest {
+ protected:
+  void SetUpOnMainThread() override {
+    InProcessBrowserTest::SetUpOnMainThread();
+    Profile* profile = ProfileManager::GetPrimaryUserProfile();
+    auto metrics_service_ =
+        std::make_unique<AppPlatformMetricsService>(profile);
+    app_platform_metrics_service_ = metrics_service_.get();
+    auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile);
+    DCHECK(proxy);
+    proxy->SetAppPlatformMetricsServiceForTesting(std::move(metrics_service_));
+
+    app_platform_metrics_service_->Start(proxy->AppRegistryCache(),
+                                         proxy->InstanceRegistry());
+  }
+
+  void TearDownOnMainThread() override {
+    InProcessBrowserTest::TearDownOnMainThread();
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    InProcessBrowserTest ::SetUpCommandLine(command_line);
+    command_line->AppendSwitch(switches::kNoStartupWindow);
+  }
+
+  Browser* CreateBrowser() {
+    Profile* profile = ProfileManager::GetPrimaryUserProfile();
+    Browser::CreateParams params(profile, true /* user_gesture */);
+    Browser* browser = Browser::Create(params);
+    browser->window()->Show();
+    return browser;
+  }
+
+  content::WebContents* NavigateAndWait(Browser* browser,
+                                        const std::string& url,
+                                        WindowOpenDisposition disposition) {
+    NavigateParams params(browser, GURL(url),
+                          ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
+    params.disposition = disposition;
+    Navigate(&params);
+    auto* contents = params.navigated_or_inserted_contents;
+    DCHECK_EQ(chrome::FindBrowserWithWebContents(
+                  params.navigated_or_inserted_contents),
+              browser);
+    content::TestNavigationObserver observer(contents);
+    observer.Wait();
+    return contents;
+  }
+
+  content::WebContents* InsertForegroundTab(Browser* browser,
+                                            const std::string& url) {
+    return NavigateAndWait(browser, url,
+                           WindowOpenDisposition::NEW_FOREGROUND_TAB);
+  }
+
+  web_app::AppId InstallWebApp(const std::string& start_url,
+                               web_app::UserDisplayMode user_display_mode) {
+    auto info = std::make_unique<WebAppInstallInfo>();
+    info->start_url = GURL(start_url);
+    info->user_display_mode = user_display_mode;
+    Profile* profile = ProfileManager::GetPrimaryUserProfile();
+    auto app_id = web_app::test::InstallWebApp(profile, std::move(info));
+    return app_id;
+  }
+
+  web_app::AppId InstallWebAppOpeningAsTab(const std::string& start_url) {
+    return InstallWebApp(start_url, web_app::UserDisplayMode::kBrowser);
+  }
+
+  WebsiteMetrics* website_metrics() {
+    DCHECK(app_platform_metrics_service_);
+    return app_platform_metrics_service_->website_metrics_.get();
+  }
+
+  base::flat_map<aura::Window*, content::WebContents*>&
+  window_to_web_contents() {
+    return website_metrics()->window_to_web_contents_;
+  }
+
+  base::flat_map<content::WebContents*,
+                 std::unique_ptr<WebsiteMetrics::ActiveTabWebContentsObserver>>&
+  webcontents_to_observer_map() {
+    return website_metrics()->webcontents_to_observer_map_;
+  }
+
+ protected:
+  AppPlatformMetricsService* app_platform_metrics_service_ = nullptr;
+};
+
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, InsertAndCloseTabs) {
+  InstallWebAppOpeningAsTab("https://a.example.org");
+
+  Browser* browser = CreateBrowser();
+  auto* window = browser->window()->GetNativeWindow();
+  EXPECT_EQ(1u, window_to_web_contents().size());
+
+  // Insert an app tab.
+  InsertForegroundTab(browser, "https://a.example.org");
+  EXPECT_EQ(1u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window]));
+  EXPECT_EQ(window_to_web_contents()[window]->GetVisibleURL(),
+            GURL("https://a.example.org"));
+
+  // Open a second tab in foreground with no app.
+  InsertForegroundTab(browser, "https://b.example.org");
+  EXPECT_EQ(1u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window]));
+  EXPECT_EQ(window_to_web_contents()[window]->GetVisibleURL(),
+            GURL("https://b.example.org"));
+
+  // Open two more tabs in foreground and close them.
+  auto* tab_app3 = InsertForegroundTab(browser, "https://c.example.org");
+  auto* tab_app4 = InsertForegroundTab(browser, "https://d.example.org");
+
+  EXPECT_EQ(1u, webcontents_to_observer_map().size());
+  EXPECT_EQ(1u, window_to_web_contents().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window]));
+  EXPECT_EQ(window_to_web_contents()[window]->GetVisibleURL(),
+            GURL("https://d.example.org"));
+
+  // Close in reverse order.
+  int i = browser->tab_strip_model()->GetIndexOfWebContents(tab_app4);
+  browser->tab_strip_model()->CloseWebContentsAt(
+      i, TabStripModel::CLOSE_USER_GESTURE);
+  i = browser->tab_strip_model()->GetIndexOfWebContents(tab_app3);
+  browser->tab_strip_model()->CloseWebContentsAt(
+      i, TabStripModel::CLOSE_USER_GESTURE);
+  EXPECT_EQ(1u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window]));
+  EXPECT_EQ(window_to_web_contents()[window]->GetVisibleURL(),
+            GURL("https://b.example.org"));
+
+  browser->tab_strip_model()->CloseAllTabs();
+  EXPECT_EQ(0u, webcontents_to_observer_map().size());
+  EXPECT_EQ(0u, window_to_web_contents().size());
+}
+
+IN_PROC_BROWSER_TEST_F(WebsiteMetricsBrowserTest, MultipleBrowser) {
+  // Setup: two browsers with two tabs each.
+  auto* browser1 = CreateBrowser();
+  auto* window1 = browser1->window()->GetNativeWindow();
+  auto* tab_app1 = InsertForegroundTab(browser1, "https://a.example.org");
+  auto* tab_app2 = InsertForegroundTab(browser1, "https://b.example.org");
+
+  EXPECT_EQ(1u, window_to_web_contents().size());
+  EXPECT_EQ(1u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window1]));
+  EXPECT_EQ(window_to_web_contents()[window1]->GetVisibleURL(),
+            GURL("https://b.example.org"));
+
+  auto* browser2 = CreateBrowser();
+  auto* window2 = browser2->window()->GetNativeWindow();
+  auto* tab_app3 = InsertForegroundTab(browser2, "https://c.example.org");
+  auto* tab_app4 = InsertForegroundTab(browser2, "https://d.example.org");
+
+  EXPECT_EQ(2u, window_to_web_contents().size());
+  EXPECT_EQ(2u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window2]));
+  EXPECT_EQ(window_to_web_contents()[window2]->GetVisibleURL(),
+            GURL("https://d.example.org"));
+
+  // Close tabs.
+  int i = browser1->tab_strip_model()->GetIndexOfWebContents(tab_app1);
+  browser1->tab_strip_model()->CloseWebContentsAt(
+      i, TabStripModel::CLOSE_USER_GESTURE);
+  EXPECT_EQ(2u, window_to_web_contents().size());
+  EXPECT_EQ(2u, webcontents_to_observer_map().size());
+  EXPECT_EQ(window_to_web_contents()[window1]->GetVisibleURL(),
+            GURL("https://b.example.org"));
+
+  i = browser2->tab_strip_model()->GetIndexOfWebContents(tab_app3);
+  browser2->tab_strip_model()->CloseWebContentsAt(
+      i, TabStripModel::CLOSE_USER_GESTURE);
+  EXPECT_EQ(2u, window_to_web_contents().size());
+  EXPECT_EQ(2u, webcontents_to_observer_map().size());
+  EXPECT_EQ(window_to_web_contents()[window2]->GetVisibleURL(),
+            GURL("https://d.example.org"));
+
+  i = browser2->tab_strip_model()->GetIndexOfWebContents(tab_app4);
+  browser2->tab_strip_model()->CloseWebContentsAt(
+      i, TabStripModel::CLOSE_USER_GESTURE);
+  EXPECT_EQ(1u, window_to_web_contents().size());
+  EXPECT_EQ(1u, webcontents_to_observer_map().size());
+  EXPECT_TRUE(base::Contains(webcontents_to_observer_map(),
+                             window_to_web_contents()[window1]));
+
+  i = browser1->tab_strip_model()->GetIndexOfWebContents(tab_app2);
+  browser1->tab_strip_model()->CloseWebContentsAt(
+      i, TabStripModel::CLOSE_USER_GESTURE);
+
+  EXPECT_EQ(0u, window_to_web_contents().size());
+  EXPECT_EQ(0u, webcontents_to_observer_map().size());
+}
+
+}  // namespace apps
diff --git a/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
index 8a3a1fb..6975485 100644
--- a/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
+++ b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
@@ -54,8 +54,8 @@
     extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
     arc::ArcSessionManager::SetUiEnabledForTesting(false);
     // SessionManagerClient will be destroyed in ChromeBrowserMain.
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
-    chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
+    ash::SessionManagerClient::InitializeFakeInMemory();
+    ash::FakeSessionManagerClient::Get()->set_arc_available(true);
   }
 
   void SetUpOnMainThread() override {
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
index 4388e99..f69e303 100644
--- a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
@@ -344,7 +344,7 @@
     const std::string& extension_id,
     extensions::events::HistogramValue histogram_value,
     const std::string& event_name,
-    std::vector<base::Value> event_args) {
+    base::Value::List event_args) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   extensions::EventRouter* router = extensions::EventRouter::Get(profile_);
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h
index f3d194a86..f74e2b1 100644
--- a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h
@@ -66,7 +66,7 @@
       const std::string& extension_id,
       extensions::events::HistogramValue histogram_value,
       const std::string& event_name,
-      std::vector<base::Value> event_args);
+      base::Value::List event_args);
 
   explicit MediaGalleriesEventRouter(content::BrowserContext* context);
   ~MediaGalleriesEventRouter() override;
diff --git a/chrome/browser/apps/platform_apps/api/sync_file_system/extension_sync_event_observer.cc b/chrome/browser/apps/platform_apps/api/sync_file_system/extension_sync_event_observer.cc
index ca3b0df..2dc3a0c 100644
--- a/chrome/browser/apps/platform_apps/api/sync_file_system/extension_sync_event_observer.cc
+++ b/chrome/browser/apps/platform_apps/api/sync_file_system/extension_sync_event_observer.cc
@@ -92,13 +92,13 @@
     ::sync_file_system::SyncFileStatus status,
     ::sync_file_system::SyncAction action,
     ::sync_file_system::SyncDirection direction) {
-  std::vector<base::Value> params;
+  base::Value::List params;
 
   std::unique_ptr<base::DictionaryValue> entry =
       CreateDictionaryValueForFileSystemEntry(url, file_type);
   if (!entry)
     return;
-  params.push_back(base::Value::FromUniquePtrValue(std::move(entry)));
+  params.Append(base::Value::FromUniquePtrValue(std::move(entry)));
 
   // Status, SyncAction and any optional notes to go here.
   sync_file_system::FileStatus status_enum =
@@ -106,9 +106,9 @@
   sync_file_system::SyncAction action_enum = SyncActionToExtensionEnum(action);
   sync_file_system::SyncDirection direction_enum =
       SyncDirectionToExtensionEnum(direction);
-  params.push_back(base::Value(sync_file_system::ToString(status_enum)));
-  params.push_back(base::Value(sync_file_system::ToString(action_enum)));
-  params.push_back(base::Value(sync_file_system::ToString(direction_enum)));
+  params.Append(sync_file_system::ToString(status_enum));
+  params.Append(sync_file_system::ToString(action_enum));
+  params.Append(sync_file_system::ToString(direction_enum));
 
   BroadcastOrDispatchEvent(
       url.origin().GetURL(),
@@ -120,7 +120,7 @@
     const GURL& app_origin,
     extensions::events::HistogramValue histogram_value,
     const std::string& event_name,
-    std::vector<base::Value> values) {
+    base::Value::List values) {
   // Check to see whether the event should be broadcasted to all listening
   // extensions or sent to a specific extension ID.
   bool broadcast_mode = app_origin.is_empty();
diff --git a/chrome/browser/apps/platform_apps/api/sync_file_system/extension_sync_event_observer.h b/chrome/browser/apps/platform_apps/api/sync_file_system/extension_sync_event_observer.h
index c1a71445..a0e7a14 100644
--- a/chrome/browser/apps/platform_apps/api/sync_file_system/extension_sync_event_observer.h
+++ b/chrome/browser/apps/platform_apps/api/sync_file_system/extension_sync_event_observer.h
@@ -76,7 +76,7 @@
       const GURL& app_origin,
       extensions::events::HistogramValue histogram_value,
       const std::string& event_name,
-      std::vector<base::Value> value);
+      base::Value::List value);
 };
 
 }  // namespace api
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 7d5151c..014c9f7 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -471,6 +471,8 @@
     "arc/session/arc_app_id_provider_impl.h",
     "arc/session/arc_demo_mode_preference_handler.cc",
     "arc/session/arc_demo_mode_preference_handler.h",
+    "arc/session/arc_disk_space_monitor.cc",
+    "arc/session/arc_disk_space_monitor.h",
     "arc/session/arc_play_store_enabled_preference_handler.cc",
     "arc/session/arc_play_store_enabled_preference_handler.h",
     "arc/session/arc_provisioning_result.cc",
@@ -792,6 +794,8 @@
     "crostini/crostini_manager.h",
     "crostini/crostini_manager_factory.cc",
     "crostini/crostini_manager_factory.h",
+    "crostini/crostini_mount_provider.cc",
+    "crostini/crostini_mount_provider.h",
     "crostini/crostini_package_notification.cc",
     "crostini/crostini_package_notification.h",
     "crostini/crostini_package_operation_status.h",
@@ -976,6 +980,8 @@
     "file_manager/fileapi_util.h",
     "file_manager/filesystem_api_util.cc",
     "file_manager/filesystem_api_util.h",
+    "file_manager/fusebox_moniker.cc",
+    "file_manager/fusebox_moniker.h",
     "file_manager/fusebox_mounter.cc",
     "file_manager/fusebox_mounter.h",
     "file_manager/guest_os_file_tasks.cc",
@@ -1126,6 +1132,8 @@
     "guest_os/guest_os_diagnostics_builder.h",
     "guest_os/guest_os_external_protocol_handler.cc",
     "guest_os/guest_os_external_protocol_handler.h",
+    "guest_os/guest_os_file_watcher.cc",
+    "guest_os/guest_os_file_watcher.h",
     "guest_os/guest_os_launcher.cc",
     "guest_os/guest_os_launcher.h",
     "guest_os/guest_os_mime_types_service.cc",
@@ -2008,8 +2016,12 @@
     "//chromeos/ash/components/dbus/session_manager",
     "//chromeos/ash/components/dbus/system_clock",
     "//chromeos/ash/components/dbus/system_proxy:system_proxy_proto",
+    "//chromeos/ash/components/dbus/userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/ash/components/memory",
     "//chromeos/ash/components/network/portal_detector",
+    "//chromeos/ash/services/cros_healthd/public/cpp",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//chromeos/components/feature_usage",
     "//chromeos/components/onc",
     "//chromeos/components/sharesheet:constants",
@@ -2036,12 +2048,9 @@
     "//chromeos/dbus/tpm_manager",
     "//chromeos/dbus/tpm_manager:tpm_manager_proto",
     "//chromeos/dbus/update_engine",
-    "//chromeos/dbus/userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//chromeos/login/login_state",
     "//chromeos/metrics",
     "//chromeos/network",
-    "//chromeos/services/cros_healthd/public/mojom",
     "//chromeos/services/machine_learning/public/mojom",
     "//chromeos/services/network_config/public/mojom",
     "//chromeos/services/network_health/public/mojom",
@@ -2260,6 +2269,7 @@
     "//chromeos/ash/components/hibernate:buildflags",
     "//chromeos/ash/components/oobe_quick_start",
     "//chromeos/ash/services/assistant/public/cpp",
+    "//chromeos/ash/services/cros_healthd/private/cpp",
     "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_browser",
     "//chromeos/components/disks:prefs",
     "//chromeos/components/local_search_service/public/cpp",
@@ -2296,8 +2306,6 @@
     "//chromeos/dbus/vm_plugin_dispatcher",
     "//chromeos/ime:gencode",
     "//chromeos/services/bluetooth_config:in_process_bluetooth_config",
-    "//chromeos/services/cros_healthd/private/cpp",
-    "//chromeos/services/cros_healthd/public/cpp",
     "//chromeos/services/machine_learning/public/cpp",
     "//chromeos/services/network_config:in_process_instance",
     "//chromeos/services/network_config/public/cpp",
diff --git a/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc
index c119a6f..d28278d 100644
--- a/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc
+++ b/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc
@@ -26,7 +26,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "components/ownership/mock_owner_key_util.h"
 #include "content/public/test/browser_test.h"
 #include "net/dns/mock_host_resolver.h"
@@ -53,8 +53,8 @@
         *device_policy_.GetSigningKey());
 
     // SessionManagerClient will be destroyed in ChromeBrowserMain.
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
-    chromeos::FakeSessionManagerClient::Get()->set_device_policy(
+    SessionManagerClient::InitializeFakeInMemory();
+    FakeSessionManagerClient::Get()->set_device_policy(
         device_policy_.GetBlob());
   }
 
diff --git a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
index 36c8a43..6a5696d3 100644
--- a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
+++ b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/ash/app_mode/pref_names.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/app_mode/kiosk_profile_loader.cc b/chrome/browser/ash/app_mode/kiosk_profile_loader.cc
index 8cf307df..743f7a32 100644
--- a/chrome/browser/ash/app_mode/kiosk_profile_loader.cc
+++ b/chrome/browser/ash/app_mode/kiosk_profile_loader.cc
@@ -23,8 +23,8 @@
 #include "chrome/browser/ash/login/auth/chrome_login_performer.h"
 #include "chrome/browser/ash/login/ui/login_display_host.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/user_names.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc b/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc
index 79e7e703..259e711 100644
--- a/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc
+++ b/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc
@@ -186,10 +186,9 @@
 
     ASSERT_EQ(event.event_name,
               extensions::api::app_runtime::OnLaunched::kEventName);
-    ASSERT_TRUE(event.event_args);
-    ASSERT_EQ(1u, event.event_args->GetListDeprecated().size());
+    ASSERT_EQ(1u, event.event_args.size());
 
-    const base::Value& launch_data = event.event_args->GetListDeprecated()[0];
+    const base::Value& launch_data = event.event_args[0];
     const base::Value* is_kiosk_session =
         launch_data.FindKeyOfType("isKioskSession", base::Value::Type::BOOLEAN);
     ASSERT_TRUE(is_kiosk_session);
diff --git a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
index 85b52f9..ce3275e 100644
--- a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
@@ -34,8 +34,8 @@
 #include "chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "chrome/browser/ui/ash/shelf/shelf_spinner_controller.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/system/scheduler_configuration_manager_base.h"
 #include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/app_restore_utils.h"
diff --git a/chrome/browser/ash/app_restore/arc_app_launch_handler.h b/chrome/browser/ash/app_restore/arc_app_launch_handler.h
index fce5afb..b3705a4 100644
--- a/chrome/browser/ash/app_restore/arc_app_launch_handler.h
+++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.h
@@ -14,8 +14,8 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/scheduler_configuration_manager.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "chromeos/dbus/resourced/resourced_client.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
index 14c96a8..2b1161f 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
@@ -235,8 +235,7 @@
   ASSERT_EQ(1, helper_bridge->GetEventCount(event_name));
   ASSERT_EQ(event_name, helper_bridge->last_event->event_name);
   base::Value::ConstListView arg =
-      helper_bridge->last_event->event_args->GetListDeprecated()[0]
-          .GetListDeprecated();
+      helper_bridge->last_event->event_args[0].GetListDeprecated();
   ASSERT_EQ(1U, arg.size());
   ASSERT_EQ(announce_text, arg[0].GetString());
 }
@@ -266,8 +265,7 @@
   ASSERT_EQ(1, helper_bridge->GetEventCount(event_name));
   ASSERT_EQ(event_name, helper_bridge->last_event->event_name);
   base::Value::ConstListView arg =
-      helper_bridge->last_event->event_args->GetListDeprecated()[0]
-          .GetListDeprecated();
+      helper_bridge->last_event->event_args[0].GetListDeprecated();
   ASSERT_EQ(1U, arg.size());
   ASSERT_EQ(toast_text, arg[0].GetString());
 
diff --git a/chrome/browser/ash/arc/auth/arc_active_directory_enrollment_token_fetcher_browsertest.cc b/chrome/browser/ash/arc/auth/arc_active_directory_enrollment_token_fetcher_browsertest.cc
index ca4c6810..04d83fe 100644
--- a/chrome/browser/ash/arc/auth/arc_active_directory_enrollment_token_fetcher_browsertest.cc
+++ b/chrome/browser/ash/arc/auth/arc_active_directory_enrollment_token_fetcher_browsertest.cc
@@ -20,8 +20,8 @@
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
 #include "components/policy/core/common/policy_switches.h"
 #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc b/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc
index 7d21214..0c36863 100644
--- a/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc
+++ b/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc
@@ -116,7 +116,7 @@
   VLOG(2) << "OnBootCompleted";
   boot_completed_ = true;
 
-  chromeos::SessionManagerClient::Get()->EmitArcBooted(
+  ash::SessionManagerClient::Get()->EmitArcBooted(
       cryptohome::CreateAccountIdentifierFromAccountId(account_id_),
       base::BindOnce(&OnEmitArcBooted));
 
diff --git a/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc b/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc
index dc2d700b..1f91de2 100644
--- a/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc
@@ -39,7 +39,7 @@
     // constructor calls DBusThreadManager::Get().
     chromeos::DBusThreadManager::Initialize();
     ash::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
 
     arc_service_manager_ = std::make_unique<ArcServiceManager>();
     arc_session_manager_ =
@@ -71,7 +71,7 @@
     testing_profile_.reset();
     arc_session_manager_.reset();
     arc_service_manager_.reset();
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
     ash::ConciergeClient::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
   }
diff --git a/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate_unittest.cc b/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate_unittest.cc
index 696c18e5..1e6d79a 100644
--- a/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate_unittest.cc
+++ b/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate_unittest.cc
@@ -70,7 +70,7 @@
 
     chromeos::DBusThreadManager::Initialize();
     ash::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
 
     TestingProfile::Builder profile_builder;
     profile_builder.SetProfileName("user@gmail.com");
@@ -87,7 +87,7 @@
       delete;
 
   ~ArcDataSnapshotdDelegateTest() override {
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
     ash::ConciergeClient::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
   }
diff --git a/chrome/browser/ash/arc/input_overlay/actions/action_move.cc b/chrome/browser/ash/arc/input_overlay/actions/action_move.cc
index 9bfdc1f..f5719ad 100644
--- a/chrome/browser/ash/arc/input_overlay/actions/action_move.cc
+++ b/chrome/browser/ash/arc/input_overlay/actions/action_move.cc
@@ -163,9 +163,6 @@
     if (it == labels_.end())
       return;
 
-    if (ShouldShowErrorMsg(code, action_label))
-      return;
-
     const auto& binding = action_->GetCurrentDisplayedBinding();
     DCHECK(binding.keys().size() == kActionMoveKeysSize);
     std::vector<ui::DomCode> new_keys = binding.keys();
diff --git a/chrome/browser/ash/arc/input_overlay/actions/action_tap.cc b/chrome/browser/ash/arc/input_overlay/actions/action_tap.cc
index b534c82..e6449cbc 100644
--- a/chrome/browser/ash/arc/input_overlay/actions/action_tap.cc
+++ b/chrome/browser/ash/arc/input_overlay/actions/action_tap.cc
@@ -99,8 +99,6 @@
 
   void OnKeyBindingChange(ActionLabel* action_label,
                           ui::DomCode code) override {
-    if (ShouldShowErrorMsg(code, action_label))
-      return;
     DCHECK(labels_.size() == 1 && labels_[0] == action_label);
     if (labels_.size() != 1 || labels_[0] != action_label)
       return;
diff --git a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc
index 0fea50b..953260e 100644
--- a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc
+++ b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc
@@ -60,9 +60,13 @@
   AddOverlay(first_launch ? DisplayMode::kEducation : DisplayMode::kView);
   touch_injector_->set_display_overlay_controller(this);
   ash::Shell::Get()->AddPreTargetHandler(this);
+  if (ash::ColorProvider::Get())
+    ash::ColorProvider::Get()->AddObserver(this);
 }
 
 DisplayOverlayController::~DisplayOverlayController() {
+  if (ash::ColorProvider::Get())
+    ash::ColorProvider::Get()->RemoveObserver(this);
   ash::Shell::Get()->RemovePreTargetHandler(this);
   touch_injector_->set_display_overlay_controller(nullptr);
   RemoveOverlayIfAny();
@@ -348,6 +352,7 @@
     case DisplayMode::kNone:
       RemoveMenuEntryView();
       RemoveInputMappingView();
+      RemoveEducationalView();
       RemoveEditFinishView();
       RemoveNudgeView();
       break;
@@ -497,6 +502,19 @@
     ProcessPressedEvent(*event);
 }
 
+void DisplayOverlayController::OnColorModeChanged(bool dark_mode_enabled) {
+  // Only make the color mode change responsive when in
+  // |DisplayMode::kEducation| because:
+  // 1. Other modes like |DisplayMode::kEdit| and |DisplayMode::kView| only have
+  // one color mode.
+  // 2. When in |DisplayMode::kMenu| and changing the color mode, the menu is
+  // closed and it becomes |DisplayMode::kView| so no need to update color mode.
+  if (display_mode_ != DisplayMode::kEducation)
+    return;
+  SetDisplayMode(DisplayMode::kNone);
+  SetDisplayMode(DisplayMode::kEducation);
+}
+
 bool DisplayOverlayController::HasMenuView() const {
   return input_menu_view_ != nullptr;
 }
@@ -538,6 +556,12 @@
     return;
 
   auto root_location = event.root_location();
+  // Convert the LocatedEvent root location to screen location.
+  auto origin = touch_injector_->target_window()
+                    ->GetRootWindow()
+                    ->GetBoundsInScreen()
+                    .origin();
+  root_location.Offset(origin.x(), origin.y());
 
   if (action_edit_menu_) {
     auto bounds = action_edit_menu_->GetBoundsInScreen();
diff --git a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h
index a0206dca..b931cc8 100644
--- a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h
+++ b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_ASH_ARC_INPUT_OVERLAY_DISPLAY_OVERLAY_CONTROLLER_H_
 #define CHROME_BROWSER_ASH_ARC_INPUT_OVERLAY_DISPLAY_OVERLAY_CONTROLLER_H_
 
+#include "ash/public/cpp/style/color_mode_observer.h"
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/ash/arc/input_overlay/actions/action.h"
 #include "chrome/browser/ash/arc/input_overlay/touch_injector.h"
@@ -40,7 +41,8 @@
 // DisplayOverlayController manages the input mapping view, view and edit mode,
 // menu, and educational dialog. It also handles the visibility of the
 // |ActionEditMenu| and |MessageView| by listening to the |LocatedEvent|.
-class DisplayOverlayController : public ui::EventHandler {
+class DisplayOverlayController : public ui::EventHandler,
+                                 public ash::ColorModeObserver {
  public:
   DisplayOverlayController(TouchInjector* touch_injector, bool first_launch);
   DisplayOverlayController(const DisplayOverlayController&) = delete;
@@ -49,7 +51,7 @@
 
   void OnWindowBoundsChanged();
   void SetDisplayMode(DisplayMode mode);
-  // Get the bounds of |menu_entry_| in screen coordinates
+  // Get the bounds of |menu_entry_| in screen coordinates.
   absl::optional<gfx::Rect> GetOverlayMenuEntryBounds();
 
   void AddActionEditMenu(ActionView* anchor, ActionType action_type);
@@ -79,6 +81,9 @@
   void OnMouseEvent(ui::MouseEvent* event) override;
   void OnTouchEvent(ui::TouchEvent* event) override;
 
+  // ash::ColorModeObserver:
+  void OnColorModeChanged(bool dark_mode_enabled) override;
+
  private:
   friend class ::arc::ArcInputOverlayManagerTest;
   friend class DisplayOverlayControllerTest;
diff --git a/chrome/browser/ash/arc/input_overlay/touch_injector.cc b/chrome/browser/ash/arc/input_overlay/touch_injector.cc
index a6f3af80..0276d832 100644
--- a/chrome/browser/ash/arc/input_overlay/touch_injector.cc
+++ b/chrome/browser/ash/arc/input_overlay/touch_injector.cc
@@ -394,6 +394,9 @@
 
   auto event_location = gfx::Point(event.AsLocatedEvent()->root_location());
   target_window_->GetHost()->ConvertPixelsToDIP(&event_location);
+  // Convert |event_location| from root window location to screen location.
+  auto origin = target_window_->GetRootWindow()->GetBoundsInScreen().origin();
+  event_location.Offset(origin.x(), origin.y());
 
   if (!press_required)
     return menu_anchor_bounds->Contains(event_location);
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
index daa4a1a..f97ec857 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
@@ -241,8 +241,12 @@
   DCHECK(parent());
   auto code = event.code();
   auto* parent_view = static_cast<ActionView*>(parent());
-  if (base::UTF8ToUTF16(GetDisplayText(code)) != GetText())
-    parent_view->OnKeyBindingChange(this, code);
+  if (base::UTF8ToUTF16(GetDisplayText(code)) == GetText() ||
+      parent_view->ShouldShowErrorMsg(code)) {
+    return true;
+  }
+
+  parent_view->OnKeyBindingChange(this, code);
   return true;
 }
 
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_view.cc b/chrome/browser/ash/arc/input_overlay/ui/action_view.cc
index 8a760e1..3716c94 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/action_view.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/action_view.cc
@@ -132,6 +132,19 @@
                                                std::move(input_element));
 }
 
+bool ActionView::ShouldShowErrorMsg(ui::DomCode code,
+                                    ActionLabel* editing_label) {
+  if ((!action_->support_modifier_key() &&
+       ModifierDomCodeToEventFlag(code) != ui::EF_NONE) ||
+      IsReservedDomCode(code)) {
+    ShowErrorMsg(l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_RESERVED_KEYS),
+                 editing_label);
+    return true;
+  }
+
+  return false;
+}
+
 void ActionView::AddEditButton() {
   if (!show_edit_button_ || !editable_ || menu_entry_)
     return;
@@ -154,18 +167,5 @@
   menu_entry_ = nullptr;
 }
 
-bool ActionView::ShouldShowErrorMsg(ui::DomCode code,
-                                    ActionLabel* editing_label) {
-  if ((!action_->support_modifier_key() &&
-       ModifierDomCodeToEventFlag(code) != ui::EF_NONE) ||
-      IsReservedDomCode(code)) {
-    ShowErrorMsg(l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_RESERVED_KEYS),
-                 editing_label);
-    return true;
-  }
-
-  return false;
-}
-
 }  // namespace input_overlay
 }  // namespace arc
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_view.h b/chrome/browser/ash/arc/input_overlay/ui/action_view.h
index 05815940..70b4a91 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/action_view.h
+++ b/chrome/browser/ash/arc/input_overlay/ui/action_view.h
@@ -74,7 +74,10 @@
                      std::unique_ptr<InputElement> input_element);
   // Reset binding to its previous binding before entering to the edit mode.
   void OnResetBinding();
-
+  // Return true if it needs to show error message and also shows error message.
+  // Otherwise, don't show any error message and return false.
+  bool ShouldShowErrorMsg(ui::DomCode code,
+                          ActionLabel* editing_label = nullptr);
   Action* action() { return action_; }
   const std::vector<ActionLabel*>& labels() const { return labels_; }
   void set_editable(bool editable) { editable_ = editable; }
@@ -88,9 +91,6 @@
   bool show_circle() const { return show_circle_; }
 
  protected:
-  bool ShouldShowErrorMsg(ui::DomCode code,
-                          ActionLabel* editing_label = nullptr);
-
   // Reference to the action of this UI.
   raw_ptr<Action> action_ = nullptr;
   // Reference to the owner class.
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc
index eae6358..2bc9ba91 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc
@@ -176,7 +176,7 @@
 }
 
 void SetArcContainerCpuRestriction(CpuRestrictionState cpu_restriction_state) {
-  if (!chromeos::SessionManagerClient::Get()) {
+  if (!ash::SessionManagerClient::Get()) {
     LOG(WARNING) << "SessionManagerClient is not available";
     return;
   }
@@ -190,7 +190,7 @@
       state = login_manager::CONTAINER_CPU_RESTRICTION_BACKGROUND;
       break;
   }
-  chromeos::SessionManagerClient::Get()->SetArcCpuRestriction(
+  ash::SessionManagerClient::Get()->SetArcCpuRestriction(
       state, base::BindOnce(SetArcCpuRestrictionCallback, state));
 }
 
diff --git a/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc b/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc
index d049d1e..c2d40fe 100644
--- a/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc
+++ b/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc
@@ -30,8 +30,8 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "components/arc/test/fake_intent_helper_host.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
diff --git a/chrome/browser/ash/arc/session/arc_disk_space_monitor.cc b/chrome/browser/ash/arc/session/arc_disk_space_monitor.cc
new file mode 100644
index 0000000..6576a6e
--- /dev/null
+++ b/chrome/browser/ash/arc/session/arc_disk_space_monitor.cc
@@ -0,0 +1,86 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/arc/session/arc_disk_space_monitor.h"
+
+#include "base/logging.h"
+#include "chrome/browser/ash/arc/arc_util.h"
+#include "chrome/browser/ash/arc/session/arc_session_manager.h"
+#include "chromeos/ash/components/dbus/spaced/spaced_client.h"
+
+namespace arc {
+
+ArcDiskSpaceMonitor::ArcDiskSpaceMonitor() {
+  ArcSessionManager::Get()->AddObserver(this);
+}
+
+ArcDiskSpaceMonitor::~ArcDiskSpaceMonitor() {
+  ArcSessionManager::Get()->RemoveObserver(this);
+}
+
+void ArcDiskSpaceMonitor::OnArcStarted() {
+  VLOG(1) << "ARC started. Activating ArcDiskSpaceMonitor.";
+
+  // Calling ScheduleCheckDiskSpace(Seconds(0)) instead of CheckDiskSpace()
+  // because ArcSessionManager::RequestStopOnLowDiskSpace() doesn't work if it
+  // is called directly inside OnArcStarted().
+  ScheduleCheckDiskSpace(base::Seconds(0));
+}
+
+void ArcDiskSpaceMonitor::OnArcSessionStopped(ArcStopReason stop_reason) {
+  VLOG(1) << "ARC stopped. Deactivating ArcDiskSpaceMonitor.";
+  timer_.Stop();
+}
+
+void ArcDiskSpaceMonitor::ScheduleCheckDiskSpace(base::TimeDelta delay) {
+  timer_.Start(FROM_HERE, delay,
+               base::BindOnce(&ArcDiskSpaceMonitor::CheckDiskSpace,
+                              weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ArcDiskSpaceMonitor::CheckDiskSpace() {
+  ash::SpacedClient::Get()->GetFreeDiskSpace(
+      "/home", base::BindOnce(&ArcDiskSpaceMonitor::OnGetFreeDiskSpace,
+                              weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ArcDiskSpaceMonitor::OnGetFreeDiskSpace(absl::optional<int64_t> reply) {
+  if (!reply.has_value() || reply.value() < 0) {
+    LOG(ERROR) << "spaced::GetFreeDiskSpace failed. "
+               << "Deactivating ArcDiskSpaceMonitor.";
+    return;
+  }
+  const int64_t free_disk_space = reply.value();
+
+  arc::ArcSessionManager* const arc_session_manager =
+      arc::ArcSessionManager::Get();
+  const ArcSessionManager::State state = arc_session_manager->state();
+
+  VLOG(1) << "ArcSessionManager::State:" << state
+          << ", free_disk_space:" << free_disk_space;
+
+  if (state != ArcSessionManager::State::ACTIVE) {
+    LOG(WARNING) << "ARC is not active.";
+    // No need to call ScheduleCheckDiskSpace() because
+    // OnArcStarted() will trigger CheckDiskSpace() when ARC starts.
+    return;
+  }
+
+  if (free_disk_space < kDiskSpaceThresholdForStoppingArc) {
+    LOG(WARNING) << "Stopping ARC due to low disk space. free_disk_space:"
+                 << free_disk_space;
+    arc_session_manager->RequestStopOnLowDiskSpace();
+    // TODO(b/233030867): Show a final warning notification.
+    return;
+  } else if (free_disk_space < kDiskSpaceThresholdForPreWarning) {
+    // TODO(b/233030867): Show a pre-warning notification.
+  }
+
+  if (free_disk_space < kDiskSpaceThresholdForPreWarning)
+    ScheduleCheckDiskSpace(kDiskSpaceCheckIntervalShort);
+  else
+    ScheduleCheckDiskSpace(kDiskSpaceCheckIntervalLong);
+}
+
+}  // namespace arc
diff --git a/chrome/browser/ash/arc/session/arc_disk_space_monitor.h b/chrome/browser/ash/arc/session/arc_disk_space_monitor.h
new file mode 100644
index 0000000..32968ce0
--- /dev/null
+++ b/chrome/browser/ash/arc/session/arc_disk_space_monitor.h
@@ -0,0 +1,76 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_ARC_SESSION_ARC_DISK_SPACE_MONITOR_H_
+#define CHROME_BROWSER_ASH_ARC_SESSION_ARC_DISK_SPACE_MONITOR_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/ash/arc/session/arc_session_manager_observer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace arc {
+
+// These thresholds are chosen based on UMA stats. (go/arcvm-virtio-blk-sparse)
+// Show a pre-warning notification if free disk space is lower than this.
+constexpr int64_t kDiskSpaceThresholdForPreWarning = 1LL << 30;  // 1GB
+
+// Stop ARC and show a final warning notification if free disk space is
+// lower than this.
+constexpr int64_t kDiskSpaceThresholdForStoppingArc = 256LL << 20;  // 256MB
+
+// TODO(b/233030867): Choose these values based on some logic
+//                    instead of deciding them on a hunch.
+// Disk space check interval used when free disk space is lower than
+// kDiskSpaceThresholdForPreWarning.
+constexpr base::TimeDelta kDiskSpaceCheckIntervalShort = base::Seconds(1);
+
+// Disk space check interval used when free disk space is higher than
+// kDiskSpaceThresholdForPreWarning.
+constexpr base::TimeDelta kDiskSpaceCheckIntervalLong = base::Seconds(10);
+
+// Monitors disk usage. Requests stopping ARC and/or shows a warning
+// notification when device's free disk space becomes lower than a threshold.
+// Used when arcvm_virtio_blk_data is enabled. (go/arcvm-virtio-blk-sparse)
+// TODO(b/233030867): Delete this after we switch ARCVM to using Storage
+//                    Balloons for disk space management.
+class ArcDiskSpaceMonitor : public ArcSessionManagerObserver {
+ public:
+  ArcDiskSpaceMonitor();
+  ~ArcDiskSpaceMonitor() override;
+
+  ArcDiskSpaceMonitor(const ArcDiskSpaceMonitor&) = delete;
+  ArcDiskSpaceMonitor& operator=(const ArcDiskSpaceMonitor&) = delete;
+
+  bool IsTimerRunningForTesting() { return timer_.IsRunning(); }
+  base::TimeDelta GetTimerCurrentDelayForTesting() {
+    return timer_.GetCurrentDelay();
+  }
+
+  // ArcSessionManagerObserver overrides.
+  void OnArcStarted() override;
+  void OnArcSessionStopped(ArcStopReason stop_reason) override;
+
+ private:
+  // Schedules calling CheckDiskSpace().
+  void ScheduleCheckDiskSpace(base::TimeDelta delay);
+
+  // Checks disk usage, requests stopping ARC and/or shows a warning
+  // notification based on the free disk space.
+  void CheckDiskSpace();
+
+  // Used as a callback function.
+  void OnGetFreeDiskSpace(absl::optional<int64_t> reply);
+
+  // Used for periodically calling CheckDiskSpace().
+  base::OneShotTimer timer_;
+
+  // WeakPtrFactory to use callbacks.
+  base::WeakPtrFactory<ArcDiskSpaceMonitor> weak_ptr_factory_{this};
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_ASH_ARC_SESSION_ARC_DISK_SPACE_MONITOR_H_
diff --git a/chrome/browser/ash/arc/session/arc_disk_space_monitor_unittest.cc b/chrome/browser/ash/arc/session/arc_disk_space_monitor_unittest.cc
new file mode 100644
index 0000000..659db128
--- /dev/null
+++ b/chrome/browser/ash/arc/session/arc_disk_space_monitor_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/arc/session/arc_disk_space_monitor.h"
+
+#include "ash/components/arc/test/arc_util_test_support.h"
+#include "ash/components/arc/test/fake_arc_session.h"
+#include "base/logging.h"
+#include "chrome/browser/ash/arc/session/arc_session_manager.h"
+#include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
+#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/spaced/fake_spaced_client.h"
+#include "chromeos/ash/components/dbus/spaced/spaced_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "components/user_manager/user_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcDiskSpaceMonitorTest : public testing::Test {
+ public:
+  ArcDiskSpaceMonitorTest() = default;
+  ~ArcDiskSpaceMonitorTest() override = default;
+
+  ArcDiskSpaceMonitorTest(const ArcDiskSpaceMonitorTest&) = delete;
+  ArcDiskSpaceMonitorTest& operator=(const ArcDiskSpaceMonitorTest&) = delete;
+
+  void SetUp() override {
+    // Need to initialize DBusThreadManager before ArcSessionManager's
+    // constructor calls DBusThreadManager::Get().
+    chromeos::DBusThreadManager::Initialize();
+
+    // Initialize fake clients.
+    ash::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
+    ash::SpacedClient::InitializeFake();
+
+    // Set --arc-availability=officially-supported.
+    SetArcAvailableCommandLineForTesting(
+        base::CommandLine::ForCurrentProcess());
+
+    // Make the session manager skip creating UI.
+    ArcSessionManager::SetUiEnabledForTesting(/*enabled=*/false);
+
+    // Initialize a testing profile and a fake user manager.
+    // (Required for testing ARC.)
+    testing_profile_ = std::make_unique<TestingProfile>();
+    const AccountId account_id(AccountId::FromUserEmailGaiaId(
+        testing_profile_->GetProfileUserName(), ""));
+    auto* user_manager = static_cast<ash::FakeChromeUserManager*>(
+        user_manager::UserManager::Get());
+    user_manager->AddUser(account_id);
+    user_manager->LoginUser(account_id);
+
+    // Initialize a session manager with a fake ARC session.
+    arc_session_manager_ =
+        CreateTestArcSessionManager(std::make_unique<ArcSessionRunner>(
+            base::BindRepeating(FakeArcSession::Create)));
+    arc_session_manager_->SetProfile(testing_profile_.get());
+    arc_session_manager_->Initialize();
+    arc_session_manager_->RequestEnable();
+
+    // Invoke OnTermsOfServiceNegotiated as if negotiation is done for testing.
+    // Now we are ready to call arc_session_manager_->StartArcForTesting().
+    arc_session_manager_->OnTermsOfServiceNegotiatedForTesting(true);
+
+    // ArcDiskSpaceMonitor should be initialized after the session manager is
+    // created.
+    arc_disk_space_monitor_ = std::make_unique<ArcDiskSpaceMonitor>();
+  }
+
+  void TearDown() override {
+    arc_disk_space_monitor_.reset();
+    arc_session_manager_.reset();
+    testing_profile_.reset();
+    ash::SpacedClient::Shutdown();
+    ash::ConciergeClient::Shutdown();
+    chromeos::DBusThreadManager::Shutdown();
+  }
+
+  ArcSessionManager* arc_session_manager() const {
+    return arc_session_manager_.get();
+  }
+
+  ArcDiskSpaceMonitor* arc_disk_space_monitor() const {
+    return arc_disk_space_monitor_.get();
+  }
+
+ private:
+  content::BrowserTaskEnvironment task_environment_{
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+  std::unique_ptr<TestingProfile> testing_profile_;
+  std::unique_ptr<ArcSessionManager> arc_session_manager_;
+  std::unique_ptr<ArcDiskSpaceMonitor> arc_disk_space_monitor_;
+};
+
+TEST_F(ArcDiskSpaceMonitorTest, GetFreeDiskSpaceFailed) {
+  // spaced::GetFreeDiskSpace fails.
+  ash::FakeSpacedClient::Get()->set_free_disk_space(absl::nullopt);
+
+  arc_session_manager()->StartArcForTesting();
+  EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
+
+  // Wait until ArcDiskSpaceMonitor::CheckDiskSpace() runs.
+  base::RunLoop().RunUntilIdle();
+
+  // ARC should keep running but the timer should be stopped.
+  EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
+  EXPECT_FALSE(arc_disk_space_monitor()->IsTimerRunningForTesting());
+}
+
+TEST_F(ArcDiskSpaceMonitorTest, FreeSpaceIsHigherThanThresholdForPreWarning) {
+  // ThresholdForStoppingArc < ThresholdForPreWarning < free_disk_space
+  ash::FakeSpacedClient::Get()->set_free_disk_space(
+      absl::make_optional(kDiskSpaceThresholdForPreWarning + 1));
+
+  arc_session_manager()->StartArcForTesting();
+  EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
+
+  // Wait until ArcDiskSpaceMonitor::CheckDiskSpace() runs.
+  base::RunLoop().RunUntilIdle();
+
+  // ARC should still be active.
+  EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
+
+  // The timer should be running with the long check interval.
+  EXPECT_TRUE(arc_disk_space_monitor()->IsTimerRunningForTesting());
+  EXPECT_EQ(kDiskSpaceCheckIntervalLong,
+            arc_disk_space_monitor()->GetTimerCurrentDelayForTesting());
+}
+
+TEST_F(ArcDiskSpaceMonitorTest, FreeSpaceIsLowerThanThresholdForPreWarning) {
+  // ThresholdForStoppingArc < free_disk_space < ThresholdForPreWarning
+  ash::FakeSpacedClient::Get()->set_free_disk_space(
+      absl::make_optional(kDiskSpaceThresholdForPreWarning - 1));
+
+  arc_session_manager()->StartArcForTesting();
+  EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
+
+  // Wait until ArcDiskSpaceMonitor::CheckDiskSpace() runs.
+  base::RunLoop().RunUntilIdle();
+
+  // ARC should still be active.
+  EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
+  EXPECT_TRUE(arc_disk_space_monitor()->IsTimerRunningForTesting());
+
+  // The timer should be running with the short check interval.
+  EXPECT_EQ(kDiskSpaceCheckIntervalShort,
+            arc_disk_space_monitor()->GetTimerCurrentDelayForTesting());
+}
+
+TEST_F(ArcDiskSpaceMonitorTest, FreeSpaceIsLowerThanThresholdForStoppingArc) {
+  // free_disk_space < ThresholdForStoppingArc < ThresholdForPreWarning
+  ash::FakeSpacedClient::Get()->set_free_disk_space(
+      absl::make_optional(kDiskSpaceThresholdForStoppingArc - 1));
+
+  arc_session_manager()->StartArcForTesting();
+  EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
+
+  // Wait until ArcDiskSpaceMonitor::CheckDiskSpace() runs.
+  base::RunLoop().RunUntilIdle();
+
+  // Both ARC and the timer should be stopped.
+  EXPECT_EQ(ArcSessionManager::State::STOPPED, arc_session_manager()->state());
+  EXPECT_FALSE(arc_disk_space_monitor()->IsTimerRunningForTesting());
+}
+
+}  // namespace
+}  // namespace arc
diff --git a/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc b/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc
index 66204a4..89bd3d47 100644
--- a/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc
+++ b/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc
@@ -68,7 +68,7 @@
     // constructor calls DBusThreadManager::Get().
     chromeos::DBusThreadManager::Initialize();
     ash::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
     ash::UpstartClient::InitializeFake();
 
     SetArcAvailableCommandLineForTesting(
@@ -113,7 +113,7 @@
     profile_.reset();
     TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
     ash::UpstartClient::Shutdown();
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
     ash::ConciergeClient::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
   }
@@ -322,7 +322,7 @@
 TEST_F(ArcPlayStoreEnabledPreferenceHandlerTest, MiniStateUnmanaged) {
   // Ensure the mini-instance starts.
   SetArcAvailableCommandLineForTesting(base::CommandLine::ForCurrentProcess());
-  chromeos::SessionManagerClient::Get()->EmitLoginPromptVisible();
+  ash::SessionManagerClient::Get()->EmitLoginPromptVisible();
   ASSERT_TRUE(arc_session_manager()
                   ->GetArcSessionRunnerForTesting()
                   ->GetArcSessionForTesting());
@@ -347,7 +347,7 @@
 TEST_F(ArcPlayStoreEnabledPreferenceHandlerTest, MiniStateManagedDisabled) {
   // Ensure the mini-instance starts.
   SetArcAvailableCommandLineForTesting(base::CommandLine::ForCurrentProcess());
-  chromeos::SessionManagerClient::Get()->EmitLoginPromptVisible();
+  ash::SessionManagerClient::Get()->EmitLoginPromptVisible();
   ASSERT_TRUE(arc_session_manager()
                   ->GetArcSessionRunnerForTesting()
                   ->GetArcSessionForTesting());
@@ -375,7 +375,7 @@
 TEST_F(ArcPlayStoreEnabledPreferenceHandlerTest, MiniStateManagedEnabled) {
   // Ensure the mini-instance starts.
   SetArcAvailableCommandLineForTesting(base::CommandLine::ForCurrentProcess());
-  chromeos::SessionManagerClient::Get()->EmitLoginPromptVisible();
+  ash::SessionManagerClient::Get()->EmitLoginPromptVisible();
   ASSERT_TRUE(arc_session_manager()
                   ->GetArcSessionRunnerForTesting()
                   ->GetArcSessionForTesting());
diff --git a/chrome/browser/ash/arc/session/arc_service_launcher.cc b/chrome/browser/ash/arc/session/arc_service_launcher.cc
index e050cc12..4b9668a2 100644
--- a/chrome/browser/ash/arc/session/arc_service_launcher.cc
+++ b/chrome/browser/ash/arc/session/arc_service_launcher.cc
@@ -80,6 +80,7 @@
 #include "chrome/browser/ash/arc/process/arc_process_service.h"
 #include "chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.h"
 #include "chrome/browser/ash/arc/session/arc_demo_mode_preference_handler.h"
+#include "chrome/browser/ash/arc/session/arc_disk_space_monitor.h"
 #include "chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.h"
@@ -151,6 +152,9 @@
     arc_demo_mode_preference_handler_ =
         ArcDemoModePreferenceHandler::Create(arc_session_manager_.get());
   }
+
+  if (base::FeatureList::IsEnabled(kEnableVirtioBlkForData))
+    arc_disk_space_monitor_ = std::make_unique<ArcDiskSpaceMonitor>();
 }
 
 ArcServiceLauncher::~ArcServiceLauncher() {
diff --git a/chrome/browser/ash/arc/session/arc_service_launcher.h b/chrome/browser/ash/arc/session/arc_service_launcher.h
index eecbb5ba..b804c768 100644
--- a/chrome/browser/ash/arc/session/arc_service_launcher.h
+++ b/chrome/browser/ash/arc/session/arc_service_launcher.h
@@ -25,6 +25,7 @@
 namespace arc {
 
 class ArcDemoModePreferenceHandler;
+class ArcDiskSpaceMonitor;
 class ArcIconCacheDelegateProvider;
 class ArcPlayStoreEnabledPreferenceHandler;
 class ArcServiceManager;
@@ -93,6 +94,7 @@
       arc_play_store_enabled_preference_handler_;
   std::unique_ptr<ArcDemoModePreferenceHandler>
       arc_demo_mode_preference_handler_;
+  std::unique_ptr<ArcDiskSpaceMonitor> arc_disk_space_monitor_;
   std::unique_ptr<ArcIconCacheDelegateProvider>
       arc_icon_cache_delegate_provider_;
   // |scheduler_configuration_manager_| outlives |this|.
diff --git a/chrome/browser/ash/arc/session/arc_session_manager.cc b/chrome/browser/ash/arc/session/arc_session_manager.cc
index efd3ac9..2d2dc30 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager.cc
+++ b/chrome/browser/ash/arc/session/arc_session_manager.cc
@@ -566,8 +566,8 @@
   arc_session_runner_->AddObserver(this);
   arc_session_runner_->SetDemoModeDelegate(
       std::make_unique<ArcDemoModeDelegateImpl>());
-  if (chromeos::SessionManagerClient::Get())
-    chromeos::SessionManagerClient::Get()->AddObserver(this);
+  if (ash::SessionManagerClient::Get())
+    ash::SessionManagerClient::Get()->AddObserver(this);
   ResetStabilityMetrics();
   ash::ConciergeClient::Get()->AddVmObserver(this);
   arc_dlc_installer_ = std::make_unique<ArcDlcInstaller>();
@@ -579,8 +579,8 @@
 
   ash::ConciergeClient::Get()->RemoveVmObserver(this);
 
-  if (chromeos::SessionManagerClient::Get())
-    chromeos::SessionManagerClient::Get()->RemoveObserver(this);
+  if (ash::SessionManagerClient::Get())
+    ash::SessionManagerClient::Get()->RemoveObserver(this);
 
   Shutdown();
   arc_session_runner_->RemoveObserver(this);
@@ -1576,6 +1576,10 @@
   arc_session_runner_->RequestUpgrade(std::move(params));
 }
 
+void ArcSessionManager::RequestStopOnLowDiskSpace() {
+  arc_session_runner_->RequestStop();
+}
+
 void ArcSessionManager::StopArc() {
   // TODO(hidehiko): This STOPPED guard should be unnecessary. Remove it later.
   // |reenable_arc_| may be set in |StopAndEnableArc| in case enterprise
diff --git a/chrome/browser/ash/arc/session/arc_session_manager.h b/chrome/browser/ash/arc/session/arc_session_manager.h
index 4cc815a..644716a 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager.h
+++ b/chrome/browser/ash/arc/session/arc_session_manager.h
@@ -56,7 +56,7 @@
 // This class is responsible for handing stages of ARC life-cycle.
 class ArcSessionManager : public ArcSessionRunner::Observer,
                           public ArcSupportHost::ErrorDelegate,
-                          public chromeos::SessionManagerClient::Observer,
+                          public ash::SessionManagerClient::Observer,
                           public ash::ConciergeClient::VmObserver,
                           public policy::PolicyService::Observer {
  public:
@@ -216,6 +216,16 @@
   // this.
   void RequestArcDataRemoval();
 
+  // Stops ARC instance without removing user ARC data.
+  // Unlike RequestDisable(), this doesn't clear user ARC prefs, and ARC is not
+  // supposed to restart within the same user session.
+  // NOTE: This method should be used only for the purpose of stopping ARC
+  //       under low disk space.
+  // TODO(b/236325019): Remove this once ArcSessionManager officially supports
+  //       a method to stop ARC without clearing user ARC prefs, or when we
+  //       remove ArcDiskSpaceMonitor after Storage Balloon is ready.
+  void RequestStopOnLowDiskSpace();
+
   // ArcSupportHost:::ErrorDelegate:
   void OnWindowClosed() override;
   void OnRetryClicked() override;
@@ -421,7 +431,7 @@
                                bool should_show_send_feedback,
                                bool should_show_run_network_tests);
 
-  // chromeos::SessionManagerClient::Observer:
+  // ash::SessionManagerClient::Observer:
   void EmitLoginPromptVisibleCalled() override;
 
   // Called when the first part of ExpandPropertyFilesAndReadSalt is done.
diff --git a/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc b/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
index 18d0f9d..c0507719 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
+++ b/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
@@ -57,9 +57,9 @@
 #include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
 #include "chromeos/ash/components/dbus/upstart/upstart_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/prefs/pref_service.h"
@@ -163,7 +163,7 @@
     // constructor calls DBusThreadManager::Get().
     chromeos::DBusThreadManager::Initialize();
     ash::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
 
     ArcSessionManager::SetUiEnabledForTesting(false);
     SetArcBlockedDueToIncompatibleFileSystemForTesting(false);
@@ -183,7 +183,7 @@
     arc_session_manager_->Shutdown();
     arc_session_manager_.reset();
     arc_service_manager_.reset();
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
     ash::ConciergeClient::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
   }
@@ -213,7 +213,7 @@
 
   SetArcAvailableCommandLineForTesting(base::CommandLine::ForCurrentProcess());
 
-  chromeos::SessionManagerClient::Get()->EmitLoginPromptVisible();
+  ash::SessionManagerClient::Get()->EmitLoginPromptVisible();
   ASSERT_TRUE(arc_session());
   EXPECT_FALSE(arc_session()->is_running());
   EXPECT_EQ(ArcSessionManager::State::NOT_INITIALIZED,
@@ -225,7 +225,7 @@
 TEST_F(ArcSessionManagerInLoginScreenTest, EmitLoginPromptVisible_NoOp) {
   EXPECT_FALSE(arc_session());
 
-  chromeos::SessionManagerClient::Get()->EmitLoginPromptVisible();
+  ash::SessionManagerClient::Get()->EmitLoginPromptVisible();
   EXPECT_FALSE(arc_session());
   EXPECT_EQ(ArcSessionManager::State::NOT_INITIALIZED,
             arc_session_manager()->state());
@@ -240,7 +240,7 @@
   command_line.GetProcessCommandLine()->AppendSwitchASCII("arc-start-mode",
                                                           "manual");
 
-  chromeos::SessionManagerClient::Get()->EmitLoginPromptVisible();
+  ash::SessionManagerClient::Get()->EmitLoginPromptVisible();
   EXPECT_FALSE(arc_session());
   EXPECT_EQ(ArcSessionManager::State::NOT_INITIALIZED,
             arc_session_manager()->state());
@@ -252,7 +252,7 @@
 
   SetArcAvailableCommandLineForTesting(base::CommandLine::ForCurrentProcess());
 
-  chromeos::SessionManagerClient::Get()->EmitLoginPromptVisible();
+  ash::SessionManagerClient::Get()->EmitLoginPromptVisible();
   EXPECT_TRUE(arc_session());
 
   arc_session_manager()->StopMiniArcIfNecessary();
@@ -278,7 +278,7 @@
     chromeos::DBusThreadManager::Initialize();
     ash::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
     chromeos::PowerManagerClient::InitializeFake();
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
     ash::UpstartClient::InitializeFake();
 
     SetArcAvailableCommandLineForTesting(
@@ -308,7 +308,7 @@
     arc_session_manager_.reset();
     arc_service_manager_.reset();
     ash::UpstartClient::Shutdown();
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
     ash::ConciergeClient::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
diff --git a/chrome/browser/ash/authpolicy/authpolicy_credentials_manager_unittest.cc b/chrome/browser/ash/authpolicy/authpolicy_credentials_manager_unittest.cc
index 993c6ec1..df330a9d 100644
--- a/chrome/browser/ash/authpolicy/authpolicy_credentials_manager_unittest.cc
+++ b/chrome/browser/ash/authpolicy/authpolicy_credentials_manager_unittest.cc
@@ -16,7 +16,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/dbus/authpolicy/fake_authpolicy_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/authpolicy/authpolicy_helper_unittest.cc b/chrome/browser/ash/authpolicy/authpolicy_helper_unittest.cc
index dcdfc4d7c..2ecbb982 100644
--- a/chrome/browser/ash/authpolicy/authpolicy_helper_unittest.cc
+++ b/chrome/browser/ash/authpolicy/authpolicy_helper_unittest.cc
@@ -7,8 +7,8 @@
 #include "ash/components/tpm/stub_install_attributes.h"
 #include "base/bind.h"
 #include "chromeos/ash/components/dbus/authpolicy/fake_authpolicy_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/fake_install_attributes_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler_unittest.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler_unittest.cc
index 6b4090d..1884a2f 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler_unittest.cc
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler_unittest.cc
@@ -17,9 +17,9 @@
 #include "chrome/browser/ash/platform_keys/platform_keys_service.h"
 #include "chrome/browser/platform_keys/platform_keys.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/attestation/fake_attestation_client.h"
 #include "chromeos/dbus/attestation/interface.pb.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
 #include "components/prefs/testing_pref_service.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/child_accounts/screen_time_controller.cc b/chrome/browser/ash/child_accounts/screen_time_controller.cc
index 50b93434..2bdb885 100644
--- a/chrome/browser/ash/child_accounts/screen_time_controller.cc
+++ b/chrome/browser/ash/child_accounts/screen_time_controller.cc
@@ -227,7 +227,7 @@
     return;
   }
 
-  chromeos::SessionManagerClient::Get()->RequestLockScreen();
+  SessionManagerClient::Get()->RequestLockScreen();
 }
 
 void ScreenTimeController::OnAccessCodeValidation(
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.cc b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
index 916559f..15ba286b 100644
--- a/chrome/browser/ash/chrome_browser_main_parts_ash.cc
+++ b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
@@ -201,7 +201,10 @@
 #include "chromeos/ash/components/dbus/services/cros_dbus_service.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/ash/components/network/portal_detector/network_portal_detector_stub.h"
+#include "chromeos/ash/services/cros_healthd/private/cpp/data_collector.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "chromeos/components/local_search_service/public/cpp/local_search_service_proxy_factory.h"
 #include "chromeos/components/sensors/ash/sensor_hal_dispatcher.h"
 #include "chromeos/dbus/constants/cryptohome_key_delegate_constants.h"
@@ -209,15 +212,12 @@
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/util/version_loader.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/fast_transition_observer.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/system_token_cert_db_storage.h"
-#include "chromeos/services/cros_healthd/private/cpp/data_collector.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
 #include "chromeos/services/machine_learning/public/cpp/service_connection.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/account_id/account_id.h"
@@ -298,9 +298,9 @@
 }
 
 #if !defined(USE_REAL_DBUS_CLIENTS)
-chromeos::FakeSessionManagerClient* FakeSessionManagerClient() {
-  chromeos::FakeSessionManagerClient* fake_session_manager_client =
-      chromeos::FakeSessionManagerClient::Get();
+ash::FakeSessionManagerClient* FakeSessionManagerClient() {
+  ash::FakeSessionManagerClient* fake_session_manager_client =
+      ash::FakeSessionManagerClient::Get();
   DCHECK(fake_session_manager_client);
   return fake_session_manager_client;
 }
diff --git a/chrome/browser/ash/chromebox_for_meetings/device_info/device_info_service_unittest.cc b/chrome/browser/ash/chromebox_for_meetings/device_info/device_info_service_unittest.cc
index bf72821f..7ea4605 100644
--- a/chrome/browser/ash/chromebox_for_meetings/device_info/device_info_service_unittest.cc
+++ b/chrome/browser/ash/chromebox_for_meetings/device_info/device_info_service_unittest.cc
@@ -138,7 +138,7 @@
   FakeCfmServiceContext context_;
   FakeServiceConnectionImpl fake_service_connection_;
   ScopedTestDeviceSettingsService scoped_device_settings_service_;
-  chromeos::FakeSessionManagerClient session_manager_client_;
+  FakeSessionManagerClient session_manager_client_;
   chromeos::system::FakeStatisticsProvider fake_statistics_provider_;
   mojo::ReceiverSet<mojom::CfmServiceContext> context_receiver_set_;
   mojo::Remote<mojom::CfmServiceAdaptor> adaptor_remote_;
diff --git a/chrome/browser/ash/chromebox_for_meetings/diagnostics/diagnostics_service.cc b/chrome/browser/ash/chromebox_for_meetings/diagnostics/diagnostics_service.cc
index 56bc93f0..5c62890 100644
--- a/chrome/browser/ash/chromebox_for_meetings/diagnostics/diagnostics_service.cc
+++ b/chrome/browser/ash/chromebox_for_meetings/diagnostics/diagnostics_service.cc
@@ -8,7 +8,7 @@
 
 #include "base/bind.h"
 #include "chromeos/ash/components/dbus/chromebox_for_meetings/cfm_hotline_client.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 
 namespace ash::cfm {
diff --git a/chrome/browser/ash/chromebox_for_meetings/diagnostics/diagnostics_service_unittest.cc b/chrome/browser/ash/chromebox_for_meetings/diagnostics/diagnostics_service_unittest.cc
index dab5985..7ff128b 100644
--- a/chrome/browser/ash/chromebox_for_meetings/diagnostics/diagnostics_service_unittest.cc
+++ b/chrome/browser/ash/chromebox_for_meetings/diagnostics/diagnostics_service_unittest.cc
@@ -20,8 +20,8 @@
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
 #include "chromeos/ash/components/dbus/chromebox_for_meetings/fake_cfm_hotline_client.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "content/public/test/test_utils.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index f41cc053..4264ddc 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -234,6 +234,7 @@
     "//chrome/common:constants",
     "//chromeos/ash/components/dbus/session_manager",
     "//chromeos/ash/components/dbus/upstart",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_browser",
     "//chromeos/components/quick_answers/public/cpp:prefs",
     "//chromeos/components/remote_apps/mojom",
@@ -246,11 +247,11 @@
     "//chromeos/dbus/power",
     "//chromeos/dbus/resourced",
     "//chromeos/dbus/update_engine",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//chromeos/login/login_state",
     "//chromeos/network",
     "//chromeos/printing",
     "//chromeos/services/machine_learning/public/cpp",
+    "//chromeos/services/network_config/public/cpp",
     "//chromeos/startup",
     "//chromeos/startup:constants",
     "//chromeos/system",
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc b/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc
index 99e4063..cef4673 100644
--- a/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc
+++ b/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc
@@ -74,7 +74,7 @@
   }
 
   void SetUpInProcessBrowserTestFixture() override {
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    SessionManagerClient::InitializeFakeInMemory();
   }
 
  protected:
@@ -112,10 +112,10 @@
       base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
   LoginAsRegularUser();
   run_loop.Run();
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
-                  ->request_browser_data_migration_called());
+  EXPECT_TRUE(
+      FakeSessionManagerClient::Get()->request_browser_data_migration_called());
   // Migration should be triggered in copy mode and not move mode.
-  EXPECT_FALSE(chromeos::FakeSessionManagerClient::Get()
+  EXPECT_FALSE(FakeSessionManagerClient::Get()
                    ->request_browser_data_migration_for_move_called());
 };
 
@@ -160,9 +160,9 @@
   SetLacrosAvailability(crosapi::browser_util::LacrosAvailability::kLacrosOnly);
   LoginAsRegularUser();
   run_loop.Run();
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
-                  ->request_browser_data_migration_called());
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
+  EXPECT_TRUE(
+      FakeSessionManagerClient::Get()->request_browser_data_migration_called());
+  EXPECT_TRUE(FakeSessionManagerClient::Get()
                   ->request_browser_data_migration_for_move_called());
 };
 
@@ -199,9 +199,9 @@
       base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
   LoginAsRegularUser();
   run_loop.Run();
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
-                  ->request_browser_data_migration_called());
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
+  EXPECT_TRUE(
+      FakeSessionManagerClient::Get()->request_browser_data_migration_called());
+  EXPECT_TRUE(FakeSessionManagerClient::Get()
                   ->request_browser_data_migration_for_move_called());
 };
 
@@ -240,9 +240,9 @@
       base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
   LoginAsRegularUser();
   run_loop.Run();
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
-                  ->request_browser_data_migration_called());
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
+  EXPECT_TRUE(
+      FakeSessionManagerClient::Get()->request_browser_data_migration_called());
+  EXPECT_TRUE(FakeSessionManagerClient::Get()
                   ->request_browser_data_migration_for_move_called());
 }
 
@@ -288,7 +288,7 @@
   }
 
   void SetUpInProcessBrowserTestFixture() override {
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    SessionManagerClient::InitializeFakeInMemory();
   }
 
  protected:
@@ -326,9 +326,9 @@
 IN_PROC_BROWSER_TEST_F(
     BrowserDataMigratorMoveMigrateOnRestartInSessionByFeature,
     RunMoveMigration) {
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
-                  ->request_browser_data_migration_called());
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
+  EXPECT_TRUE(
+      FakeSessionManagerClient::Get()->request_browser_data_migration_called());
+  EXPECT_TRUE(FakeSessionManagerClient::Get()
                   ->request_browser_data_migration_for_move_called());
 }
 
@@ -362,9 +362,9 @@
 // restart.
 IN_PROC_BROWSER_TEST_F(BrowserDataMigratorMoveMigrateOnRestartInSessionByPolicy,
                        RunMoveMigration) {
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
-                  ->request_browser_data_migration_called());
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
+  EXPECT_TRUE(
+      FakeSessionManagerClient::Get()->request_browser_data_migration_called());
+  EXPECT_TRUE(FakeSessionManagerClient::Get()
                   ->request_browser_data_migration_for_move_called());
 }
 
@@ -393,9 +393,9 @@
                        ResumeMigration) {
   // Test `MaybeForceResumeMoveMigration()` in
   // `ChromeBrowserMainPartsAsh::PreProfileInit()`.
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
-                  ->request_browser_data_migration_called());
-  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
+  EXPECT_TRUE(
+      FakeSessionManagerClient::Get()->request_browser_data_migration_called());
+  EXPECT_TRUE(FakeSessionManagerClient::Get()
                   ->request_browser_data_migration_for_move_called());
 }
 
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_util.cc b/chrome/browser/ash/crosapi/browser_data_migrator_util.cc
index 1f43c529..369b21b 100644
--- a/chrome/browser/ash/crosapi/browser_data_migrator_util.cc
+++ b/chrome/browser/ash/crosapi/browser_data_migrator_util.cc
@@ -724,9 +724,9 @@
   return true;
 }
 
-bool MigrateSyncData(const base::FilePath& original_path,
-                     const base::FilePath& ash_target_path,
-                     const base::FilePath& lacros_target_path) {
+bool MigrateSyncDataLevelDB(const base::FilePath& original_path,
+                            const base::FilePath& ash_target_path,
+                            const base::FilePath& lacros_target_path) {
   // Open the original LevelDB database.
   std::unique_ptr<leveldb::DB> original_db;
   leveldb_env::Options options;
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_util.h b/chrome/browser/ash/crosapi/browser_data_migrator_util.h
index 315665ff5..7390865 100644
--- a/chrome/browser/ash/crosapi/browser_data_migrator_util.h
+++ b/chrome/browser/ash/crosapi/browser_data_migrator_util.h
@@ -232,6 +232,7 @@
 // `Sync Data` path.
 constexpr char kSyncDataFilePath[] = "Sync Data";
 constexpr char kSyncDataLeveldbName[] = "LevelDB";
+constexpr char kSyncDataNigoriFileName[] = "Nigori.bin";
 
 // State Store paths.
 constexpr const char* const kStateStorePaths[] = {
@@ -489,9 +490,9 @@
 // Migrate Sync Data's LevelDB instance at `original_path` to Ash and Lacros.
 // For Ash, filter out the data types that are not meant to be ported to Lacros.
 // For Lacros, filter out the data types that are meant to stay in Ash.
-bool MigrateSyncData(const base::FilePath& original_path,
-                     const base::FilePath& ash_target_path,
-                     const base::FilePath& lacros_target_path);
+bool MigrateSyncDataLevelDB(const base::FilePath& original_path,
+                            const base::FilePath& ash_target_path,
+                            const base::FilePath& lacros_target_path);
 
 // Manipulates the given representation of Preferences (`root_dict`)
 // so that the given key only contains values relevant to Ash or
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_util_unittest.cc b/chrome/browser/ash/crosapi/browser_data_migrator_util_unittest.cc
index a7baa380..1dcc0ea 100644
--- a/chrome/browser/ash/crosapi/browser_data_migrator_util_unittest.cc
+++ b/chrome/browser/ash/crosapi/browser_data_migrator_util_unittest.cc
@@ -421,7 +421,7 @@
   EXPECT_EQ(expected_keys, keys);
 }
 
-TEST(BrowserDataMigratorUtilTest, MigrateSyncData) {
+TEST(BrowserDataMigratorUtilTest, MigrateSyncDataLevelDB) {
   base::ScopedTempDir scoped_temp_dir;
   ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
 
@@ -435,7 +435,7 @@
   // Migrate Sync Data.
   const base::FilePath ash_db_path = db_path.AddExtension(".ash");
   const base::FilePath lacros_db_path = db_path.AddExtension(".lacros");
-  EXPECT_TRUE(MigrateSyncData(db_path, ash_db_path, lacros_db_path));
+  EXPECT_TRUE(MigrateSyncDataLevelDB(db_path, ash_db_path, lacros_db_path));
 
   // Check resulting Ash database.
   auto ash_db_map = ReadLevelDB(ash_db_path);
diff --git a/chrome/browser/ash/crosapi/geolocation_service_ash_unittest.cc b/chrome/browser/ash/crosapi/geolocation_service_ash_unittest.cc
index 30aa5a1..ef48ca63 100644
--- a/chrome/browser/ash/crosapi/geolocation_service_ash_unittest.cc
+++ b/chrome/browser/ash/crosapi/geolocation_service_ash_unittest.cc
@@ -9,10 +9,10 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/geolocation_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
diff --git a/chrome/browser/ash/crosapi/idle_service_ash.cc b/chrome/browser/ash/crosapi/idle_service_ash.cc
index 774478c..48066e0 100644
--- a/chrome/browser/ash/crosapi/idle_service_ash.cc
+++ b/chrome/browser/ash/crosapi/idle_service_ash.cc
@@ -26,15 +26,15 @@
 IdleServiceAsh::Dispatcher::Dispatcher() {
   if (!IdleServiceAsh::Dispatcher::is_disabled_for_testing_) {
     CHECK(ui::UserActivityDetector::Get());
-    CHECK(chromeos::SessionManagerClient::Get());
+    CHECK(ash::SessionManagerClient::Get());
     ui::UserActivityDetector::Get()->AddObserver(this);
-    chromeos::SessionManagerClient::Get()->AddObserver(this);
+    ash::SessionManagerClient::Get()->AddObserver(this);
   }
 }
 
 IdleServiceAsh::Dispatcher::~Dispatcher() {
   if (!IdleServiceAsh::Dispatcher::is_disabled_for_testing_) {
-    chromeos::SessionManagerClient::Get()->RemoveObserver(this);
+    ash::SessionManagerClient::Get()->RemoveObserver(this);
 
     // UserActivityDetector may not be exist on actual shutdown, because
     // the ProfileManager destruct before CrosapiManager.
@@ -88,8 +88,7 @@
         ui::UserActivityDetector::Get()->last_activity_time();
 
     // Taken from ui::CheckIdleStateIsLocked() for ChromeOS.
-    idle_info->is_locked =
-        chromeos::SessionManagerClient::Get()->IsScreenLocked();
+    idle_info->is_locked = ash::SessionManagerClient::Get()->IsScreenLocked();
   }
 
   return idle_info;
diff --git a/chrome/browser/ash/crosapi/idle_service_ash.h b/chrome/browser/ash/crosapi/idle_service_ash.h
index 2ca17518..2728ec9 100644
--- a/chrome/browser/ash/crosapi/idle_service_ash.h
+++ b/chrome/browser/ash/crosapi/idle_service_ash.h
@@ -25,7 +25,7 @@
   // Helper to observe changes in relevant quantities, read these values, and
   // manage / dispatch to observers for IdleServiceAsh.
   class Dispatcher : public ui::UserActivityObserver,
-                     public chromeos::SessionManagerClient::Observer {
+                     public ash::SessionManagerClient::Observer {
    public:
     Dispatcher();
     Dispatcher(const Dispatcher&) = delete;
@@ -35,7 +35,7 @@
     // ui::UserActivityObserver:
     void OnUserActivity(const ui::Event* event) override;
 
-    // chromeos::SessionManagerClient::Observer:
+    // SessionManagerClient::Observer:
     void ScreenLockedStateUpdated() override;
 
    private:
diff --git a/chrome/browser/ash/crosapi/login_screen_storage_ash.cc b/chrome/browser/ash/crosapi/login_screen_storage_ash.cc
index a19ed78..9a0893b 100644
--- a/chrome/browser/ash/crosapi/login_screen_storage_ash.cc
+++ b/chrome/browser/ash/crosapi/login_screen_storage_ash.cc
@@ -47,7 +47,7 @@
   auto dbus_callback = base::BindOnce(
       &LoginScreenStorageAsh::OnStored, weak_ptr_factory_.GetWeakPtr(),
       std::move(keys), metadata, data, std::move(callback));
-  chromeos::SessionManagerClient::Get()->LoginScreenStorageStore(
+  ash::SessionManagerClient::Get()->LoginScreenStorageStore(
       key, metadata, data, std::move(dbus_callback));
 }
 
@@ -75,7 +75,7 @@
   auto dbus_callback =
       base::BindOnce(&LoginScreenStorageAsh::OnRetrieved,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback));
-  chromeos::SessionManagerClient::Get()->LoginScreenStorageRetrieve(
+  ash::SessionManagerClient::Get()->LoginScreenStorageRetrieve(
       key, std::move(dbus_callback));
 }
 
diff --git a/chrome/browser/ash/crosapi/login_screen_storage_ash_unittest.cc b/chrome/browser/ash/crosapi/login_screen_storage_ash_unittest.cc
index e503c53..0c6a35cc7 100644
--- a/chrome/browser/ash/crosapi/login_screen_storage_ash_unittest.cc
+++ b/chrome/browser/ash/crosapi/login_screen_storage_ash_unittest.cc
@@ -61,25 +61,23 @@
 }
 
 void LoginScreenStorageStoreSuccess(
-    chromeos::FakeSessionManagerClient::LoginScreenStorageStoreCallback
-        callback) {
+    ash::FakeSessionManagerClient::LoginScreenStorageStoreCallback callback) {
   std::move(callback).Run(/*error_message=*/absl::nullopt);
 }
 
 void LoginScreenStorageStoreError(
-    chromeos::FakeSessionManagerClient::LoginScreenStorageStoreCallback
-        callback) {
+    ash::FakeSessionManagerClient::LoginScreenStorageStoreCallback callback) {
   std::move(callback).Run(kError);
 }
 
 void LoginScreenStorageRetrieveSuccess(
-    chromeos::FakeSessionManagerClient::LoginScreenStorageRetrieveCallback
+    ash::FakeSessionManagerClient::LoginScreenStorageRetrieveCallback
         callback) {
   std::move(callback).Run(kData, /*error_message=*/absl::nullopt);
 }
 
 void LoginScreenStorageRetrieveError(
-    chromeos::FakeSessionManagerClient::LoginScreenStorageRetrieveCallback
+    ash::FakeSessionManagerClient::LoginScreenStorageRetrieveCallback
         callback) {
   std::move(callback).Run(/*data=*/absl::nullopt, kError);
 }
@@ -88,7 +86,7 @@
 class LoginScreenStorageAshTest : public testing::Test {
  public:
   // A mock around FakeSessionManagerClient for tracking the D-Bus calls.
-  class MockSessionManagerClient : public chromeos::FakeSessionManagerClient {
+  class MockSessionManagerClient : public ash::FakeSessionManagerClient {
    public:
     MockSessionManagerClient() = default;
     ~MockSessionManagerClient() override = default;
diff --git a/chrome/browser/ash/crosapi/move_migrator.cc b/chrome/browser/ash/crosapi/move_migrator.cc
index 8260de7..a8f133c 100644
--- a/chrome/browser/ash/crosapi/move_migrator.cc
+++ b/chrome/browser/ash/crosapi/move_migrator.cc
@@ -489,7 +489,7 @@
           original_profile_dir
               .Append(browser_data_migrator_util::kSyncDataFilePath)
               .Append(browser_data_migrator_util::kSyncDataLeveldbName))) {
-    if (!browser_data_migrator_util::MigrateSyncData(
+    if (!browser_data_migrator_util::MigrateSyncDataLevelDB(
             original_profile_dir
                 .Append(browser_data_migrator_util::kSyncDataFilePath)
                 .Append(browser_data_migrator_util::kSyncDataLeveldbName),
@@ -498,8 +498,8 @@
             tmp_profile_dir
                 .Append(browser_data_migrator_util::kSyncDataFilePath)
                 .Append(browser_data_migrator_util::kSyncDataLeveldbName))) {
-      LOG(ERROR) << "MigrateSyncData() failed";
-      return {TaskStatus::kSetupAshDirMigrateSyncDataFailed};
+      LOG(ERROR) << "MigrateSyncDataLevelDB() failed";
+      return {TaskStatus::kSetupAshDirMigrateSyncDataLevelDBFailed};
     }
   }
 
@@ -554,6 +554,35 @@
       original_profile_dir.Append(browser_data_migrator_util::kMoveTmpDir)
           .Append(browser_data_migrator_util::kLacrosProfilePath);
 
+  // Nigori file needs special handling, because it's not stored directly under
+  // |original_profile_dir|.
+  const base::FilePath original_nigori_path =
+      original_profile_dir.Append(browser_data_migrator_util::kSyncDataFilePath)
+          .Append(browser_data_migrator_util::kSyncDataNigoriFileName);
+  if (base::PathExists(original_nigori_path)) {
+    // In theory, `Sync Data` directory should be already created by
+    // SplitSyncDataLevelDB() as long as DB exists. It still needs to be created
+    // manually here, to handle the case when DB doesn't exist, but Nigori file
+    // does.
+    if (!base::CreateDirectory(tmp_profile_dir.Append(
+            browser_data_migrator_util::kSyncDataFilePath))) {
+      PLOG(ERROR) << "Failure while creating "
+                  << tmp_profile_dir.Append(
+                         browser_data_migrator_util::kSyncDataFilePath)
+                  << " directory.";
+      return {TaskStatus::kMoveLacrosItemsCreateDirFailed, errno};
+    }
+
+    const base::FilePath target_nigori_path =
+        tmp_profile_dir.Append(browser_data_migrator_util::kSyncDataFilePath)
+            .Append(browser_data_migrator_util::kSyncDataNigoriFileName);
+    if (!base::Move(original_nigori_path, target_nigori_path)) {
+      PLOG(ERROR) << "Failed to move item " << original_nigori_path.value()
+                  << " to " << target_nigori_path << ": ";
+      return {TaskStatus::kMoveLacrosItemsToNewDirMoveFailed, errno};
+    }
+  }
+
   for (const auto& item : lacros_items.items) {
     if (!base::Move(item.path, tmp_profile_dir.Append(item.path.BaseName()))) {
       PLOG(ERROR) << "Failed to move item " << item.path.value() << " to "
@@ -849,9 +878,10 @@
     case TaskStatus::kSetupAshDirCreateDirFailed:
     case TaskStatus::kSetupAshDirCopyExtensionsFailed:
     case TaskStatus::kSetupAshDirCopyIndexedDBFailed:
-    case TaskStatus::kSetupAshDirMigrateSyncDataFailed:
+    case TaskStatus::kSetupAshDirMigrateSyncDataLevelDBFailed:
     case TaskStatus::kSetupAshDirCopyStorageFailed:
     case TaskStatus::kMoveSplitItemsToOriginalDirMoveStorageFailed:
+    case TaskStatus::kMoveLacrosItemsCreateDirFailed:
       return {BrowserDataMigratorImpl::DataWipeResult::kSucceeded,
               {BrowserDataMigratorImpl::ResultKind::kFailed}};
   }
@@ -898,9 +928,10 @@
     MAPPING(SetupAshDirCreateDirFailed);
     MAPPING(SetupAshDirCopyExtensionsFailed);
     MAPPING(SetupAshDirCopyIndexedDBFailed);
-    MAPPING(SetupAshDirMigrateSyncDataFailed);
+    MAPPING(SetupAshDirMigrateSyncDataLevelDBFailed);
     MAPPING(SetupAshDirCopyStorageFailed);
     MAPPING(MoveSplitItemsToOriginalDirMoveStorageFailed);
+    MAPPING(MoveLacrosItemsCreateDirFailed);
 #undef MAPPING
   }
 }
diff --git a/chrome/browser/ash/crosapi/move_migrator.h b/chrome/browser/ash/crosapi/move_migrator.h
index d6d108a..d0154b0b 100644
--- a/chrome/browser/ash/crosapi/move_migrator.h
+++ b/chrome/browser/ash/crosapi/move_migrator.h
@@ -172,10 +172,11 @@
     kSetupAshDirCreateDirFailed = 21,
     kSetupAshDirCopyExtensionsFailed = 22,
     kSetupAshDirCopyIndexedDBFailed = 23,
-    kSetupAshDirMigrateSyncDataFailed = 24,
+    kSetupAshDirMigrateSyncDataLevelDBFailed = 24,
     kSetupAshDirCopyStorageFailed = 25,
     kMoveSplitItemsToOriginalDirMoveStorageFailed = 26,
-    kMaxValue = kMoveSplitItemsToOriginalDirMoveStorageFailed,
+    kMoveLacrosItemsCreateDirFailed = 27,
+    kMaxValue = kMoveLacrosItemsCreateDirFailed,
   };
 
   struct TaskResult {
diff --git a/chrome/browser/ash/crosapi/move_migrator_unittest.cc b/chrome/browser/ash/crosapi/move_migrator_unittest.cc
index b51a931a..b535b35 100644
--- a/chrome/browser/ash/crosapi/move_migrator_unittest.cc
+++ b/chrome/browser/ash/crosapi/move_migrator_unittest.cc
@@ -63,6 +63,11 @@
 constexpr int64_t kRequiredDiskSpaceForBot =
     browser_data_migrator_util::kBuffer * 2;
 
+base::FilePath GetNigoriPath(const base::FilePath& profile_path) {
+  return profile_path.Append(browser_data_migrator_util::kSyncDataFilePath)
+      .Append(browser_data_migrator_util::kSyncDataNigoriFileName);
+}
+
 // Setup the `Extensions` folder inside a profile.
 // If `ash_only` is true, it will only generate data associated to extensions
 // that have to be kept in Ash. Otherwise, it will generate data for both
@@ -298,17 +303,18 @@
   ASSERT_TRUE(base::WriteFile(path, contents));
 }
 
-void SetUpSyncData(const base::FilePath& profile_path,
-                   bool ash = true,
-                   bool lacros = true) {
-  base::FilePath path =
+void SetUpSyncDataLevelDB(const base::FilePath& profile_path,
+                          bool ash = true,
+                          bool lacros = true) {
+  base::FilePath leveldb_path =
       profile_path.Append(browser_data_migrator_util::kSyncDataFilePath)
           .Append(browser_data_migrator_util::kSyncDataLeveldbName);
 
   leveldb_env::Options options;
   options.create_if_missing = true;
   std::unique_ptr<leveldb::DB> db;
-  leveldb::Status status = leveldb_env::OpenDB(options, path.value(), &db);
+  leveldb::Status status =
+      leveldb_env::OpenDB(options, leveldb_path.value(), &db);
   ASSERT_TRUE(status.ok());
 
   leveldb::WriteBatch batch;
@@ -350,6 +356,8 @@
   // |- Preferences
   // |- Storage/
   // |- Sync Data/
+  //     |- LevelDB
+  //     |- Nigori.bin
   ASSERT_TRUE(base::CreateDirectory(path.Append(kCacheFilePath)));
   ASSERT_EQ(base::WriteFile(path.Append(kCacheFilePath).Append(kDataFilePath),
                             kDataContent, kDataSize),
@@ -375,13 +383,18 @@
                             kDataContent, kDataSize),
             kDataSize);
 
+  ASSERT_TRUE(base::CreateDirectory(
+      path.Append(browser_data_migrator_util::kSyncDataFilePath)));
+  ASSERT_EQ(base::WriteFile(GetNigoriPath(path), kDataContent, kDataSize),
+            kDataSize);
+
   SetUpExtensions(path);
   SetUpStorage(path);
   SetUpLocalStorage(path);
   SetUpExtensionState(path);
   SetUpIndexedDB(path);
   SetUpPreferences(path);
-  SetUpSyncData(path);
+  SetUpSyncDataLevelDB(path);
 }
 
 std::map<std::string, std::string> ReadLevelDB(const base::FilePath& path) {
@@ -517,12 +530,14 @@
   EXPECT_FALSE(
       base::PathExists(original_profile_dir.Append(kBookmarksFilePath)));
   EXPECT_FALSE(base::PathExists(original_profile_dir.Append(kCookiesFilePath)));
+  EXPECT_FALSE(base::PathExists(GetNigoriPath(original_profile_dir)));
   EXPECT_TRUE(base::PathExists(tmp_profile_dir.Append(kBookmarksFilePath)));
   EXPECT_TRUE(base::PathExists(tmp_profile_dir.Append(kCookiesFilePath)));
   EXPECT_TRUE(base::PathExists(
       tmp_profile_dir.Append(browser_data_migrator_util::kExtensionsFilePath)));
   EXPECT_TRUE(base::PathExists(
       tmp_profile_dir.Append(browser_data_migrator_util::kIndexedDBFilePath)));
+  EXPECT_TRUE(base::PathExists(GetNigoriPath(tmp_profile_dir)));
 }
 
 TEST(MoveMigratorTest, MoveLacrosItemsToNewDirFailIfNoWritePermForLacrosItem) {
@@ -633,7 +648,8 @@
       tmp_profile_dir.Append(chrome::kPreferencesFilename);
   EXPECT_TRUE(base::PathExists(lacros_path));
 
-  // Check `Sync Data` is present in both tmp_profile_dir and tmp_split_dir.
+  // Check `Sync Data`/LevelDB is present in both tmp_profile_dir and
+  // tmp_split_dir.
   path = tmp_split_dir.Append(browser_data_migrator_util::kSyncDataFilePath)
              .Append(browser_data_migrator_util::kSyncDataLeveldbName);
   EXPECT_TRUE(base::PathExists(path));
@@ -728,7 +744,7 @@
     // |- Policy
     // |- Preferences
     // |- Storage/
-    // |- Sync Data
+    // |- Sync Data/LevelDB
     // |- lacros/First Run
     // |- lacros/Default/
     //     |- Bookmarks
@@ -739,7 +755,9 @@
     //     |- Policy
     //     |- Preferences
     //     |- Storage/
-    //     |- Sync Data
+    //     |- Sync Data/
+    //         |- LevelDB
+    //         |- Nigori.bin
 
     const base::FilePath new_user_dir =
         original_profile_dir_.Append(browser_data_migrator_util::kLacrosDir);
@@ -883,16 +901,20 @@
     EXPECT_TRUE(base::PathExists(ash_preferences_path));
     EXPECT_TRUE(base::PathExists(lacros_preferences_path));
 
-    // Sync Data.
-    const base::FilePath ash_syncdata_path =
+    // Sync Data/LevelDB.
+    const base::FilePath ash_syncdata_leveldb_path =
         original_profile_dir_
             .Append(browser_data_migrator_util::kSyncDataFilePath)
             .Append(browser_data_migrator_util::kSyncDataLeveldbName);
-    const base::FilePath lacros_syncdata_path =
+    const base::FilePath lacros_syncdata_leveldb_path =
         new_profile_dir.Append(browser_data_migrator_util::kSyncDataFilePath)
             .Append(browser_data_migrator_util::kSyncDataLeveldbName);
-    EXPECT_TRUE(base::PathExists(ash_syncdata_path));
-    EXPECT_TRUE(base::PathExists(lacros_syncdata_path));
+    EXPECT_TRUE(base::PathExists(ash_syncdata_leveldb_path));
+    EXPECT_TRUE(base::PathExists(lacros_syncdata_leveldb_path));
+
+    // Sync Data/Nigori.bin
+    EXPECT_FALSE(base::PathExists(GetNigoriPath(original_profile_dir_)));
+    EXPECT_TRUE(base::PathExists(GetNigoriPath(new_profile_dir)));
   }
 
   void TearDown() override { EXPECT_TRUE(scoped_temp_dir_.Delete()); }
@@ -940,14 +962,16 @@
   //     |- Policy
   //     |- Preferences
   //     |- Storage/
-  //     |- Sync Data
+  //     |- Sync Data/
+  //         |- LevelDB
+  //         |- Nigori.bin
   // |- move_migrator_split/
   //     |- Extensions
   //     |- IndexedDB
   //     |- Local Storage
   //     |- Preferences
   //     |- Storage/
-  //     |- Sync Data
+  //     |- Sync Data/LevelDB
 
   const base::FilePath tmp_user_dir =
       original_profile_dir_.Append(browser_data_migrator_util::kMoveTmpDir);
@@ -970,6 +994,11 @@
   ASSERT_TRUE(base::Move(original_profile_dir_.Append(kBookmarksFilePath),
                          tmp_profile_dir.Append(kBookmarksFilePath)));
 
+  ASSERT_TRUE(base::CreateDirectory(
+      tmp_profile_dir.Append(browser_data_migrator_util::kSyncDataFilePath)));
+  ASSERT_TRUE(base::Move(GetNigoriPath(original_profile_dir_),
+                         GetNigoriPath(tmp_profile_dir)));
+
   // Extensions that have to stay in both Ash and Lacros were copied to the
   // split dir.
   SetUpExtensions(tmp_split_dir, /*ash=*/false, /*lacros=*/false,
@@ -1011,9 +1040,9 @@
   SetUpPreferences(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
   SetUpPreferences(tmp_split_dir, /*ash=*/true, /*lacros=*/false);
 
-  // Sync Data has been split.
-  SetUpSyncData(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
-  SetUpSyncData(tmp_split_dir, /*ash=*/true, /*lacros=*/false);
+  // `Sync Data`/LevelDB has been split.
+  SetUpSyncDataLevelDB(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
+  SetUpSyncDataLevelDB(tmp_split_dir, /*ash=*/true, /*lacros=*/false);
 
   migrator_->Migrate();
   run_loop_->Run();
@@ -1043,14 +1072,16 @@
   //     |- Policy
   //     |- Preferences
   //     |- Storage/
-  //     |- Sync Data
+  //     |- Sync Data/
+  //         |- LevelDB
+  //         |- Nigori.bin
   // |- move_migrator_split/
   //     |- Extensions
   //     |- IndexedDB
   //     |- Local Storage
   //     |- Preferences
   //     |- Storage/
-  //     |- Sync Data
+  //     |- Sync Data/LevelDB
 
   const base::FilePath tmp_user_dir =
       original_profile_dir_.Append(browser_data_migrator_util::kMoveTmpDir);
@@ -1075,6 +1106,11 @@
   ASSERT_TRUE(base::Move(original_profile_dir_.Append(kCookiesFilePath),
                          tmp_profile_dir.Append(kCookiesFilePath)));
 
+  ASSERT_TRUE(base::CreateDirectory(
+      tmp_profile_dir.Append(browser_data_migrator_util::kSyncDataFilePath)));
+  ASSERT_TRUE(base::Move(GetNigoriPath(original_profile_dir_),
+                         GetNigoriPath(tmp_profile_dir)));
+
   // Extensions that have to stay in both Ash and Lacros were copied to the
   // split dir.
   SetUpExtensions(tmp_split_dir, /*ash=*/false, /*lacros=*/false,
@@ -1119,9 +1155,9 @@
   SetUpPreferences(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
   SetUpPreferences(tmp_split_dir, /*ash=*/true, /*lacros=*/false);
 
-  // `Sync Data` has been split, but not yet moved to Ash profile dir.
-  SetUpSyncData(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
-  SetUpSyncData(tmp_split_dir, /*ash=*/true, /*lacros=*/false);
+  // `Sync Data`/LevelDB has been split, but not yet moved to Ash profile dir.
+  SetUpSyncDataLevelDB(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
+  SetUpSyncDataLevelDB(tmp_split_dir, /*ash=*/true, /*lacros=*/false);
 
   migrator_->Migrate();
   run_loop_->Run();
@@ -1145,7 +1181,7 @@
   // |- Policy
   // |- Preferences
   // |- Storage/
-  // |- Sync Data
+  // |- Sync Data/LevelDB
   // |- move_migrator/First Run
   // |- move_migrator/Default/
   //     |- Bookmarks
@@ -1155,7 +1191,9 @@
   //     |- Policy
   //     |- Preferences
   //     |- Storage/
-  //     |- Sync Data
+  //     |- Sync Data/
+  //         |- LevelDB
+  //         |- Nigori.bin
 
   const base::FilePath tmp_user_dir =
       original_profile_dir_.Append(browser_data_migrator_util::kMoveTmpDir);
@@ -1177,6 +1215,11 @@
   ASSERT_TRUE(base::Move(original_profile_dir_.Append(kCookiesFilePath),
                          tmp_profile_dir.Append(kCookiesFilePath)));
 
+  ASSERT_TRUE(base::CreateDirectory(
+      tmp_profile_dir.Append(browser_data_migrator_util::kSyncDataFilePath)));
+  ASSERT_TRUE(base::Move(GetNigoriPath(original_profile_dir_),
+                         GetNigoriPath(tmp_profile_dir)));
+
   // Extensions have been split, and Ash's version is in its final place.
   ASSERT_TRUE(base::DeletePathRecursively(original_profile_dir_.Append(
       browser_data_migrator_util::kExtensionsFilePath)));
@@ -1207,9 +1250,9 @@
   SetUpPreferences(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
   SetUpPreferences(original_profile_dir_, /*ash=*/true, /*lacros=*/false);
 
-  // `Sync Data` has been split.
-  SetUpSyncData(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
-  SetUpSyncData(original_profile_dir_, /*ash=*/true, /*lacros=*/false);
+  // `Sync Data`/LevelDB has been split.
+  SetUpSyncDataLevelDB(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
+  SetUpSyncDataLevelDB(original_profile_dir_, /*ash=*/true, /*lacros=*/false);
 
   migrator_->Migrate();
   run_loop_->Run();
diff --git a/chrome/browser/ash/crosapi/networking_attributes_ash_unittest.cc b/chrome/browser/ash/crosapi/networking_attributes_ash_unittest.cc
index fa80c79..f55d794 100644
--- a/chrome/browser/ash/crosapi/networking_attributes_ash_unittest.cc
+++ b/chrome/browser/ash/crosapi/networking_attributes_ash_unittest.cc
@@ -10,6 +10,7 @@
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/crosapi/mojom/networking_attributes.mojom.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_profile_client.h"
@@ -17,7 +18,6 @@
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/device_state.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/scoped_user_manager.h"
diff --git a/chrome/browser/ash/crosapi/video_frame_handler_ash.cc b/chrome/browser/ash/crosapi/video_frame_handler_ash.cc
index a376763..bbc6fab1 100644
--- a/chrome/browser/ash/crosapi/video_frame_handler_ash.cc
+++ b/chrome/browser/ash/crosapi/video_frame_handler_ash.cc
@@ -185,6 +185,10 @@
   proxy_->OnFrameDropped(reason);
 }
 
+void VideoFrameHandlerAsh::OnNewCropVersion(uint32_t crop_version) {
+  proxy_->OnNewCropVersion(crop_version);
+}
+
 void VideoFrameHandlerAsh::OnFrameWithEmptyRegionCapture() {
   proxy_->OnFrameWithEmptyRegionCapture();
 }
diff --git a/chrome/browser/ash/crosapi/video_frame_handler_ash.h b/chrome/browser/ash/crosapi/video_frame_handler_ash.h
index 03990f5..f4863ae 100644
--- a/chrome/browser/ash/crosapi/video_frame_handler_ash.h
+++ b/chrome/browser/ash/crosapi/video_frame_handler_ash.h
@@ -71,6 +71,7 @@
   void OnBufferRetired(int buffer_id) override;
   void OnError(media::VideoCaptureError error) override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnLog(const std::string& message) override;
   void OnStarted() override;
diff --git a/chrome/browser/ash/crosapi/vpn_service_ash.h b/chrome/browser/ash/crosapi/vpn_service_ash.h
index 8fab7f4..32bb6547 100644
--- a/chrome/browser/ash/crosapi/vpn_service_ash.h
+++ b/chrome/browser/ash/crosapi/vpn_service_ash.h
@@ -25,7 +25,7 @@
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_state_handler_observer.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
@@ -48,28 +48,10 @@
 
 namespace api_vpn = extensions::api::vpn_provider;
 
-class SimpleCrosNetworkObserver
-    : public chromeos::network_config::mojom::CrosNetworkConfigObserver {
- public:
-  // chromeos::network_config::mojom::CrosNetworkConfigObserver:
-  void OnVpnProvidersChanged() override {}
-
-  // We're not interested in these functions, but we still have to override them
-  // since they're purely virtual.
-  void OnActiveNetworksChanged(
-      std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>)
-      final {}
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr) final {}
-  void OnNetworkStateListChanged() final {}
-  void OnDeviceStateListChanged() final {}
-  void OnNetworkCertificatesChanged() final {}
-  void OnPoliciesApplied(const std::string&) final {}
-};
-
 // Listens to |OnVpnProvidersChanged| event and informs the delegate of the
 // current set of vpn extension.
-class VpnProvidersObserver : public SimpleCrosNetworkObserver {
+class VpnProvidersObserver
+    : public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   class Delegate {
    public:
@@ -82,7 +64,7 @@
   explicit VpnProvidersObserver(Delegate*);
   ~VpnProvidersObserver() override;
 
-  // chromeos::network_config::mojom::CrosNetworkConfigObserver:
+  // chromeos::network_config::CrosNetworkConfigObserver:
   void OnVpnProvidersChanged() override;
 
  private:
diff --git a/chrome/browser/ash/crostini/crostini_features.cc b/chrome/browser/ash/crostini/crostini_features.cc
index 55fdc7c..b60c01a 100644
--- a/chrome/browser/ash/crostini/crostini_features.cc
+++ b/chrome/browser/ash/crostini/crostini_features.cc
@@ -179,6 +179,7 @@
 bool CrostiniFeatures::CouldBeAllowed(Profile* profile, std::string* reason) {
   if (!base::FeatureList::IsEnabled(features::kCrostini)) {
     VLOG(1) << "Crostini is not enabled in feature list.";
+    // Prior to M105, the /dev/kvm check used the same reason string.
     *reason = "Crostini is not supported on this device";
     return false;
   }
@@ -186,7 +187,7 @@
   if (!crostini::CrostiniManager::IsDevKvmPresent()) {
     // Hardware is physically incapable, no matter what the user wants.
     VLOG(1) << "Cannot run crostini because /dev/kvm is not present.";
-    *reason = "Crostini is not supported on this device";
+    *reason = "Virtualization is not supported on this device";
     return false;
   }
 
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc
index 4ecb5dd..d50daee6 100644
--- a/chrome/browser/ash/crostini/crostini_manager.cc
+++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -30,6 +30,7 @@
 #include "chrome/browser/ash/crostini/crostini_engagement_metrics_service.h"
 #include "chrome/browser/ash/crostini/crostini_features.h"
 #include "chrome/browser/ash/crostini/crostini_manager_factory.h"
+#include "chrome/browser/ash/crostini/crostini_mount_provider.h"
 #include "chrome/browser/ash/crostini/crostini_port_forwarder.h"
 #include "chrome/browser/ash/crostini/crostini_pref_names.h"
 #include "chrome/browser/ash/crostini/crostini_remover.h"
@@ -1092,8 +1093,8 @@
 }
 
 void CrostiniManager::ConfigureForArcSideload() {
-  chromeos::SessionManagerClient* session_manager_client =
-      chromeos::SessionManagerClient::Get();
+  ash::SessionManagerClient* session_manager_client =
+      ash::SessionManagerClient::Get();
   if (!base::FeatureList::IsEnabled(features::kCrostiniArcSideload) ||
       !session_manager_client)
     return;
@@ -1102,11 +1103,11 @@
       // avoid header pollution. This means we have to manually check the weak
       // pointer is alive.
       [](base::WeakPtr<CrostiniManager> manager,
-         chromeos::SessionManagerClient::AdbSideloadResponseCode response_code,
+         ash::SessionManagerClient::AdbSideloadResponseCode response_code,
          bool is_allowed) {
         if (!manager || !is_allowed ||
-            response_code != chromeos::SessionManagerClient::
-                                 AdbSideloadResponseCode::SUCCESS) {
+            response_code !=
+                ash::SessionManagerClient::AdbSideloadResponseCode::SUCCESS) {
           return;
         }
         vm_tools::cicerone::ConfigureForArcSideloadRequest request;
@@ -2237,58 +2238,6 @@
   container_shutdown_observers_.RemoveObserver(observer);
 }
 
-void CrostiniManager::AddFileWatch(const guest_os::GuestId& container_id,
-                                   const base::FilePath& path,
-                                   BoolCallback callback) {
-  vm_tools::cicerone::AddFileWatchRequest request;
-  request.set_vm_name(container_id.vm_name);
-  request.set_container_name(container_id.container_name);
-  request.set_owner_id(CryptohomeIdForProfile(profile_));
-  request.set_path(path.value());
-  GetCiceroneClient()->AddFileWatch(
-      request,
-      base::BindOnce(
-          [](BoolCallback callback,
-             absl::optional<vm_tools::cicerone::AddFileWatchResponse>
-                 response) {
-            std::move(callback).Run(
-                response &&
-                response->status() ==
-                    vm_tools::cicerone::AddFileWatchResponse::SUCCEEDED);
-          },
-          std::move(callback)));
-}
-
-void CrostiniManager::RemoveFileWatch(const guest_os::GuestId& container_id,
-                                      const base::FilePath& path) {
-  vm_tools::cicerone::RemoveFileWatchRequest request;
-  request.set_vm_name(container_id.vm_name);
-  request.set_container_name(container_id.container_name);
-  request.set_owner_id(CryptohomeIdForProfile(profile_));
-  request.set_path(path.value());
-  GetCiceroneClient()->RemoveFileWatch(request, base::DoNothing());
-}
-
-void CrostiniManager::AddFileChangeObserver(
-    CrostiniFileChangeObserver* observer) {
-  file_change_observers_.AddObserver(observer);
-}
-
-void CrostiniManager::RemoveFileChangeObserver(
-    CrostiniFileChangeObserver* observer) {
-  file_change_observers_.RemoveObserver(observer);
-}
-
-void CrostiniManager::OnFileWatchTriggered(
-    const vm_tools::cicerone::FileWatchTriggeredSignal& signal) {
-  for (auto& observer : file_change_observers_) {
-    observer.OnCrostiniFileChanged(
-        guest_os::GuestId(kCrostiniDefaultVmType, signal.vm_name(),
-                          signal.container_name()),
-        base::FilePath(signal.path()));
-  }
-}
-
 void CrostiniManager::GetVshSession(const guest_os::GuestId& container_id,
                                     int32_t host_vsh_pid,
                                     VshSessionCallback callback) {
@@ -4061,15 +4010,24 @@
 }
 
 void CrostiniManager::RegisterContainer(const guest_os::GuestId& container_id) {
-  if (terminal_provider_ids_.find(container_id) !=
+  if (terminal_provider_ids_.find(container_id) ==
       terminal_provider_ids_.end()) {
-    // Already registered, do nothing.
-    return;
+    auto* registry = guest_os::GuestOsService::GetForProfile(profile_)
+                         ->TerminalProviderRegistry();
+    terminal_provider_ids_[container_id] = registry->Register(
+        std::make_unique<CrostiniTerminalProvider>(container_id));
   }
-  auto* terminal_registry = guest_os::GuestOsService::GetForProfile(profile_)
-                                ->TerminalProviderRegistry();
-  terminal_provider_ids_[container_id] = terminal_registry->Register(
-      std::make_unique<CrostiniTerminalProvider>(container_id));
+  if (CrostiniFeatures::Get()->IsMultiContainerAllowed(profile_) &&
+      container_id != DefaultContainerId()) {
+    // TODO(b/217469540): The default container is still using sshfs for now, so
+    // start off using this approach only for non-default.
+    if (mount_provider_ids_.find(container_id) == mount_provider_ids_.end()) {
+      auto* registry = guest_os::GuestOsService::GetForProfile(profile_)
+                           ->MountProviderRegistry();
+      mount_provider_ids_[container_id] = registry->Register(
+          std::make_unique<CrostiniMountProvider>(profile_, container_id));
+    }
+  }
 }
 
 void CrostiniManager::UnregisterContainer(
diff --git a/chrome/browser/ash/crostini/crostini_manager.h b/chrome/browser/ash/crostini/crostini_manager.h
index d76d985..4648c56 100644
--- a/chrome/browser/ash/crostini/crostini_manager.h
+++ b/chrome/browser/ash/crostini/crostini_manager.h
@@ -23,6 +23,7 @@
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/ash/crostini/termina_installer.h"
 #include "chrome/browser/ash/guest_os/guest_id.h"
+#include "chrome/browser/ash/guest_os/public/guest_os_mount_provider_registry.h"
 #include "chrome/browser/ash/guest_os/public/guest_os_terminal_provider_registry.h"
 #include "chrome/browser/ash/vm_shutdown_observer.h"
 #include "chrome/browser/ash/vm_starting_observer.h"
@@ -140,13 +141,6 @@
   virtual void OnContainerShutdown(const guest_os::GuestId& container_id) = 0;
 };
 
-class CrostiniFileChangeObserver : public base::CheckedObserver {
- public:
-  // Called when a path registered via AddFileWatch() is changed.
-  virtual void OnCrostiniFileChanged(const guest_os::GuestId& container_id,
-                                     const base::FilePath& path) = 0;
-};
-
 // CrostiniManager is a singleton which is used to check arguments for
 // ConciergeClient and CiceroneClient. ConciergeClient is dedicated to
 // communication with the Concierge service, CiceroneClient is dedicated to
@@ -429,17 +423,6 @@
   void GetContainerSshKeys(const guest_os::GuestId& container_id,
                            GetContainerSshKeysCallback callback);
 
-  // Add a relative path to watch within the container homedir. Register as a
-  // CrostiniFileChangeObserver to be notified when changes occur. Used by
-  // FilesApp.
-  void AddFileWatch(const guest_os::GuestId& container_id,
-                    const base::FilePath& path,
-                    BoolCallback callback);
-  void RemoveFileWatch(const guest_os::GuestId& container_id,
-                       const base::FilePath& path);
-  void AddFileChangeObserver(CrostiniFileChangeObserver* observer);
-  void RemoveFileChangeObserver(CrostiniFileChangeObserver* observer);
-
   // Lookup vsh session from pid. Used by terminal to open new tabs in cwd.
   using VshSessionCallback =
       base::OnceCallback<void(bool success,
@@ -567,8 +550,6 @@
       override;
   void OnStartLxdProgress(
       const vm_tools::cicerone::StartLxdProgressSignal& signal) override;
-  void OnFileWatchTriggered(
-      const vm_tools::cicerone::FileWatchTriggeredSignal& signal) override;
 
   // chromeos::NetworkStateHandlerObserver overrides:
   void ActiveNetworksChanged(const std::vector<const chromeos::NetworkState*>&
@@ -612,10 +593,6 @@
   // Can be called for testing to skip restart.
   void set_skip_restart_for_testing() { skip_restart_for_testing_ = true; }
   bool skip_restart_for_testing() { return skip_restart_for_testing_; }
-  void set_component_manager_load_error_for_testing(
-      component_updater::CrOSComponentManager::Error error) {
-    component_manager_load_error_for_testing_ = error;
-  }
 
   void SetCrostiniDialogStatus(DialogType dialog_type, bool open);
   // Returns true if the dialog is open.
@@ -864,9 +841,6 @@
   std::string owner_id_;
 
   bool skip_restart_for_testing_ = false;
-  component_updater::CrOSComponentManager::Error
-      component_manager_load_error_for_testing_ =
-          component_updater::CrOSComponentManager::Error::NONE;
 
   static bool is_dev_kvm_present_;
 
@@ -944,8 +918,6 @@
   base::ObserverList<ContainerStartedObserver> container_started_observers_;
   base::ObserverList<ContainerShutdownObserver> container_shutdown_observers_;
 
-  base::ObserverList<CrostiniFileChangeObserver> file_change_observers_;
-
   // Contains the types of crostini dialogs currently open. It is generally
   // invalid to show more than one. e.g. uninstalling and installing are
   // mutually exclusive.
@@ -977,6 +949,9 @@
                           chromeos::NetworkStateHandlerObserver>
       network_state_handler_observer_{this};
 
+  base::flat_map<guest_os::GuestId, guest_os::GuestOsMountProviderRegistry::Id>
+      mount_provider_ids_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<CrostiniManager> weak_ptr_factory_{this};
diff --git a/chrome/browser/ash/crostini/crostini_manager_unittest.cc b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
index 5076ef7a..413b133 100644
--- a/chrome/browser/ash/crostini/crostini_manager_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
@@ -44,11 +44,11 @@
 #include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "chromeos/dbus/anomaly_detector/anomaly_detector_client.h"
 #include "chromeos/dbus/anomaly_detector/fake_anomaly_detector_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/user_manager/scoped_user_manager.h"
@@ -1701,8 +1701,8 @@
 }
 
 TEST_F(CrostiniManagerRestartTest, RestartTriggersArcSideloadIfEnabled) {
-  chromeos::SessionManagerClient::InitializeFake();
-  chromeos::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(true);
+  ash::SessionManagerClient::InitializeFake();
+  ash::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(true);
 
   vm_tools::cicerone::ConfigureForArcSideloadResponse fake_response;
   fake_response.set_status(
@@ -1720,8 +1720,8 @@
 }
 
 TEST_F(CrostiniManagerRestartTest, RestartDoesNotTriggerArcSideloadIfDisabled) {
-  chromeos::SessionManagerClient::InitializeFake();
-  chromeos::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(false);
+  ash::SessionManagerClient::InitializeFake();
+  ash::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(false);
 
   vm_tools::cicerone::ConfigureForArcSideloadResponse fake_response;
   fake_response.set_status(
@@ -1748,29 +1748,6 @@
   // of shutting down chrome while a restart is running.
 }
 
-TEST_F(CrostiniManagerRestartTest, ComponentUpdateInProgress) {
-  crostini_manager()->set_component_manager_load_error_for_testing(
-      component_updater::CrOSComponentManager::Error::UPDATE_IN_PROGRESS);
-
-  crostini_manager()->RestartCrostini(
-      container_id(),
-      base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
-                     base::Unretained(this), run_loop()->QuitClosure()));
-
-  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(
-          &CrostiniManager::set_component_manager_load_error_for_testing,
-          base::Unretained(crostini_manager()),
-          component_updater::CrOSComponentManager::Error::NONE),
-      base::Seconds(3));
-
-  run_loop()->Run();
-
-  ExpectRestarterUmaCount(1);
-  ExpectCrostiniRestartResult(CrostiniResult::SUCCESS);
-}
-
 TEST_F(CrostiniManagerRestartTest, AllObservers) {
   TestRestartObserver observer2;
   int observer1_count = 0;
diff --git a/chrome/browser/ash/crostini/crostini_mount_provider.cc b/chrome/browser/ash/crostini/crostini_mount_provider.cc
new file mode 100644
index 0000000..349b62d
--- /dev/null
+++ b/chrome/browser/ash/crostini/crostini_mount_provider.cc
@@ -0,0 +1,70 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/crostini/crostini_mount_provider.h"
+#include "chrome/browser/ash/crostini/crostini_manager.h"
+#include "chrome/browser/ash/crostini/crostini_util.h"
+#include "chrome/browser/ash/guest_os/public/types.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
+
+namespace crostini {
+
+CrostiniMountProvider::CrostiniMountProvider(Profile* profile,
+                                             guest_os::GuestId container_id)
+    : profile_(profile), container_id_(container_id) {}
+
+CrostiniMountProvider::~CrostiniMountProvider() = default;
+
+// GuestOsMountProvider overrides
+Profile* CrostiniMountProvider::profile() {
+  return profile_;
+}
+
+std::string CrostiniMountProvider::DisplayName() {
+  return FormatForUi(container_id_);
+}
+
+guest_os::GuestId CrostiniMountProvider::GuestId() {
+  return container_id_;
+}
+
+guest_os::VmType CrostiniMountProvider::vm_type() {
+  return guest_os::VmType::TERMINA;
+}
+
+void CrostiniMountProvider::Prepare(PrepareCallback callback) {
+  auto* manager = CrostiniManager::GetForProfile(profile_);
+  manager->RestartCrostini(
+      container_id_,
+      base::BindOnce(&CrostiniMountProvider::OnRestarted,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void CrostiniMountProvider::OnRestarted(PrepareCallback callback,
+                                        CrostiniResult result) {
+  if (result != CrostiniResult::SUCCESS) {
+    std::move(callback).Run(false, 0, 0, base::FilePath());
+    return;
+  }
+  auto* manager = CrostiniManager::GetForProfile(profile_);
+  auto vm_info = manager->GetVmInfo(container_id_.vm_name);
+  auto container_info = manager->GetContainerInfo(container_id_);
+
+  std::move(callback).Run(
+      true, vm_info->info.cid(),
+      1234,  // TODO(b/217469540): Once the sftp changes in garcon land, change
+             // this to get the port from Garcon instead of being hardcoded for
+             // testing.
+      container_info->homedir);
+}
+
+std::unique_ptr<guest_os::GuestOsFileWatcher>
+CrostiniMountProvider::CreateFileWatcher(base::FilePath mount_path,
+                                         base::FilePath relative_path) {
+  return std::make_unique<guest_os::GuestOsFileWatcher>(
+      ash::ProfileHelper::GetUserIdHashFromProfile(profile_), container_id_,
+      std::move(mount_path), std::move(relative_path));
+}
+
+}  // namespace crostini
diff --git a/chrome/browser/ash/crostini/crostini_mount_provider.h b/chrome/browser/ash/crostini/crostini_mount_provider.h
new file mode 100644
index 0000000..58c5806
--- /dev/null
+++ b/chrome/browser/ash/crostini/crostini_mount_provider.h
@@ -0,0 +1,55 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_CROSTINI_CROSTINI_MOUNT_PROVIDER_H_
+#define CHROME_BROWSER_ASH_CROSTINI_CROSTINI_MOUNT_PROVIDER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ash/crostini/crostini_simple_types.h"
+#include "chrome/browser/ash/guest_os/public/guest_os_mount_provider.h"
+
+namespace guest_os {
+class GuestOsFileWatcher;
+}
+
+namespace crostini {
+
+class CrostiniMountProvider : public guest_os::GuestOsMountProvider {
+ public:
+  explicit CrostiniMountProvider(Profile* profile,
+                                 guest_os::GuestId container_id);
+
+  CrostiniMountProvider(const CrostiniMountProvider&) = delete;
+  CrostiniMountProvider& operator=(const CrostiniMountProvider&) = delete;
+
+  ~CrostiniMountProvider() override;
+
+  // GuestOsMountProvider overrides
+  Profile* profile() override;
+  std::string DisplayName() override;
+  guest_os::GuestId GuestId() override;
+  guest_os::VmType vm_type() override;
+
+  std::unique_ptr<guest_os::GuestOsFileWatcher> CreateFileWatcher(
+      base::FilePath mount_path,
+      base::FilePath relative_path) override;
+
+ protected:
+  // GuestOsMountProvider override. Make sure Crostini's running, then get
+  // address info e.g. cid and vsock port.
+  void Prepare(PrepareCallback callback) override;
+
+ private:
+  Profile* profile_;
+  guest_os::GuestId container_id_;
+
+  void OnRestarted(PrepareCallback callback, CrostiniResult result);
+
+  // Note: This should remain the last member so it'll be destroyed and
+  // invalidate its weak pointers before any other members are destroyed.
+  base::WeakPtrFactory<CrostiniMountProvider> weak_ptr_factory_{this};
+};
+}  // namespace crostini
+
+#endif  // CHROME_BROWSER_ASH_CROSTINI_CROSTINI_MOUNT_PROVIDER_H_
diff --git a/chrome/browser/ash/crostini/crostini_terminal_provider.cc b/chrome/browser/ash/crostini/crostini_terminal_provider.cc
index bb5a5ab..195b950 100644
--- a/chrome/browser/ash/crostini/crostini_terminal_provider.cc
+++ b/chrome/browser/ash/crostini/crostini_terminal_provider.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ash/crostini/crostini_terminal_provider.h"
 
-#include "base/strings/strcat.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
 
 namespace crostini {
@@ -15,11 +14,7 @@
 CrostiniTerminalProvider::~CrostiniTerminalProvider() = default;
 
 std::string CrostiniTerminalProvider::Label() {
-  if (container_id_.vm_name == kCrostiniDefaultVmName) {
-    return container_id_.container_name;
-  }
-  return base::StrCat(
-      {container_id_.vm_name, ":", container_id_.container_name});
+  return crostini::FormatForUi(container_id_);
 }
 
 absl::optional<guest_os::GuestId>
diff --git a/chrome/browser/ash/crostini/crostini_terminal_provider.h b/chrome/browser/ash/crostini/crostini_terminal_provider.h
index 6f5b9f36..67cd1c9a 100644
--- a/chrome/browser/ash/crostini/crostini_terminal_provider.h
+++ b/chrome/browser/ash/crostini/crostini_terminal_provider.h
@@ -19,8 +19,8 @@
   std::string Label() override;
 
   // TODO(b/233287586): While we're migrating some Crostini-specific code still
-  // needs a ContainerId. Eventually this should always be nullopt and then
-  // removed.
+  // needs a guest_os::GuestId. Eventually this should always be nullopt and
+  // then removed.
   absl::optional<guest_os::GuestId> CrostiniContainerId() override;
 
  private:
diff --git a/chrome/browser/ash/crostini/crostini_util.cc b/chrome/browser/ash/crostini/crostini_util.cc
index 844f8190..6d89c35 100644
--- a/chrome/browser/ash/crostini/crostini_util.cc
+++ b/chrome/browser/ash/crostini/crostini_util.cc
@@ -14,6 +14,7 @@
 #include "base/files/file_path.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
+#include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/crostini/crostini_features.h"
@@ -508,4 +509,11 @@
   return true;
 }
 
+std::string FormatForUi(guest_os::GuestId guest_id) {
+  if (guest_id.vm_name == kCrostiniDefaultVmName) {
+    return guest_id.container_name;
+  }
+  return base::StrCat({guest_id.vm_name, ":", guest_id.container_name});
+}
+
 }  // namespace crostini
diff --git a/chrome/browser/ash/crostini/crostini_util.h b/chrome/browser/ash/crostini/crostini_util.h
index 7ca08f7..aab2f31f 100644
--- a/chrome/browser/ash/crostini/crostini_util.h
+++ b/chrome/browser/ash/crostini/crostini_util.h
@@ -202,6 +202,9 @@
 // VM. Returns true if the VM should be stopped.
 bool ShouldStopVm(Profile* profile, const guest_os::GuestId& container_id);
 
+// Formats a container id the way most UI surfaces identify Crostini containers.
+std::string FormatForUi(guest_os::GuestId container_id);
+
 }  // namespace crostini
 
 #endif  // CHROME_BROWSER_ASH_CROSTINI_CROSTINI_UTIL_H_
diff --git a/chrome/browser/ash/crostini/termina_installer.cc b/chrome/browser/ash/crostini/termina_installer.cc
index be921f4d..70686a4 100644
--- a/chrome/browser/ash/crostini/termina_installer.cc
+++ b/chrome/browser/ash/crostini/termina_installer.cc
@@ -11,13 +11,13 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part_ash.h"
+#include "chrome/browser/component_updater/cros_component_manager.h"
 #include "chromeos/dbus/dlcservice/dlcservice.pb.h"
 #include "content/public/browser/network_service_instance.h"
 #include "services/network/public/cpp/network_connection_tracker.h"
@@ -25,20 +25,6 @@
 
 namespace crostini {
 
-namespace {
-
-const char kHistogram[] = "Crostini.InstallSource";
-
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class InstallSource {
-  Component = 0,
-  DLC = 1,
-  kMaxValue = DLC,
-};
-
-}  // namespace
-
 TerminaInstaller::TerminaInstaller() = default;
 TerminaInstaller::~TerminaInstaller() = default;
 
@@ -57,36 +43,9 @@
   auto* uninstall_result_ptr = ptr.get();
   auto remove_callback = base::BindOnce(
       [](std::unique_ptr<UninstallResult> ptr) {}, std::move(ptr));
+  RemoveComponentIfPresent(std::move(remove_callback), uninstall_result_ptr);
 
-  InstallDlc(
-      base::BindOnce(
-          [](base::WeakPtr<TerminaInstaller> weak_this,
-             base::OnceCallback<void(InstallResult)> callback,
-             bool is_initial_install, base::OnceClosure remove_callback,
-             UninstallResult* uninstall_result_ptr, InstallResult result) {
-            if (!weak_this)
-              return;
-
-            // Fallback logic for the transition to DLC.
-            // If we succeeded with DLC, we're good.
-            // If we're running the installer, we can show a useful error
-            // message. Otherwise, try and fall back to installing the
-            // cros-termina component.
-            if (is_initial_install || result == InstallResult::Success) {
-              // Delay removing cros-termina until here so as to avoid messing
-              // up the InstallComponent call below.
-              weak_this->RemoveComponentIfPresent(std::move(remove_callback),
-                                                  uninstall_result_ptr);
-              std::move(callback).Run(result);
-              return;
-            }
-            LOG(ERROR) << "Failed to install termina-dlc, falling back to "
-                          "cros-termina";
-            weak_this->InstallComponent(std::move(callback));
-          },
-          weak_ptr_factory_.GetWeakPtr(), std::move(callback),
-          is_initial_install, std::move(remove_callback), uninstall_result_ptr),
-      is_initial_install);
+  InstallDlc(std::move(callback), is_initial_install);
 }
 
 void TerminaInstaller::InstallDlc(
@@ -112,7 +71,6 @@
     response = InstallResult::Success;
     dlc_id_ = kCrostiniDlcName;
     termina_location_ = base::FilePath(result.root_path);
-    UMA_HISTOGRAM_ENUMERATION(kHistogram, InstallSource::DLC);
   } else if (is_initial_install && result.error == dlcservice::kErrorBusy) {
     base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
         FROM_HERE,
@@ -140,151 +98,6 @@
   std::move(callback).Run(response);
 }
 
-using UpdatePolicy = component_updater::CrOSComponentManager::UpdatePolicy;
-
-void TerminaInstaller::InstallComponent(
-    base::OnceCallback<void(InstallResult)> callback) {
-  scoped_refptr<component_updater::CrOSComponentManager> component_manager =
-      g_browser_process->platform_part()->cros_component_manager();
-
-  bool major_update_required =
-      component_manager->GetCompatiblePath(imageloader::kTerminaComponentName)
-          .empty();
-  bool is_offline = content::GetNetworkConnectionTracker()->IsOffline();
-
-  if (major_update_required) {
-    component_update_check_needed_ = false;
-    if (is_offline) {
-      LOG(ERROR) << "Need to load a major component update, but we're offline.";
-      std::move(callback).Run(InstallResult::Offline);
-      return;
-    }
-  }
-
-  UpdatePolicy update_policy;
-  if (component_update_check_needed_ && !is_offline) {
-    // Don't use kForce all the time because it generates traffic to
-    // ComponentUpdaterService. Also, it's only appropriate for minor version
-    // updates. Not major version incompatiblility.
-    update_policy = UpdatePolicy::kForce;
-  } else {
-    update_policy = UpdatePolicy::kDontForce;
-  }
-
-  component_manager->Load(
-      imageloader::kTerminaComponentName,
-      component_updater::CrOSComponentManager::MountPolicy::kMount,
-      update_policy,
-      base::BindOnce(&TerminaInstaller::OnInstallComponent,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback),
-                     update_policy == UpdatePolicy::kForce));
-}
-
-void TerminaInstaller::OnInstallComponent(
-    base::OnceCallback<void(InstallResult)> callback,
-    bool is_update_checked,
-    component_updater::CrOSComponentManager::Error error,
-    const base::FilePath& path) {
-  bool is_successful =
-      error == component_updater::CrOSComponentManager::Error::NONE;
-
-  if (is_successful) {
-    dlc_id_ = absl::nullopt;
-    termina_location_ = path;
-    UMA_HISTOGRAM_ENUMERATION(kHistogram, InstallSource::Component);
-  } else {
-    LOG(ERROR)
-        << "Failed to install the cros-termina component with error code: "
-        << static_cast<int>(error);
-
-    if (error ==
-        component_updater::CrOSComponentManager::Error::MOUNT_FAILURE) {
-      ReinstallComponent(std::move(callback));
-      return;
-    }
-    if (is_update_checked) {
-      scoped_refptr<component_updater::CrOSComponentManager> component_manager =
-          g_browser_process->platform_part()->cros_component_manager();
-      if (component_manager) {
-        // Try again, this time with no update checking. The reason we do this
-        // is that we may still be offline even when is_offline above was
-        // false. It's notoriously difficult to know when you're really
-        // connected to the Internet, and it's also possible to be unable to
-        // connect to a service like ComponentUpdaterService even when you are
-        // connected to the rest of the Internet.
-        UpdatePolicy update_policy = UpdatePolicy::kDontForce;
-
-        LOG(ERROR) << "Retrying cros-termina component load, no update check";
-        // Load the existing component on disk.
-        component_manager->Load(
-            imageloader::kTerminaComponentName,
-            component_updater::CrOSComponentManager::MountPolicy::kMount,
-            update_policy,
-            base::BindOnce(&TerminaInstaller::OnInstallComponent,
-                           weak_ptr_factory_.GetWeakPtr(), std::move(callback),
-                           false));
-        return;
-      }
-    }
-  }
-
-  if (is_successful && is_update_checked) {
-    VLOG(1) << "cros-termina update check successful.";
-    component_update_check_needed_ = false;
-  }
-  InstallResult result = InstallResult::Success;
-  if (!is_successful) {
-    if (error ==
-        component_updater::CrOSComponentManager::Error::UPDATE_IN_PROGRESS) {
-      // Something else triggered an update that we have to wait on. We don't
-      // know what, or when they will be finished, so just retry every 5 seconds
-      // until we get a different result.
-      base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE,
-          base::BindOnce(&TerminaInstaller::InstallComponent,
-                         weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
-          base::Seconds(5));
-      return;
-    } else {
-      result = InstallResult::Failure;
-    }
-  }
-
-  std::move(callback).Run(result);
-}
-
-void TerminaInstaller::ReinstallComponent(
-    base::OnceCallback<void(InstallResult)> callback) {
-  scoped_refptr<component_updater::CrOSComponentManager> component_manager =
-      g_browser_process->platform_part()->cros_component_manager();
-  if (component_manager->Unload(imageloader::kTerminaComponentName)) {
-    component_manager->Load(
-        imageloader::kTerminaComponentName,
-        component_updater::CrOSComponentManager::MountPolicy::kMount,
-        UpdatePolicy::kDontForce,
-        base::BindOnce(&TerminaInstaller::OnReinstallComponent,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(callback),
-                       false));
-  } else {
-    std::move(callback).Run(InstallResult::Failure);
-  }
-}
-
-void TerminaInstaller::OnReinstallComponent(
-    base::OnceCallback<void(InstallResult)> callback,
-    bool is_update_checked,
-    component_updater::CrOSComponentManager::Error error,
-    const base::FilePath& path) {
-  LOG(ERROR) << "Attempting to re-install cros-termina component.";
-  if (error != component_updater::CrOSComponentManager::Error::MOUNT_FAILURE) {
-    OnInstallComponent(std::move(callback), is_update_checked, error, path);
-    return;
-  }
-  // Give up with a permanent failure. The newly downloaded component failed to
-  // mount.
-  std::move(callback).Run(InstallResult::Failure);
-}
-
 void TerminaInstaller::Uninstall(base::OnceCallback<void(bool)> callback) {
   // Unset |termina_location_| now since it will become invalid at some point
   // soon.
diff --git a/chrome/browser/ash/crostini/termina_installer.h b/chrome/browser/ash/crostini/termina_installer.h
index 77bbc2eb..b89681d 100644
--- a/chrome/browser/ash/crostini/termina_installer.h
+++ b/chrome/browser/ash/crostini/termina_installer.h
@@ -10,15 +10,14 @@
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/component_updater/cros_component_manager.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace crostini {
 
-// This class is responsible for tracking which source the termina VM is
-// installed from (component updater, dlc service etc.) and ensuring that any
-// unneeded versions are cleaned up.
+// This class is responsible managing (un)installation of the Termina VM.
+// From M105, we require using DLC and will forcibly remove the component even
+// if loading DLC fails.
 class TerminaInstaller {
  public:
   TerminaInstaller();
@@ -48,11 +47,10 @@
   // check the result of this.
   //
   // |is_initial_install| should be set to true when this is called from the
-  // crostini installer, and false otherwise. This allows us to fall back to the
-  // cros-termina component if transitioning to DLC fails while still requiring
-  // it for new installs. In the future this may also allow us to force the DLC
-  // to be installed even on tethered connections during the install, as in this
-  // case we can expect the user already knows we will download things.
+  // crostini installer, and false otherwise. In the future this may allow us
+  // to force the DLC to be installed even on tethered connections during the
+  // install, as in this case we can expect the user already knows we will
+  // download things.
   void Install(base::OnceCallback<void(InstallResult)> callback,
                bool is_initial_install);
 
@@ -67,9 +65,8 @@
   // Get the id of the installed DLC, or nullopt if DLC is not being used.
   absl::optional<std::string> GetDlcId();
 
-  // Attempt to cancel a pending install. Note that neither DLC service nor
-  // component updater support this, but we have some retry logic that can be
-  // aborted.
+  // Attempt to cancel a pending install. The DLC service does not support
+  // this, but we have some retry logic that can be aborted.
   void Cancel();
 
  private:
@@ -79,18 +76,6 @@
                     bool is_initial_install,
                     const chromeos::DlcserviceClient::InstallResult& result);
 
-  void InstallComponent(base::OnceCallback<void(InstallResult)> callback);
-  void OnInstallComponent(base::OnceCallback<void(InstallResult)> callback,
-                          bool is_update_checked,
-                          component_updater::CrOSComponentManager::Error error,
-                          const base::FilePath& path);
-  void ReinstallComponent(base::OnceCallback<void(InstallResult)> callback);
-  void OnReinstallComponent(
-      base::OnceCallback<void(InstallResult)> callback,
-      bool is_update_checked,
-      component_updater::CrOSComponentManager::Error error,
-      const base::FilePath& path);
-
   void RemoveComponentIfPresent(base::OnceCallback<void()> callback,
                                 UninstallResult* result);
   void RemoveDlcIfPresent(base::OnceCallback<void()> callback,
@@ -100,11 +85,6 @@
   void OnUninstallFinished(base::OnceCallback<void(bool)> callback,
                            std::vector<UninstallResult> partial_results);
 
-  // Do we need to try to force a component update? We want to do this at most
-  // once per session, so this is initialized to true and unset whenever we
-  // successfully check for an update or we need to install a new major version.
-  bool component_update_check_needed_{true};
-
   absl::optional<base::FilePath> termina_location_{absl::nullopt};
   absl::optional<std::string> dlc_id_{};
   base::WeakPtrFactory<TerminaInstaller> weak_ptr_factory_{this};
diff --git a/chrome/browser/ash/crostini/termina_installer_unittest.cc b/chrome/browser/ash/crostini/termina_installer_unittest.cc
index 6abeebd..13a05e0 100644
--- a/chrome/browser/ash/crostini/termina_installer_unittest.cc
+++ b/chrome/browser/ash/crostini/termina_installer_unittest.cc
@@ -137,14 +137,6 @@
     EXPECT_EQ(termina_installer_.GetDlcId(), "termina-dlc");
   }
 
-  void ExpectComponentInstalled() {
-    EXPECT_TRUE(component_manager_->IsRegisteredMayBlock(
-        imageloader::kTerminaComponentName));
-    EXPECT_EQ(termina_installer_.GetInstallLocation(),
-              base::FilePath(component_mount_path_));
-    EXPECT_EQ(termina_installer_.GetDlcId(), absl::nullopt);
-  }
-
  protected:
   scoped_refptr<component_updater::FakeCrOSComponentManager> component_manager_;
   BrowserProcessPlatformPartTestApi browser_part_;
@@ -377,13 +369,14 @@
   fake_dlc_client_->set_install_error("An error");
   PrepareComponentForLoad();
 
-  termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess,
+  termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectFailure,
                                             base::Unretained(this)),
                              /*is_initial_install=*/false);
   run_loop_.Run();
 
   CheckDlcInstallCalledTimes(1);
-  ExpectComponentInstalled();
+  EXPECT_FALSE(component_manager_->IsRegisteredMayBlock(
+      imageloader::kTerminaComponentName));
 }
 
 TEST_F(TerminaInstallTest, InstallDlcFallbackIsCancelable) {
@@ -432,12 +425,13 @@
   network_connection_tracker->SetConnectionType(
       network::mojom::ConnectionType::CONNECTION_NONE);
 
-  termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess,
+  termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectOffline,
                                             base::Unretained(this)),
                              /*is_initial_install=*/false);
   run_loop_.Run();
 
-  ExpectComponentInstalled();
+  EXPECT_FALSE(component_manager_->IsRegisteredMayBlock(
+      imageloader::kTerminaComponentName));
 }
 
 }  // namespace crostini
diff --git a/chrome/browser/ash/customization/customization_document_unittest.cc b/chrome/browser/ash/customization/customization_document_unittest.cc
index 2b74d98..f01f09e 100644
--- a/chrome/browser/ash/customization/customization_document_unittest.cc
+++ b/chrome/browser/ash/customization/customization_document_unittest.cc
@@ -18,8 +18,8 @@
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/system/fake_statistics_provider.h"
diff --git a/chrome/browser/ash/dbus/ash_dbus_helper.cc b/chrome/browser/ash/dbus/ash_dbus_helper.cc
index 8b37f0d..9fd731c2 100644
--- a/chrome/browser/ash/dbus/ash_dbus_helper.cc
+++ b/chrome/browser/ash/dbus/ash_dbus_helper.cc
@@ -38,6 +38,11 @@
 #include "chromeos/ash/components/dbus/system_proxy/system_proxy_client.h"
 #include "chromeos/ash/components/dbus/typecd/typecd_client.h"
 #include "chromeos/ash/components/dbus/upstart/upstart_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/arc_quota_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/ash/components/hibernate/buildflags.h"  // ENABLE_HIBERNATE
 #include "chromeos/dbus/anomaly_detector/anomaly_detector_client.h"
 #include "chromeos/dbus/arc/arc_appfuse_provider_client.h"
@@ -63,11 +68,6 @@
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/u2f/u2f_client.h"
 #include "chromeos/dbus/update_engine/update_engine_client.h"
-#include "chromeos/dbus/userdataauth/arc_quota_client.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h"
-#include "chromeos/dbus/userdataauth/install_attributes_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h"
 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "device/bluetooth/floss/floss_dbus_manager.h"
@@ -153,7 +153,7 @@
   InitializeDBusClient<chromeos::PowerManagerClient>(bus);
   InitializeDBusClient<chromeos::ResourcedClient>(bus);
   InitializeDBusClient<SeneschalClient>(bus);
-  InitializeDBusClient<chromeos::SessionManagerClient>(bus);
+  InitializeDBusClient<SessionManagerClient>(bus);
   InitializeDBusClient<SpacedClient>(bus);
   InitializeDBusClient<SystemClockClient>(bus);
   InitializeDBusClient<SystemProxyClient>(bus);
@@ -229,7 +229,7 @@
   SystemProxyClient::Shutdown();
   SystemClockClient::Shutdown();
   SpacedClient::Shutdown();
-  chromeos::SessionManagerClient::Shutdown();
+  SessionManagerClient::Shutdown();
   SeneschalClient::Shutdown();
   chromeos::ResourcedClient::Shutdown();
   if (ash::features::IsRgbKeyboardEnabled()) {
diff --git a/chrome/browser/ash/dbus/fusebox_service_provider.cc b/chrome/browser/ash/dbus/fusebox_service_provider.cc
index b021a75..6d17afd 100644
--- a/chrome/browser/ash/dbus/fusebox_service_provider.cc
+++ b/chrome/browser/ash/dbus/fusebox_service_provider.cc
@@ -17,6 +17,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/task/bind_post_task.h"
 #include "chrome/browser/ash/file_manager/fileapi_util.h"
+#include "chrome/browser/ash/file_manager/fusebox_moniker.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/ash/components/dbus/fusebox/fusebox_reverse_client.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -49,10 +50,19 @@
   base::File::Error error_code;
   scoped_refptr<storage::FileSystemContext> fs_context;
   storage::FileSystemURL fs_url;
+
+  // is_moniker_root is used for the special case where
+  // fusebox::kMonikerFileSystemURL (also known as "dummy://moniker", with no
+  // trailing slash) is passed to ReadDir. There is no FileSystemURL linked to
+  // that fs_url_as_string (there is no base::Token in the string), so
+  // ParseCommonDBusMethodArguments (which returns a valid FileSystemURL on
+  // success) must return an error. However, ReadDir on "dummy://moniker"
+  // should succeed (but send an empty directory listing back over D-Bus).
+  bool is_moniker_root = false;
 };
 
 ParseResult::ParseResult(base::File::Error error_code_arg)
-    : error_code(error_code_arg), fs_context(), fs_url() {}
+    : error_code(error_code_arg) {}
 
 ParseResult::ParseResult(
     scoped_refptr<storage::FileSystemContext> fs_context_arg,
@@ -82,17 +92,43 @@
     return ParseResult(base::File::Error::FILE_ERROR_INVALID_URL);
   }
 
-  storage::FileSystemURL fs_url =
-      fs_context->CrackURLInFirstPartyContext(GURL(fs_url_as_string));
-  if (!fs_url.is_valid()) {
-    LOG(ERROR) << "Invalid FileSystemURL";
-    return ParseResult(base::File::Error::FILE_ERROR_INVALID_URL);
-  } else if (!fs_context->external_backend()->CanHandleType(fs_url.type())) {
+  storage::FileSystemURL fs_url;
+
+  // Intercept any moniker names and replace them by their linked target.
+  using ResultType =
+      file_manager::FuseBoxMoniker::ExtractTokenResult::ResultType;
+  auto moniker_parse_result =
+      file_manager::FuseBoxMoniker::ExtractToken(fs_url_as_string);
+  switch (moniker_parse_result.result_type) {
+    case ResultType::OK:
+      fs_url =
+          file_manager::FuseBoxMoniker::Resolve(moniker_parse_result.token);
+      if (!fs_url.is_valid()) {
+        LOG(ERROR) << "Unresolvable Moniker";
+        return ParseResult(base::File::Error::FILE_ERROR_NOT_FOUND);
+      }
+      break;
+    case ResultType::NOT_A_MONIKER_FS_URL:
+      fs_url = fs_context->CrackURLInFirstPartyContext(GURL(fs_url_as_string));
+      if (!fs_url.is_valid()) {
+        LOG(ERROR) << "Invalid FileSystemURL";
+        return ParseResult(base::File::Error::FILE_ERROR_INVALID_URL);
+      }
+      break;
+    case ResultType::MONIKER_FS_URL_BUT_ONLY_ROOT: {
+      ParseResult result = ParseResult(base::File::Error::FILE_ERROR_NOT_FOUND);
+      result.is_moniker_root = true;
+      return result;
+    }
+    case ResultType::MONIKER_FS_URL_BUT_NOT_WELL_FORMED:
+      return ParseResult(base::File::Error::FILE_ERROR_NOT_FOUND);
+  }
+
+  if (!fs_context->external_backend()->CanHandleType(fs_url.type())) {
     LOG(ERROR) << "Backend cannot handle "
                << storage::GetFileSystemTypeString(fs_url.type());
     return ParseResult(base::File::Error::FILE_ERROR_INVALID_URL);
   }
-
   return ParseResult(std::move(fs_context), std::move(fs_url));
 }
 
@@ -280,6 +316,15 @@
   }
 }
 
+void SendEmptyReverseReplyToReadDir(uint64_t cookie) {
+  constexpr bool has_more = false;
+  if (auto* client = FuseBoxReverseClient::Get(); client) {
+    client->ReplyToReadDir(cookie,
+                           static_cast<int32_t>(base::File::Error::FILE_OK),
+                           fusebox::DirEntryListProto(), has_more);
+  }
+}
+
 void ReplyToStat(scoped_refptr<storage::FileSystemContext> fs_context,
                  dbus::MethodCall* method_call,
                  dbus::ExportedObject::ResponseSender sender,
@@ -416,7 +461,8 @@
 
   dbus::MessageReader reader(method_call);
   auto common = ParseCommonDBusMethodArguments(&reader);
-  if (common.error_code != base::File::Error::FILE_OK) {
+  if ((common.error_code != base::File::Error::FILE_OK) &&
+      !common.is_moniker_root) {
     ReplyToReadDir(method_call, std::move(sender), common.error_code);
     return;
   }
@@ -431,9 +477,14 @@
 
   // The ReadDir D-Bus method call deserves a reply, even if we don't have any
   // directory entries yet. Those entries will be sent back separately, in
-  // batches, by CallReverseReplyToReadDir.
+  // batches, by CallReverseReplyToReadDir or SendEmptyReverseReplyToReadDir.
   ReplyToReadDir(method_call, std::move(sender), base::File::Error::FILE_OK);
 
+  if (common.is_moniker_root) {
+    SendEmptyReverseReplyToReadDir(cookie);
+    return;
+  }
+
   auto callback =
       base::BindPostTask(base::SequencedTaskRunnerHandle::Get(),
                          base::BindRepeating(&CallReverseReplyToReadDir,
diff --git a/chrome/browser/ash/dbus/proxy_resolution_service_provider_unittest.cc b/chrome/browser/ash/dbus/proxy_resolution_service_provider_unittest.cc
index 32a0633e..444a279 100644
--- a/chrome/browser/ash/dbus/proxy_resolution_service_provider_unittest.cc
+++ b/chrome/browser/ash/dbus/proxy_resolution_service_provider_unittest.cc
@@ -15,7 +15,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/ash/components/dbus/services/service_provider_test_helper.h"
 #include "chromeos/ash/components/dbus/system_proxy/system_proxy_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chrome/browser/ash/device_name/device_name_applier_impl_unittest.cc b/chrome/browser/ash/device_name/device_name_applier_impl_unittest.cc
index 401b7080..c0747bb 100644
--- a/chrome/browser/ash/device_name/device_name_applier_impl_unittest.cc
+++ b/chrome/browser/ash/device_name/device_name_applier_impl_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "chromeos/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/drive/drive_integration_service.cc b/chrome/browser/ash/drive/drive_integration_service.cc
index 690cb47b..d62ff55 100644
--- a/chrome/browser/ash/drive/drive_integration_service.cc
+++ b/chrome/browser/ash/drive/drive_integration_service.cc
@@ -601,6 +601,21 @@
         profile_, params->extension_id, std::move(port), std::move(host));
   }
 
+  const std::string GetMachineRootID() override {
+    if (!chromeos::features::IsDriveFsMirroringEnabled()) {
+      return "";
+    }
+    return profile_->GetPrefs()->GetString(
+        prefs::kDriveFsMirrorSyncMachineRootId);
+  }
+
+  void PersistMachineRootID(const std::string& id) override {
+    if (!chromeos::features::IsDriveFsMirroringEnabled()) {
+      return;
+    }
+    profile_->GetPrefs()->SetString(prefs::kDriveFsMirrorSyncMachineRootId, id);
+  }
+
   Profile* const profile_;
   drivefs::DriveFsHost::MountObserver* const mount_observer_;
 
diff --git a/chrome/browser/ash/drive/drive_integration_service_browsertest.cc b/chrome/browser/ash/drive/drive_integration_service_browsertest.cc
index 496e74a..c19d9e4f 100644
--- a/chrome/browser/ash/drive/drive_integration_service_browsertest.cc
+++ b/chrome/browser/ash/drive/drive_integration_service_browsertest.cc
@@ -12,6 +12,8 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/bind.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/ash/drive/drivefs_test_support.h"
 #include "chrome/browser/profiles/profile.h"
@@ -19,10 +21,13 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/drive/drive_pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "components/prefs/pref_test_utils.h"
 #include "content/public/test/browser_test.h"
 
 namespace drive {
 
+using ::base::test::RunClosure;
+
 class DriveIntegrationServiceBrowserTest : public InProcessBrowserTest {
  public:
   bool SetUpUserDataDirectory() override {
@@ -577,4 +582,34 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_F(DriveIntegrationBrowserTestWithMirrorSyncEnabled,
+                       MachineRootIDPersistedAndAvailable) {
+  ToggleMirrorSync(true);
+
+  // Ensure the initial machine root ID is unset.
+  EXPECT_EQ(browser()->profile()->GetPrefs()->GetString(
+                prefs::kDriveFsMirrorSyncMachineRootId),
+            "");
+
+  // Invoke the delegate method to persist the machine root ID and wait for the
+  // prefs key to change to the expected value.
+  drivefs::FakeDriveFs* fake = GetFakeDriveFsForProfile(browser()->profile());
+  fake->delegate()->PersistMachineRootID("test-machine-id");
+  WaitForPrefValue(browser()->profile()->GetPrefs(),
+                   prefs::kDriveFsMirrorSyncMachineRootId,
+                   base::Value("test-machine-id"));
+
+  // Setup the callback for the GetMachineRootID method to assert it gets run
+  // with the "test-machine-id".
+  base::RunLoop run_loop;
+  base::MockOnceCallback<void(const std::string&)> machine_root_id_callback;
+  EXPECT_CALL(machine_root_id_callback, Run("test-machine-id"))
+      .WillOnce(RunClosure(run_loop.QuitClosure()));
+
+  // Kick off the GetMachineRootID method and wait for it to return
+  // successfully.
+  fake->delegate()->GetMachineRootID(machine_root_id_callback.Get());
+  run_loop.Run();
+}
+
 }  // namespace drive
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 7cba2f9..88b70eb 100644
--- a/chrome/browser/ash/file_manager/app_service_file_tasks.cc
+++ b/chrome/browser/ash/file_manager/app_service_file_tasks.cc
@@ -212,7 +212,7 @@
     result_list->push_back(FullTaskDescriptor(
         TaskDescriptor(launch_entry.app_id, GetTaskType(app_type),
                        launch_entry.activity_name),
-        launch_entry.activity_label, Verb::VERB_OPEN_WITH, icon_url,
+        launch_entry.activity_label, Verb::VERB_NONE, icon_url,
         /* is_default=*/false,
         // TODO(petermarshall): Handle the rest of the logic from FindWebTasks()
         // e.g. prioritise non-generic handlers.
diff --git a/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc b/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc
index f1add77..6e3c6c6 100644
--- a/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc
+++ b/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc
@@ -491,7 +491,7 @@
   EXPECT_EQ("Baz", tasks[0].task_title);
   EXPECT_TRUE(tasks[0].is_generic_file_handler);
   EXPECT_TRUE(tasks[0].is_file_extension_match);
-  EXPECT_EQ(Verb::VERB_OPEN_WITH, tasks[0].task_verb);
+  EXPECT_EQ(Verb::VERB_NONE, tasks[0].task_verb);
 }
 
 // File extension matches with bar, but there is a generic * type as well,
@@ -507,7 +507,7 @@
   EXPECT_EQ("Baz", tasks[0].task_title);
   EXPECT_TRUE(tasks[0].is_generic_file_handler);
   EXPECT_TRUE(tasks[0].is_file_extension_match);
-  EXPECT_EQ(Verb::VERB_OPEN_WITH, tasks[0].task_verb);
+  EXPECT_EQ(Verb::VERB_NONE, tasks[0].task_verb);
 }
 
 // Check that we can get web apps and Chrome apps in the same call.
@@ -539,7 +539,7 @@
   EXPECT_EQ("Baz", tasks[0].task_title);
   EXPECT_FALSE(tasks[0].is_generic_file_handler);
   EXPECT_FALSE(tasks[0].is_file_extension_match);
-  EXPECT_EQ(Verb::VERB_OPEN_WITH, tasks[0].task_verb);
+  EXPECT_EQ(Verb::VERB_NONE, tasks[0].task_verb);
 }
 
 TEST_F(AppServiceFileTasksTestEnabled, FindAppServiceChromeAppWithVerbs) {
@@ -555,7 +555,7 @@
   EXPECT_EQ("plain_text", tasks[0].task_descriptor.action_id);
   EXPECT_FALSE(tasks[0].is_generic_file_handler);
   EXPECT_FALSE(tasks[0].is_file_extension_match);
-  EXPECT_EQ(Verb::VERB_OPEN_WITH, tasks[0].task_verb);
+  EXPECT_EQ(Verb::VERB_NONE, tasks[0].task_verb);
 }
 
 TEST_F(AppServiceFileTasksTestEnabled, FindAppServiceChromeAppWithVerbs_Html) {
@@ -570,7 +570,7 @@
   EXPECT_EQ("html_handler", tasks[0].task_descriptor.action_id);
   EXPECT_FALSE(tasks[0].is_generic_file_handler);
   EXPECT_FALSE(tasks[0].is_file_extension_match);
-  EXPECT_EQ(Verb::VERB_OPEN_WITH, tasks[0].task_verb);
+  EXPECT_EQ(Verb::VERB_NONE, tasks[0].task_verb);
 }
 
 TEST_F(AppServiceFileTasksTestEnabled,
@@ -586,7 +586,7 @@
   EXPECT_EQ("any_with_directories", tasks[0].task_descriptor.action_id);
   EXPECT_TRUE(tasks[0].is_generic_file_handler);
   EXPECT_FALSE(tasks[0].is_file_extension_match);
-  EXPECT_EQ(Verb::VERB_OPEN_WITH, tasks[0].task_verb);
+  EXPECT_EQ(Verb::VERB_NONE, tasks[0].task_verb);
 }
 
 TEST_F(AppServiceFileTasksTestEnabled, FindAppServiceExtension) {
diff --git a/chrome/browser/ash/file_manager/empty_trash_io_task.cc b/chrome/browser/ash/file_manager/empty_trash_io_task.cc
index 94e207f5..d93d3d8 100644
--- a/chrome/browser/ash/file_manager/empty_trash_io_task.cc
+++ b/chrome/browser/ash/file_manager/empty_trash_io_task.cc
@@ -4,19 +4,39 @@
 
 #include "chrome/browser/ash/file_manager/empty_trash_io_task.h"
 
+#include <memory>
+
 #include "base/callback.h"
+#include "base/task/bind_post_task.h"
+#include "chrome/browser/ash/file_manager/io_task_util.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace file_manager::io_task {
 
+namespace {
+
+storage::FileSystemOperationRunner::OperationID
+StartRemoveRecursivelyOnIOThread(
+    scoped_refptr<storage::FileSystemContext> file_system_context,
+    const storage::FileSystemURL url,
+    storage::FileSystemOperationRunner::StatusCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  return file_system_context->operation_runner()->Remove(
+      url, /*recursive=*/true, std::move(callback));
+}
+
+}  // namespace
+
 EmptyTrashIOTask::EmptyTrashIOTask(
     blink::StorageKey storage_key,
     Profile* profile,
-    scoped_refptr<storage::FileSystemContext> file_system_context)
+    scoped_refptr<storage::FileSystemContext> file_system_context,
+    base::FilePath base_path)
     : file_system_context_(file_system_context),
       storage_key_(storage_key),
-      profile_(profile) {
+      profile_(profile),
+      base_path_(base_path) {
   progress_.state = State::kQueued;
   progress_.type = OperationType::kEmptyTrash;
   progress_.bytes_transferred = 0;
@@ -41,6 +61,75 @@
                                IOTask::CompleteCallback complete_callback) {
   progress_callback_ = std::move(progress_callback);
   complete_callback_ = std::move(complete_callback);
+
+  enabled_trash_locations_ =
+      GenerateEnabledTrashLocationsForProfile(profile_, base_path_);
+  progress_.state = State::kInProgress;
+
+  TrashPathsMap::const_iterator it = enabled_trash_locations_.cbegin();
+  if (it == enabled_trash_locations_.end()) {
+    Complete(State::kSuccess);
+    return;
+  }
+
+  RemoveTrashDirectory(it);
+}
+
+void EmptyTrashIOTask::RemoveTrashDirectory(
+    TrashPathsMap::const_iterator& trash_location) {
+  const base::FilePath trash_path =
+      trash_location->second.trash_parent_path.Append(
+          trash_location->second.relative_folder_path);
+  const storage::FileSystemURL trash_url =
+      file_system_context_->CreateCrackedFileSystemURL(
+          storage_key_, storage::FileSystemType::kFileSystemTypeLocal,
+          trash_path);
+
+  progress_.outputs.emplace_back(trash_url, absl::nullopt);
+
+  auto complete_callback = base::BindPostTask(
+      base::SequencedTaskRunnerHandle::Get(),
+      base::BindOnce(&EmptyTrashIOTask::OnRemoveTrashDirectory,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     base::OwnedRef(trash_location)));
+
+  content::GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult(
+      FROM_HERE,
+      base::BindOnce(&StartRemoveRecursivelyOnIOThread, file_system_context_,
+                     trash_url, std::move(complete_callback)),
+      base::BindOnce(&EmptyTrashIOTask::SetCurrentOperationID,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void EmptyTrashIOTask::OnRemoveTrashDirectory(TrashPathsMap::const_iterator& it,
+                                              base::File::Error status) {
+  progress_.outputs[progress_.outputs.size() - 1].error = status;
+  if (status != base::File::FILE_OK) {
+    LOG(ERROR) << "Failed to remove trash directory " << status;
+    Complete(State::kError);
+    return;
+  }
+  it++;
+  if (it == enabled_trash_locations_.end()) {
+    Complete(State::kSuccess);
+    return;
+  }
+
+  RemoveTrashDirectory(it);
+}
+
+// Calls the completion callback for the task. `progress_` should not be
+// accessed after calling this.
+void EmptyTrashIOTask::Complete(State state) {
+  progress_.state = state;
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(complete_callback_), std::move(progress_)));
+}
+
+void EmptyTrashIOTask::SetCurrentOperationID(
+    storage::FileSystemOperationRunner::OperationID id) {
+  operation_id_.emplace(id);
 }
 
 void EmptyTrashIOTask::Cancel() {
diff --git a/chrome/browser/ash/file_manager/empty_trash_io_task.h b/chrome/browser/ash/file_manager/empty_trash_io_task.h
index 87b8ee2..1818410 100644
--- a/chrome/browser/ash/file_manager/empty_trash_io_task.h
+++ b/chrome/browser/ash/file_manager/empty_trash_io_task.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/file_manager/io_task.h"
+#include "chrome/browser/ash/file_manager/trash_common_util.h"
 #include "storage/browser/file_system/file_system_context.h"
 #include "storage/browser/file_system/file_system_operation_runner.h"
 #include "storage/browser/file_system/file_system_url.h"
@@ -23,6 +24,10 @@
 // This class represents a task to completely empty the trash folder. An empty
 // trash task will recursively iterate over the contents of the "files" and
 // "info" subdirectories and remove all the files within.
+// The "Empty Trash" action happens for all enabled trash locations, not just
+// for one location. Therefore no sources are supplied they are identified and
+// emptied accordingly. The locations which are enabled and are emptied are
+// available on the outputs of the `ProgressStatus`.
 //
 // This follows the XDG specification
 // https://specifications.freedesktop.org/trash-spec/trashspec-1.0.html
@@ -31,7 +36,9 @@
   EmptyTrashIOTask(
       blink::StorageKey storage_key,
       Profile* profile,
-      scoped_refptr<storage::FileSystemContext> file_system_context);
+      scoped_refptr<storage::FileSystemContext> file_system_context,
+      base::FilePath base_path);
+
   ~EmptyTrashIOTask() override;
 
   // Starts empty trash trask.
@@ -40,6 +47,21 @@
   void Cancel() override;
 
  private:
+  // Removes the entire trash directory (e.g. .Trash) recursively. It only
+  // iterates over the enabled trash locations.
+  void RemoveTrashDirectory(TrashPathsMap::const_iterator& trash_location);
+
+  // After removing the trash directory, continue iterating until there are no
+  // more enabled trash directories left.
+  void OnRemoveTrashDirectory(TrashPathsMap::const_iterator& it,
+                              base::File::Error status);
+
+  // Finish up and invoke the `complete_callback_`.
+  void Complete(State state);
+
+  void SetCurrentOperationID(
+      storage::FileSystemOperationRunner::OperationID id);
+
   scoped_refptr<storage::FileSystemContext> file_system_context_;
 
   // Storage key used to construct the storage::FileSystemURLs that represent
@@ -48,6 +70,9 @@
 
   raw_ptr<Profile> profile_;
 
+  // A map containing paths which are enabled for trashing.
+  TrashPathsMap enabled_trash_locations_;
+
   // Stores the id of the restore operation if one is in progress. Used to stop
   // the empty trash operation.
   absl::optional<storage::FileSystemOperationRunner::OperationID> operation_id_;
@@ -55,6 +80,11 @@
   ProgressCallback progress_callback_;
   CompleteCallback complete_callback_;
 
+  // Represents the parent path that all the source URLs descend from. Used to
+  // work around the fact `FileSystemOperationRunner` requires relative paths
+  // only in testing.
+  const base::FilePath base_path_;
+
   base::WeakPtrFactory<EmptyTrashIOTask> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ash/file_manager/empty_trash_io_task_unittest.cc b/chrome/browser/ash/file_manager/empty_trash_io_task_unittest.cc
new file mode 100644
index 0000000..a06ab68
--- /dev/null
+++ b/chrome/browser/ash/file_manager/empty_trash_io_task_unittest.cc
@@ -0,0 +1,89 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/file_manager/empty_trash_io_task.h"
+
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/rand_util.h"
+#include "base/run_loop.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "chrome/browser/ash/file_manager/path_util.h"
+#include "chrome/browser/ash/file_manager/restore_io_task.h"
+#include "chrome/browser/ash/file_manager/trash_unittest_base.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/browser_task_environment.h"
+#include "storage/browser/file_system/file_system_context.h"
+#include "storage/browser/file_system/file_system_url.h"
+#include "storage/browser/test/test_file_system_context.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
+
+namespace file_manager::io_task {
+namespace {
+
+using ::base::test::RunClosure;
+using ::testing::AllOf;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::IsEmpty;
+
+// Matcher that only verifies the `base::FilePath`  on the
+// `storage::FileSystemURL` in a supplied `std::vector<storage::FileSystemURL>`.
+// ignoring the `error` fields. The supplied `arg` should be a
+// `std::vector<storage::FileSystemURL>` to match against.
+MATCHER_P(EntryStatusPaths, matcher, "") {
+  std::vector<base::FilePath> paths;
+  for (const auto& status : arg) {
+    paths.push_back(status.url.path());
+  }
+  return testing::ExplainMatchResult(matcher, paths, result_listener);
+}
+
+class EmptyTrashIOTaskTest : public TrashBaseTest {
+ public:
+  EmptyTrashIOTaskTest() = default;
+
+  EmptyTrashIOTaskTest(const EmptyTrashIOTaskTest&) = delete;
+  EmptyTrashIOTaskTest& operator=(const EmptyTrashIOTaskTest&) = delete;
+};
+
+TEST_F(EmptyTrashIOTaskTest, EnabledTrashDirsAreTrashed) {
+  base::FilePath my_files_trash_dir = my_files_dir_.Append(kTrashFolderName);
+  base::FilePath downloads_trash_dir = downloads_dir_.Append(kTrashFolderName);
+  base::FilePath crostini_trash_dir =
+      crostini_dir_.Append(".local/share/Trash");
+  ASSERT_TRUE(EnsureTrashDirectorySetup(my_files_trash_dir));
+  ASSERT_TRUE(EnsureTrashDirectorySetup(downloads_trash_dir));
+  ASSERT_TRUE(EnsureTrashDirectorySetup(crostini_trash_dir));
+
+  base::RunLoop run_loop;
+  base::MockRepeatingCallback<void(const ProgressStatus&)> progress_callback;
+  base::MockOnceCallback<void(ProgressStatus)> complete_callback;
+
+  // We should get one complete callback to be invoked once with a success
+  // message and the list of outputs containing the enabled trash locations.
+  EXPECT_CALL(complete_callback,
+              Run(AllOf(Field(&ProgressStatus::state, State::kSuccess),
+                        Field(&ProgressStatus::sources, IsEmpty()),
+                        Field(&ProgressStatus::outputs,
+                              EntryStatusPaths(ElementsAre(
+                                  my_files_trash_dir, downloads_trash_dir,
+                                  crostini_trash_dir))))))
+      .WillOnce(RunClosure(run_loop.QuitClosure()));
+
+  EmptyTrashIOTask task(kTestStorageKey, profile_.get(), file_system_context_,
+                        temp_dir_.GetPath());
+  task.Execute(progress_callback.Get(), complete_callback.Get());
+  run_loop.Run();
+
+  ASSERT_FALSE(base::PathExists(my_files_trash_dir));
+  ASSERT_FALSE(base::PathExists(downloads_trash_dir));
+  ASSERT_FALSE(base::PathExists(crostini_trash_dir));
+}
+
+}  // namespace
+}  // namespace file_manager::io_task
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
index 8631f2f..80052684 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -1730,6 +1730,12 @@
     std::move(callback).Run(true, cid_, 1234, base::FilePath());
   }
 
+  std::unique_ptr<guest_os::GuestOsFileWatcher> CreateFileWatcher(
+      base::FilePath mount_path,
+      base::FilePath relative_path) override {
+    return nullptr;
+  }
+
   guest_os::VmType vm_type() override { return vm_type_; }
 
   int cid_;
@@ -3190,6 +3196,9 @@
     auto* canMount = value.GetDict().Find("canMount");
     auto* vmType = value.GetDict().FindString("vmType");
     CHECK(displayName != nullptr);
+    // TODO(davidmunro): Merge with in-constructor derivation.
+    // auto id = guest_os::GuestId(guest_os::VmType::UNKNOWN, *displayName,
+    // *displayName);
     auto* registry = guest_os::GuestOsService::GetForProfile(profile())
                          ->MountProviderRegistry();
     auto id = registry->Register(std::make_unique<MockGuestOsMountProvider>(
diff --git a/chrome/browser/ash/file_manager/file_manager_jstest.cc b/chrome/browser/ash/file_manager/file_manager_jstest.cc
index 598d07f4..71ee153 100644
--- a/chrome/browser/ash/file_manager/file_manager_jstest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_jstest.cc
@@ -22,283 +22,279 @@
 };
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ActionsModelTest) {
-  RunTestURL("foreground/js/actions_model_unittest.m_gen.html");
+  RunTestURL("foreground/js/actions_model_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ActionsSubmenuTest) {
-  RunTestURL("foreground/js/ui/actions_submenu_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/actions_submenu_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, Breadcrumb) {
-  RunTestURL("foreground/js/ui/breadcrumb_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/breadcrumb_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, BannerController) {
-  RunTestURL("foreground/js/banner_controller_unittest.m_gen.html");
+  RunTestURL("foreground/js/banner_controller_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, BannerUtil) {
-  RunTestURL("foreground/js/banner_util_unittest.m_gen.html");
+  RunTestURL("foreground/js/banner_util_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, BannerEducational) {
-  RunTestURL("foreground/js/ui/banners/educational_banner_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/banners/educational_banner_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, BannerState) {
-  RunTestURL("foreground/js/ui/banners/state_banner_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/banners/state_banner_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, BannerWarning) {
-  RunTestURL("foreground/js/ui/banners/warning_banner_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/banners/warning_banner_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ContentMetadataProvider) {
-  RunTestURL(
-      "foreground/js/metadata/content_metadata_provider_unittest.m_gen.html");
+  RunTestURL("foreground/js/metadata/content_metadata_provider_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, Crostini) {
-  RunTestURL("background/js/crostini_unittest.m_gen.html");
+  RunTestURL("background/js/crostini_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, DeviceHandlerTest) {
-  RunTestURL("background/js/device_handler_unittest.m_gen.html");
+  RunTestURL("background/js/device_handler_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, DirectoryContentsTest) {
-  RunTestURL("foreground/js/directory_contents_unittest.m_gen.html");
+  RunTestURL("foreground/js/directory_contents_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, DirectoryModelTest) {
-  RunTestURL("foreground/js/directory_model_unittest.m_gen.html");
+  RunTestURL("foreground/js/directory_model_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, DirectoryTreeTest) {
-  RunTestURL("foreground/js/ui/directory_tree_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/directory_tree_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, DriveSyncHandlerTest) {
-  RunTestURL("background/js/drive_sync_handler_unittest.m_gen.html");
+  RunTestURL("background/js/drive_sync_handler_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, DuplicateFinderTest) {
-  RunTestURL("background/js/duplicate_finder_unittest.m_gen.html");
+  RunTestURL("background/js/duplicate_finder_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ExifParser) {
-  RunTestURL("foreground/js/metadata/exif_parser_unittest.m_gen.html");
+  RunTestURL("foreground/js/metadata/exif_parser_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ExternalMetadataProvider) {
-  RunTestURL(
-      "foreground/js/metadata/external_metadata_provider_unittest.m_gen.html");
+  RunTestURL("foreground/js/metadata/external_metadata_provider_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileListModel) {
-  RunTestURL("foreground/js/file_list_model_unittest.m_gen.html");
+  RunTestURL("foreground/js/file_list_model_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileListSelectionModelTest) {
-  RunTestURL("foreground/js/ui/file_list_selection_model_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/file_list_selection_model_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileManagerCommandsTest) {
-  RunTestURL("foreground/js/file_manager_commands_unittest.m_gen.html");
+  RunTestURL("foreground/js/file_manager_commands_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileManagerDialogBaseTest) {
-  RunTestURL("foreground/js/ui/file_manager_dialog_base_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/file_manager_dialog_base_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileOperationHandlerTest) {
-  RunTestURL("background/js/file_operation_handler_unittest.m_gen.html");
+  RunTestURL("background/js/file_operation_handler_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileOperationManagerTest) {
-  RunTestURL("background/js/file_operation_manager_unittest.m_gen.html");
+  RunTestURL("background/js/file_operation_manager_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FilesAppEntryTypes) {
-  RunTestURL("common/js/files_app_entry_types_unittest.m_gen.html");
+  RunTestURL("common/js/files_app_entry_types_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FilesDisplayPanel) {
-  RunTestURL("foreground/elements/files_xf_elements_unittest.m_gen.html");
+  RunTestURL("foreground/elements/files_xf_elements_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FilesPasswordDialog) {
-  RunTestURL("foreground/elements/files_password_dialog_unittest.m_gen.html");
+  RunTestURL("foreground/elements/files_password_dialog_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FilesToast) {
-  RunTestURL("foreground/elements/files_toast_unittest.m_gen.html");
+  RunTestURL("foreground/elements/files_toast_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FilesToolTip) {
-  RunTestURL("foreground/elements/files_tooltip_unittest.m_gen.html");
+  RunTestURL("foreground/elements/files_tooltip_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileSystemMetadataProvider) {
   RunTestURL(
       "foreground/js/metadata/"
-      "file_system_metadata_provider_unittest.m_gen.html");
+      "file_system_metadata_provider_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileTableList) {
-  RunTestURL("foreground/js/ui/file_table_list_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/file_table_list_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileTableTest) {
-  RunTestURL("foreground/js/ui/file_table_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/file_table_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileTapHandler) {
-  RunTestURL("foreground/js/ui/file_tap_handler_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/file_tap_handler_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileTasks) {
-  RunTestURL("foreground/js/file_tasks_unittest.m_gen.html");
+  RunTestURL("foreground/js/file_tasks_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileTransferController) {
-  RunTestURL("foreground/js/file_transfer_controller_unittest.m_gen.html");
+  RunTestURL("foreground/js/file_transfer_controller_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileTypeFiltersController) {
-  RunTestURL("foreground/js/file_type_filters_controller_unittest.m_gen.html");
+  RunTestURL("foreground/js/file_type_filters_controller_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileType) {
-  RunTestURL("common/js/file_type_unittest.m_gen.html");
+  RunTestURL("common/js/file_type_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FilteredVolumeManagerTest) {
-  RunTestURL("common/js/filtered_volume_manager_unittest.m_gen.html");
+  RunTestURL("common/js/filtered_volume_manager_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(CanvasFileManagerJsTest, ImageOrientation) {
-  RunTestURL("foreground/js/metadata/image_orientation_unittest.m_gen.html");
+  RunTestURL("foreground/js/metadata/image_orientation_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ImportControllerTest) {
-  RunTestURL("foreground/js/import_controller_unittest.m_gen.html");
+  RunTestURL("foreground/js/import_controller_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ImporterCommonTest) {
-  RunTestURL("common/js/importer_common_unittest.m_gen.html");
+  RunTestURL("common/js/importer_common_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ImportHistoryTest) {
-  RunTestURL("background/js/import_history_unittest.m_gen.html");
+  RunTestURL("background/js/import_history_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, InstallLinuxPackageDialogTest) {
-  RunTestURL(
-      "foreground/js/ui/install_linux_package_dialog_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/install_linux_package_dialog_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ListThumbnailLoader) {
-  RunTestURL("foreground/js/list_thumbnail_loader_unittest.m_gen.html");
+  RunTestURL("foreground/js/list_thumbnail_loader_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, LRUCacheTest) {
-  RunTestURL("common/js/lru_cache_unittest.m_gen.html");
+  RunTestURL("common/js/lru_cache_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MediaImportHandlerTest) {
-  RunTestURL("background/js/media_import_handler_unittest.m_gen.html");
+  RunTestURL("background/js/media_import_handler_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MediaScannerTest) {
-  RunTestURL("background/js/media_scanner_unittest.m_gen.html");
+  RunTestURL("background/js/media_scanner_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MetadataCacheItem) {
-  RunTestURL("foreground/js/metadata/metadata_cache_item_unittest.m_gen.html");
+  RunTestURL("foreground/js/metadata/metadata_cache_item_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MetadataCacheSet) {
-  RunTestURL("foreground/js/metadata/metadata_cache_set_unittest.m_gen.html");
+  RunTestURL("foreground/js/metadata/metadata_cache_set_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MetadataModel) {
-  RunTestURL("foreground/js/metadata/metadata_model_unittest.m_gen.html");
+  RunTestURL("foreground/js/metadata/metadata_model_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MetadataProxyTest) {
-  RunTestURL("background/js/metadata_proxy_unittest.m_gen.html");
+  RunTestURL("background/js/metadata_proxy_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MountMetricsTest) {
-  RunTestURL("background/js/mount_metrics_unittest.m_gen.html");
+  RunTestURL("background/js/mount_metrics_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MultiMenu) {
-  RunTestURL("foreground/js/ui/multi_menu_unittest.m_gen.html");
+  RunTestURL("foreground/js/ui/multi_menu_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MultiMetadataProvider) {
-  RunTestURL(
-      "foreground/js/metadata/multi_metadata_provider_unittest.m_gen.html");
+  RunTestURL("foreground/js/metadata/multi_metadata_provider_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, NavigationListModelTest) {
-  RunTestURL("foreground/js/navigation_list_model_unittest.m_gen.html");
+  RunTestURL("foreground/js/navigation_list_model_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, PathComponent) {
-  RunTestURL("foreground/js/path_component_unittest.m_gen.html");
+  RunTestURL("foreground/js/path_component_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ProvidersModel) {
-  RunTestURL("foreground/js/providers_model_unittest.m_gen.html");
+  RunTestURL("foreground/js/providers_model_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, Splitter) {
-  RunTestURL("foreground/js/ui/splitter_unittest_gen.html");
+  RunTestURL("foreground/js/ui/splitter_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, SpinnerController) {
-  RunTestURL("foreground/js/spinner_controller_unittest.m_gen.html");
+  RunTestURL("foreground/js/spinner_controller_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, StorageAdapter) {
-  RunTestURL("common/js/storage_adapter_unittest.m_gen.html");
+  RunTestURL("common/js/storage_adapter_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, TaskController) {
-  RunTestURL("foreground/js/task_controller_unittest.m_gen.html");
+  RunTestURL("foreground/js/task_controller_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, TaskQueueTest) {
-  RunTestURL("background/js/task_queue_unittest.m_gen.html");
+  RunTestURL("background/js/task_queue_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ThumbnailLoader) {
-  RunTestURL("foreground/js/thumbnail_loader_unittest.m_gen.html");
+  RunTestURL("foreground/js/thumbnail_loader_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ThumbnailModel) {
-  RunTestURL("foreground/js/metadata/thumbnail_model_unittest.m_gen.html");
+  RunTestURL("foreground/js/metadata/thumbnail_model_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, Trash) {
-  RunTestURL("background/js/trash_unittest.m_gen.html");
+  RunTestURL("background/js/trash_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, UtilTest) {
-  RunTestURL("common/js/util_unittest.m_gen.html");
+  RunTestURL("common/js/util_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, VolumeManagerTest) {
-  RunTestURL("background/js/volume_manager_unittest.m_gen.html");
+  RunTestURL("background/js/volume_manager_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, VolumeManagerTypesTest) {
-  RunTestURL("common/js/volume_manager_types_unittest.m_gen.html");
+  RunTestURL("common/js/volume_manager_types_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, RecentDateBucketTest) {
-  RunTestURL("common/js/recent_date_bucket_unittest.m_gen.html");
+  RunTestURL("common/js/recent_date_bucket_unittest.js");
 }
diff --git a/chrome/browser/ash/file_manager/file_manager_jstest_base.cc b/chrome/browser/ash/file_manager/file_manager_jstest_base.cc
index 9bc3ea97..12c420c7 100644
--- a/chrome/browser/ash/file_manager/file_manager_jstest_base.cc
+++ b/chrome/browser/ash/file_manager/file_manager_jstest_base.cc
@@ -29,12 +29,6 @@
 
 namespace {
 
-base::FilePath GetGenRoot() {
-  base::FilePath executable_path;
-  CHECK(base::PathService::Get(base::DIR_EXE, &executable_path));
-  return executable_path.AppendASCII("gen");
-}
-
 // WebUIProvider to attach the URLDataSource for the test URL during tests.
 // Used to start the unittest from a chrome:// URL which allows unittest files
 // (HTML/JS/CSS) to load other resources from WebUI URLs chrome://*.
@@ -60,15 +54,13 @@
         network::mojom::CSPDirectiveName::ScriptSrc,
         "script-src chrome://resources chrome://webui-test "
         "'self' chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj "
-        "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp "
-        "'unsafe-inline'; ");
+        "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp ");
 
     source->OverrideContentSecurityPolicy(
         network::mojom::CSPDirectiveName::ScriptSrcElem,
         "script-src chrome://resources chrome://webui-test "
         "'self' chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj "
-        "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp "
-        "'unsafe-inline'; ");
+        "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp ; ");
 
     // TODO(crbug.com/1098685): Trusted Type remaining WebUI.
     source->DisableTrustedTypesCSP();
@@ -90,40 +82,24 @@
 
 FileManagerJsTestBase::~FileManagerJsTestBase() {}
 
-void FileManagerJsTestBase::RunTest(const base::FilePath& file) {
-  base::FilePath root_path;
-  ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
-  base::FilePath full_path = root_path.Append(base_path_).Append(file);
-  {
-    base::ScopedAllowBlockingForTesting allow_io;
-    ASSERT_TRUE(base::PathExists(full_path)) << full_path.value();
-  }
-  RunTestImpl(net::FilePathToFileURL(full_path));
-}
-
-void FileManagerJsTestBase::RunGeneratedTest(const std::string& file) {
-  base::FilePath path = GetGenRoot();
-
-  // Serve the generated html file from out/gen. It references files from
-  // DIR_SOURCE_ROOT, so serve from there as well. An alternative would be to
-  // copy the js files as a build step and serve file:// URLs, but the embedded
-  // test server gives better output for troubleshooting errors.
-  embedded_test_server()->ServeFilesFromDirectory(path.Append(base_path_));
-  embedded_test_server()->ServeFilesFromSourceDirectory(base::FilePath());
-
-  ASSERT_TRUE(embedded_test_server()->Start());
-  RunTestImpl(embedded_test_server()->GetURL(file));
-}
-
 void FileManagerJsTestBase::RunTestURL(const std::string& file) {
-  RunTestImpl(GURL("chrome://webui-test/" + base_path_.Append(file).value()));
-}
-
-void FileManagerJsTestBase::RunTestImpl(const GURL& url) {
+  // Open a new tab with the Files app test harness.
+  auto url =
+      GURL("chrome://webui-test/base/js/test_harness.html?test_module=/" +
+           base_path_.Append(file).value());
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+
   content::WebContents* const web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   ASSERT_TRUE(web_contents);
+
+  // Wait for the JS modules to be loaded and exported to window.
+  content::DOMMessageQueue message_queue(web_contents);
+  std::string message;
+  ASSERT_TRUE(message_queue.WaitForMessage(&message));
+  EXPECT_EQ(message, "\"LOADED\"");
+
+  // Execute the WebUI test harness.
   EXPECT_TRUE(ExecuteWebUIResourceTest(web_contents));
 }
 
diff --git a/chrome/browser/ash/file_manager/file_watcher.cc b/chrome/browser/ash/file_manager/file_watcher.cc
index 73b0d79..aa1e291 100644
--- a/chrome/browser/ash/file_manager/file_watcher.cc
+++ b/chrome/browser/ash/file_manager/file_watcher.cc
@@ -11,10 +11,12 @@
 #include "base/logging.h"
 #include "base/task/task_runner_util.h"
 #include "base/task/thread_pool.h"
-#include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/ash/guest_os/guest_id.h"
+#include "chrome/browser/ash/guest_os/guest_os_file_watcher.h"
+#include "chrome/browser/ash/guest_os/public/guest_os_service.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/common/task_util.h"
 
@@ -38,77 +40,42 @@
   return watcher.release();
 }
 
-}  // namespace
-
-class FileWatcher::CrostiniFileWatcher
-    : public crostini::CrostiniFileChangeObserver {
- public:
-  static std::unique_ptr<CrostiniFileWatcher> GetForPath(
-      Profile* profile,
-      const base::FilePath& local_path) {
-    base::FilePath crostini_mount = util::GetCrostiniMountDirectory(profile);
-    base::FilePath crostini_path;
-    if (local_path == crostini_mount ||
-        crostini_mount.AppendRelativePath(local_path, &crostini_path)) {
-      crostini::CrostiniManager* crostini_manager =
-          crostini::CrostiniManager::GetForProfile(profile);
-      if (crostini_manager) {
-        return std::make_unique<CrostiniFileWatcher>(crostini_manager,
-                                                     std::move(crostini_mount),
-                                                     std::move(crostini_path));
-      }
-    }
+std::unique_ptr<guest_os::GuestOsFileWatcher> GetForPath(
+    Profile* profile,
+    const base::FilePath& local_path) {
+  // TODO(b/217469540): The default Crostini mount isn't using mount providers
+  // yet so check for it explicitly and handle it differently.
+  base::FilePath crostini_mount = util::GetCrostiniMountDirectory(profile);
+  base::FilePath relative_path;
+  if (local_path == crostini_mount ||
+      crostini_mount.AppendRelativePath(local_path, &relative_path)) {
+    return std::make_unique<guest_os::GuestOsFileWatcher>(
+        ash::ProfileHelper::GetUserIdHashFromProfile(profile),
+        crostini::DefaultContainerId(), std::move(crostini_mount),
+        std::move(relative_path));
+  }
+  auto* service = guest_os::GuestOsService::GetForProfile(profile);
+  if (!service) {
     return nullptr;
   }
-
-  CrostiniFileWatcher(crostini::CrostiniManager* crostini_manager,
-                      base::FilePath crostini_mount,
-                      base::FilePath crostini_path)
-      : crostini_manager_(crostini_manager),
-        crostini_mount_(std::move(crostini_mount)),
-        crostini_path_(std::move(crostini_path)),
-        container_id_(crostini::DefaultContainerId()) {}
-
-  ~CrostiniFileWatcher() override {
-    if (file_watcher_callback_) {
-      crostini_manager_->RemoveFileChangeObserver(this);
-      crostini_manager_->RemoveFileWatch(container_id_, crostini_path_);
+  auto* registry = service->MountProviderRegistry();
+  for (const auto id : registry->List()) {
+    auto* provider = registry->Get(id);
+    base::FilePath mount_path = util::GetGuestOsMountDirectory(
+        util::GetGuestOsMountPointName(profile, provider->GuestId()));
+    if (local_path == mount_path ||
+        mount_path.AppendRelativePath(local_path, &relative_path)) {
+      return provider->CreateFileWatcher(std::move(mount_path),
+                                         std::move(relative_path));
     }
   }
-
-  void Watch(base::FilePathWatcher::Callback file_watcher_callback,
-             FileWatcher::BoolCallback callback) {
-    DCHECK(!file_watcher_callback_);
-    file_watcher_callback_ = std::move(file_watcher_callback);
-    crostini_manager_->AddFileChangeObserver(this);
-    crostini_manager_->AddFileWatch(container_id_, crostini_path_,
-                                    std::move(callback));
-  }
-
- private:
-  // crostini::CrostiniFileChangeObserver overrides
-  void OnCrostiniFileChanged(const guest_os::GuestId& container_id,
-                             const base::FilePath& path) override {
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
-    if (container_id != container_id_) {
-      return;
-    }
-
-    DCHECK(file_watcher_callback_);
-    file_watcher_callback_.Run(crostini_mount_.Append(path), /*error=*/false);
-  }
-
-  crostini::CrostiniManager* crostini_manager_;
-  const base::FilePath crostini_mount_;
-  const base::FilePath crostini_path_;
-  const guest_os::GuestId container_id_;
-  base::FilePathWatcher::Callback file_watcher_callback_;
-};
+  return nullptr;
+}
+}  // namespace
 
 FileWatcher::FileWatcher(const base::FilePath& virtual_path)
     : sequenced_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
           {base::MayBlock(), base::TaskPriority::USER_VISIBLE})),
-      local_file_watcher_(nullptr),
       virtual_path_(virtual_path) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
@@ -158,7 +125,7 @@
   DCHECK(!local_file_watcher_);
 
   // If this is a crostini SSHFS path, use CrostiniFileWatcher.
-  crostini_file_watcher_ = CrostiniFileWatcher::GetForPath(profile, local_path);
+  crostini_file_watcher_ = GetForPath(profile, local_path);
   if (crostini_file_watcher_) {
     crostini_file_watcher_->Watch(std::move(file_watcher_callback),
                                   std::move(callback));
diff --git a/chrome/browser/ash/file_manager/file_watcher.h b/chrome/browser/ash/file_manager/file_watcher.h
index cdbbe39..994fdd0 100644
--- a/chrome/browser/ash/file_manager/file_watcher.h
+++ b/chrome/browser/ash/file_manager/file_watcher.h
@@ -17,6 +17,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "url/origin.h"
 
+namespace guest_os {
+class GuestOsFileWatcher;
+}
+
 namespace file_manager {
 
 // This class is used to watch changes in the given virtual path, remember
@@ -73,16 +77,14 @@
       BoolCallback callback);
 
  private:
-  class CrostiniFileWatcher;
-
   // Called when a FilePathWatcher is created and started.
   // |file_path_watcher| is NULL, if the watcher wasn't started successfully.
   void OnWatcherStarted(BoolCallback callback,
                         base::FilePathWatcher* file_path_watcher);
 
   scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
-  base::FilePathWatcher* local_file_watcher_;
-  std::unique_ptr<CrostiniFileWatcher> crostini_file_watcher_;
+  base::FilePathWatcher* local_file_watcher_ = nullptr;
+  std::unique_ptr<guest_os::GuestOsFileWatcher> crostini_file_watcher_;
   base::FilePath virtual_path_;
   // Map of origin to counter. See the comment at AddListener() for
   // why we need to count.
diff --git a/chrome/browser/ash/file_manager/fusebox_moniker.cc b/chrome/browser/ash/file_manager/fusebox_moniker.cc
new file mode 100644
index 0000000..0f80d27
--- /dev/null
+++ b/chrome/browser/ash/file_manager/fusebox_moniker.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/file_manager/fusebox_moniker.h"
+
+#include <unordered_map>
+#include "base/no_destructor.h"
+#include "content/public/browser/browser_thread.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace {
+
+base::NoDestructor<
+    std::unordered_map<base::Token, storage::FileSystemURL, base::TokenHash>>
+    fusebox_monikers;
+
+}  // namespace
+
+namespace file_manager {
+
+// static
+FuseBoxMoniker FuseBoxMoniker::Create(storage::FileSystemURL target) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  base::Token token = base::Token::CreateRandom();
+  fusebox_monikers->insert({token, std::move(target)});
+  return FuseBoxMoniker(token);
+}
+
+// static
+FuseBoxMoniker::ExtractTokenResult FuseBoxMoniker::ExtractToken(
+    std::string fs_url_as_string) {
+  if (!base::StartsWith(fs_url_as_string, fusebox::kMonikerFileSystemURL)) {
+    ExtractTokenResult result;
+    result.result_type = ExtractTokenResult::ResultType::NOT_A_MONIKER_FS_URL;
+    return result;
+  }
+  const size_t n = strlen(fusebox::kMonikerFileSystemURL);
+  if (fs_url_as_string.size() <= n) {
+    ExtractTokenResult result;
+    result.result_type =
+        ExtractTokenResult::ResultType::MONIKER_FS_URL_BUT_ONLY_ROOT;
+    return result;
+  } else if (fs_url_as_string[n] != '/') {
+    ExtractTokenResult result;
+    result.result_type = ExtractTokenResult::ResultType::NOT_A_MONIKER_FS_URL;
+    return result;
+  }
+  absl::optional<base::Token> token =
+      base::Token::FromString(fs_url_as_string.substr(n + 1));
+  if (!token) {
+    ExtractTokenResult result;
+    result.result_type =
+        ExtractTokenResult::ResultType::MONIKER_FS_URL_BUT_NOT_WELL_FORMED;
+    return result;
+  }
+  ExtractTokenResult result;
+  result.result_type = ExtractTokenResult::ResultType::OK;
+  result.token = *token;
+  return result;
+}
+
+// static
+storage::FileSystemURL FuseBoxMoniker::Resolve(base::Token token) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  auto iter = fusebox_monikers->find(token);
+  if (iter != fusebox_monikers->end()) {
+    return iter->second;
+  }
+  return storage::FileSystemURL();
+}
+
+FuseBoxMoniker::FuseBoxMoniker(base::Token token) : token_(token) {}
+
+void FuseBoxMoniker::Destroy() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  auto iter = fusebox_monikers->find(token_);
+  if (iter != fusebox_monikers->end()) {
+    fusebox_monikers->erase(iter);
+  }
+}
+
+storage::FileSystemURL FuseBoxMoniker::Target() {
+  return Resolve(token_);
+}
+
+std::string FuseBoxMoniker::LinkFilename() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  return fusebox::kMonikerFilenamePrefixWithTrailingSlash + token_.ToString();
+}
+
+base::Token FuseBoxMoniker::LinkToken() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  return token_;
+}
+
+}  // namespace file_manager
diff --git a/chrome/browser/ash/file_manager/fusebox_moniker.h b/chrome/browser/ash/file_manager/fusebox_moniker.h
new file mode 100644
index 0000000..a58950c4
--- /dev/null
+++ b/chrome/browser/ash/file_manager/fusebox_moniker.h
@@ -0,0 +1,109 @@
+// Copyright (c) 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_FILE_MANAGER_FUSEBOX_MONIKER_H_
+#define CHROME_BROWSER_ASH_FILE_MANAGER_FUSEBOX_MONIKER_H_
+
+#include "base/token.h"
+#include "storage/browser/file_system/file_system_url.h"
+
+namespace file_manager {
+
+// A moniker is an alternative name (an alias or symbolic link, of sorts) for a
+// FileSystemURL (a C++ object). That name is a filename on the Linux file
+// system, such as "/media/fuse/fusebox/moniker/1234etc", and is served by the
+// FuseBox FUSE server.
+//
+// It is like a symbolic link, "ln -s TARGET LINK_NAME", where TARGET is the
+// FileSystemURL and LINK_NAME is the "/media/fuse/fusebox/moniker/1234etc",
+// but differs from symlinks in three ways.
+//
+// First, the TARGET is itself not present in the file system (at the operating
+// system level). The purpose of a moniker is to provide a filename (in the OS
+// sense) for something that doesn't have one (such as an Android Content
+// Provider's "content://com.example.appname.provider/the/path/to/the/thing"
+// Content URL wrapped in a FileSystemURL). Separate processes can share a
+// filename (a plain old string) when they can't share a FileSystemURL.
+//
+// Second, the LINK_NAME is unguessable (essentially a randomly generated
+// 128-bit base::Token) and "ls /media/fuse/fusebox/moniker/" will show an
+// empty directory. Only the FuseBoxMoniker::Create caller (and whoever it
+// shares the resultant FuseBoxMoniker with, in C++ object, base::Token or
+// string filename form) has the capability to ask the FuseBox FUSE server to
+// resolve the LINK_NAME to read the original TARGET.
+//
+// Third, monikers always target individual files, never directories.
+//
+// All FuseBoxMoniker methods, static and non-static, must only be called on
+// the main (UI) thread.
+class FuseBoxMoniker {
+ public:
+  // Creates a randomly generated link name (available in both base::Token and
+  // string form) for the target. It is the caller's responsibility to call
+  // FuseBoxMoniker::Destroy when the moniker is no longer required but also to
+  // keep the FileSystemURL's backing content alive until that Destroy call.
+  static FuseBoxMoniker Create(storage::FileSystemURL target);
+
+  struct ExtractTokenResult {
+    enum class ResultType {
+      // The fs_url_as_string was a Moniker FileSystemURL (it started with the
+      // fusebox::kMonikerFileSystemURL prefix) and held a well-formed token.
+      OK = 0,
+      // The fs_url_as_string was not a Moniker FileSystemURL.
+      NOT_A_MONIKER_FS_URL = 1,
+      // The fs_url_as_string was a Moniker FileSystemURL but named the root of
+      // all such FileSystemURL's. It did not hold a well-formed token.
+      MONIKER_FS_URL_BUT_ONLY_ROOT = 2,
+      // The fs_url_as_string was a Moniker FileSystemURL but did not hold a
+      // well-formed token (and was not MONIKER_FS_URL_BUT_ONLY_ROOT).
+      MONIKER_FS_URL_BUT_NOT_WELL_FORMED = 3,
+    } result_type;
+
+    base::Token token;
+  };
+
+  // Returns the 1234etc base::Token from a storage::FileSystemURL in its
+  // string form (like "dummy://moniker/1234etc"), where "dummy://moniker" is
+  // the fusebox::kMonikerFileSystemURL prefix.
+  //
+  // This function does not resolve the base::Token (for that, use the Resolve
+  // function instead). It does not confirm the token's *validity* (that the
+  // token matches a previous call to Create), only its *well-formed-ness*
+  // (that it looks like a token, at the lexical level).
+  static ExtractTokenResult ExtractToken(std::string fs_url_as_string);
+
+  // Returns the target for the previously linked moniker, as identified by its
+  // base::Token. The return value's is_valid() will be false if there was no
+  // such moniker or if it was unlinked.
+  static storage::FileSystemURL Resolve(base::Token token);
+
+  // Tears down the link, so that Resolve and Target will return invalid
+  // FileSystemURL values.
+  void Destroy();
+
+  storage::FileSystemURL Target();
+  std::string LinkFilename();
+  base::Token LinkToken();
+
+ private:
+  explicit FuseBoxMoniker(base::Token token);
+
+  // This token (an 128-bit value) is randomly generated and unguessable, so in
+  // some sense, it is like a base::UnguessableToken (call that a b::UT). But
+  // an all-zero-bits b::UT is not just invalid, b::UT::Deserialize(0, 0) will
+  // actually DCHECK-crash. The design assumption is that b::UT values are only
+  // shared between trusted processes via trusted channels. Here, the token is
+  // parsed from the FUSE filename and all manner of processes (of various
+  // trustworthiness) can walk the file system. We don't want "ls
+  // /media/fuse/fusebox/moniker/00000000000000000000000000000000" to crash the
+  // Chrome process. So we use base::Token, a more forgiving type than
+  // base::UnguessableToken.
+  //
+  // See also the crrev.com/c/3645173 code review discussion.
+  base::Token token_;
+};
+
+}  // namespace file_manager
+
+#endif  // CHROME_BROWSER_ASH_FILE_MANAGER_FUSEBOX_MONIKER_H_
diff --git a/chrome/browser/ash/file_manager/fusebox_moniker_unittest.cc b/chrome/browser/ash/file_manager/fusebox_moniker_unittest.cc
new file mode 100644
index 0000000..659a666
--- /dev/null
+++ b/chrome/browser/ash/file_manager/fusebox_moniker_unittest.cc
@@ -0,0 +1,51 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/file_manager/fusebox_moniker.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace file_manager {
+
+TEST(FuseBoxMonikerTest, ExtractTokenResult) {
+  using ResultType = FuseBoxMoniker::ExtractTokenResult::ResultType;
+
+  {
+    auto result = FuseBoxMoniker::ExtractToken("foo://bar");
+    EXPECT_EQ(result.result_type, ResultType::NOT_A_MONIKER_FS_URL);
+  }
+
+  {
+    auto result = FuseBoxMoniker::ExtractToken(
+        "dummy://something_else/0123456789ABCDEF0000111122223333");
+    EXPECT_EQ(result.result_type, ResultType::NOT_A_MONIKER_FS_URL);
+  }
+
+  {
+    auto result = FuseBoxMoniker::ExtractToken("dummy://moniker");
+    EXPECT_EQ(result.result_type, ResultType::MONIKER_FS_URL_BUT_ONLY_ROOT);
+  }
+
+  {
+    auto result = FuseBoxMoniker::ExtractToken("dummy://moniker/");
+    EXPECT_EQ(result.result_type,
+              ResultType::MONIKER_FS_URL_BUT_NOT_WELL_FORMED);
+  }
+
+  {
+    auto result = FuseBoxMoniker::ExtractToken("dummy://moniker/0123");
+    EXPECT_EQ(result.result_type,
+              ResultType::MONIKER_FS_URL_BUT_NOT_WELL_FORMED);
+  }
+
+  {
+    auto result = FuseBoxMoniker::ExtractToken(
+        "dummy://moniker/0123456789ABCDEF0000111122223333");
+    EXPECT_EQ(result.result_type, ResultType::OK);
+    EXPECT_EQ(result.token,
+              base::Token(0x0123456789ABCDEFull, 0x0000111122223333ull));
+  }
+}
+
+}  // namespace file_manager
diff --git a/chrome/browser/ash/file_manager/image_loader_jstest.cc b/chrome/browser/ash/file_manager/image_loader_jstest.cc
index c3b0c08..f2542b1a 100644
--- a/chrome/browser/ash/file_manager/image_loader_jstest.cc
+++ b/chrome/browser/ash/file_manager/image_loader_jstest.cc
@@ -23,17 +23,17 @@
 };
 
 IN_PROC_BROWSER_TEST_F(ImageLoaderJsTest, ImageLoaderClientTest) {
-  RunTestURL("image_loader_client_unittest.m_gen.html");
+  RunTestURL("image_loader_client_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(ImageLoaderJsTest, CacheTest) {
-  RunTestURL("cache_unittest.m_gen.html");
+  RunTestURL("cache_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(ImageLoaderJsTest, ImageLoaderTest) {
-  RunTestURL("image_loader_unittest.m_gen.html");
+  RunTestURL("image_loader_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(ImageLoaderJsTest, SchedulerTest) {
-  RunTestURL("scheduler_unittest.m_gen.html");
+  RunTestURL("scheduler_unittest.js");
 }
diff --git a/chrome/browser/ash/file_manager/restore_io_task.cc b/chrome/browser/ash/file_manager/restore_io_task.cc
index 9484ff6d..05059c2 100644
--- a/chrome/browser/ash/file_manager/restore_io_task.cc
+++ b/chrome/browser/ash/file_manager/restore_io_task.cc
@@ -131,7 +131,21 @@
       trash_parent_path.Append(trash_relative_folder_path)
           .Append(kFilesFolderName)
           .Append(trash_info.BaseName().RemoveFinalExtension());
-  if (!base::PathExists(trashed_file_location)) {
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::MayBlock()},
+      base::BindOnce(&base::PathExists, trashed_file_location),
+      base::BindOnce(&RestoreIOTask::OnTrashedFileExists,
+                     weak_ptr_factory_.GetWeakPtr(), idx, trash_parent_path,
+                     trashed_file_location));
+}
+
+void RestoreIOTask::OnTrashedFileExists(
+    size_t idx,
+    const base::FilePath& trash_parent_path,
+    const base::FilePath& trashed_file_location,
+    bool exists) {
+  if (!exists) {
     progress_.sources[idx].error = base::File::FILE_ERROR_NOT_FOUND;
     Complete(State::kError);
     return;
diff --git a/chrome/browser/ash/file_manager/restore_io_task.h b/chrome/browser/ash/file_manager/restore_io_task.h
index 3d2253f..ff85bb2 100644
--- a/chrome/browser/ash/file_manager/restore_io_task.h
+++ b/chrome/browser/ash/file_manager/restore_io_task.h
@@ -53,6 +53,11 @@
   //   - Has an identical item in the files directory with no .trashinfo suffix
   void ValidateTrashInfo(size_t idx);
 
+  void OnTrashedFileExists(size_t idx,
+                           const base::FilePath& trash_parent_path,
+                           const base::FilePath& trashed_file_location,
+                           bool exists);
+
   // Make sure the enclosing folder where the trashed file to be restored to
   // actually exists. In the event the file path has been removed, recreate it.
   void EnsureParentRestorePathExists(
diff --git a/chrome/browser/ash/file_system_provider/operations/abort_unittest.cc b/chrome/browser/ash/file_system_provider/operations/abort_unittest.cc
index d64ca66..fe489b1 100644
--- a/chrome/browser/ash/file_system_provider/operations/abort_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/abort_unittest.cc
@@ -66,10 +66,10 @@
   extensions::Event* event = dispatcher.events()[0].get();
   EXPECT_EQ(extensions::api::file_system_provider::OnAbortRequested::kEventName,
             event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   AbortRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/add_watcher_unittest.cc b/chrome/browser/ash/file_system_provider/operations/add_watcher_unittest.cc
index bf645e819..b5cab5b2 100644
--- a/chrome/browser/ash/file_system_provider/operations/add_watcher_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/add_watcher_unittest.cc
@@ -69,10 +69,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnAddWatcherRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   AddWatcherRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/close_file_unittest.cc b/chrome/browser/ash/file_system_provider/operations/close_file_unittest.cc
index 349b4fe..293aca8 100644
--- a/chrome/browser/ash/file_system_provider/operations/close_file_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/close_file_unittest.cc
@@ -67,10 +67,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnCloseFileRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   CloseFileRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/configure_unittest.cc b/chrome/browser/ash/file_system_provider/operations/configure_unittest.cc
index 4b62ab0..2bb7ab8 100644
--- a/chrome/browser/ash/file_system_provider/operations/configure_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/configure_unittest.cc
@@ -65,10 +65,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnConfigureRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   ConfigureRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/copy_entry_unittest.cc b/chrome/browser/ash/file_system_provider/operations/copy_entry_unittest.cc
index 819a2b5..ef14108 100644
--- a/chrome/browser/ash/file_system_provider/operations/copy_entry_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/copy_entry_unittest.cc
@@ -72,10 +72,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnCopyEntryRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   CopyEntryRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/create_directory_unittest.cc b/chrome/browser/ash/file_system_provider/operations/create_directory_unittest.cc
index c008bc3..415350db 100644
--- a/chrome/browser/ash/file_system_provider/operations/create_directory_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/create_directory_unittest.cc
@@ -73,10 +73,10 @@
   EXPECT_EQ(extensions::api::file_system_provider::OnCreateDirectoryRequested::
                 kEventName,
             event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   CreateDirectoryRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/create_file_unittest.cc b/chrome/browser/ash/file_system_provider/operations/create_file_unittest.cc
index a34e699..44447dfe 100644
--- a/chrome/browser/ash/file_system_provider/operations/create_file_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/create_file_unittest.cc
@@ -70,10 +70,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnCreateFileRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   CreateFileRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/delete_entry_unittest.cc b/chrome/browser/ash/file_system_provider/operations/delete_entry_unittest.cc
index b413612..869b973 100644
--- a/chrome/browser/ash/file_system_provider/operations/delete_entry_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/delete_entry_unittest.cc
@@ -70,10 +70,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnDeleteEntryRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   DeleteEntryRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/execute_action_unittest.cc b/chrome/browser/ash/file_system_provider/operations/execute_action_unittest.cc
index 8911d50..634591e2 100644
--- a/chrome/browser/ash/file_system_provider/operations/execute_action_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/execute_action_unittest.cc
@@ -76,10 +76,10 @@
   EXPECT_EQ(extensions::api::file_system_provider::OnExecuteActionRequested::
                 kEventName,
             event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   ExecuteActionRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/get_actions_unittest.cc b/chrome/browser/ash/file_system_provider/operations/get_actions_unittest.cc
index 005f6fc..799a7906 100644
--- a/chrome/browser/ash/file_system_provider/operations/get_actions_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/get_actions_unittest.cc
@@ -133,10 +133,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnGetActionsRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   GetActionsRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/get_metadata_unittest.cc b/chrome/browser/ash/file_system_provider/operations/get_metadata_unittest.cc
index a94b3214..daf3cb3 100644
--- a/chrome/browser/ash/file_system_provider/operations/get_metadata_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/get_metadata_unittest.cc
@@ -245,10 +245,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnGetMetadataRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   GetMetadataRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/move_entry_unittest.cc b/chrome/browser/ash/file_system_provider/operations/move_entry_unittest.cc
index 98ac602e..3d6cb4c5 100644
--- a/chrome/browser/ash/file_system_provider/operations/move_entry_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/move_entry_unittest.cc
@@ -72,10 +72,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnMoveEntryRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   MoveEntryRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/open_file_unittest.cc b/chrome/browser/ash/file_system_provider/operations/open_file_unittest.cc
index 9395bb4..8951c8a 100644
--- a/chrome/browser/ash/file_system_provider/operations/open_file_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/open_file_unittest.cc
@@ -108,10 +108,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnOpenFileRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   OpenFileRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/operation.cc b/chrome/browser/ash/file_system_provider/operations/operation.cc
index 69f7572f..e86c251 100644
--- a/chrome/browser/ash/file_system_provider/operations/operation.cc
+++ b/chrome/browser/ash/file_system_provider/operations/operation.cc
@@ -51,7 +51,6 @@
                        ProviderId provider_id,
                        const std::string& file_system_id,
                        int request_id,
-
                        extensions::events::HistogramValue histogram_value,
                        const std::string& event_name,
                        std::vector<base::Value> event_args) {
@@ -112,10 +111,11 @@
 bool Operation::SendEvent(int request_id,
                           extensions::events::HistogramValue histogram_value,
                           const std::string& event_name,
-                          std::vector<base::Value> event_args) {
+                          base::Value::List event_args) {
   return dispatch_event_impl_.Run(
       file_system_info_.provider_id(), file_system_info_.file_system_id(),
-      request_id, histogram_value, event_name, std::move(event_args));
+      request_id, histogram_value, event_name,
+      base::Value(std::move(event_args)).TakeListDeprecated());
 }
 
 }  // namespace operations
diff --git a/chrome/browser/ash/file_system_provider/operations/operation.h b/chrome/browser/ash/file_system_provider/operations/operation.h
index 95ab7a0..67d8226 100644
--- a/chrome/browser/ash/file_system_provider/operations/operation.h
+++ b/chrome/browser/ash/file_system_provider/operations/operation.h
@@ -58,7 +58,7 @@
   bool SendEvent(int request_id,
                  extensions::events::HistogramValue histogram_value,
                  const std::string& event_name,
-                 std::vector<base::Value> event_args);
+                 base::Value::List event_args);
 
   ProvidedFileSystemInfo file_system_info_;
 
diff --git a/chrome/browser/ash/file_system_provider/operations/read_directory_unittest.cc b/chrome/browser/ash/file_system_provider/operations/read_directory_unittest.cc
index b833bb2..c1b22587 100644
--- a/chrome/browser/ash/file_system_provider/operations/read_directory_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/read_directory_unittest.cc
@@ -141,10 +141,10 @@
   EXPECT_EQ(extensions::api::file_system_provider::OnReadDirectoryRequested::
                 kEventName,
             event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   ReadDirectoryRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/read_file_unittest.cc b/chrome/browser/ash/file_system_provider/operations/read_file_unittest.cc
index 1f0c3a1a..0819f27 100644
--- a/chrome/browser/ash/file_system_provider/operations/read_file_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/read_file_unittest.cc
@@ -117,10 +117,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnReadFileRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   ReadFileRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/remove_watcher_unittest.cc b/chrome/browser/ash/file_system_provider/operations/remove_watcher_unittest.cc
index 2a4c646..3b24fc9e3 100644
--- a/chrome/browser/ash/file_system_provider/operations/remove_watcher_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/remove_watcher_unittest.cc
@@ -69,10 +69,10 @@
   EXPECT_EQ(extensions::api::file_system_provider::OnRemoveWatcherRequested::
                 kEventName,
             event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   RemoveWatcherRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/truncate_unittest.cc b/chrome/browser/ash/file_system_provider/operations/truncate_unittest.cc
index 47239248..572d279 100644
--- a/chrome/browser/ash/file_system_provider/operations/truncate_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/truncate_unittest.cc
@@ -73,10 +73,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnTruncateRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   TruncateRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/unmount_unittest.cc b/chrome/browser/ash/file_system_provider/operations/unmount_unittest.cc
index d0d3ace..bbe5755 100644
--- a/chrome/browser/ash/file_system_provider/operations/unmount_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/unmount_unittest.cc
@@ -65,10 +65,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnUnmountRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   UnmountRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/operations/write_file.cc b/chrome/browser/ash/file_system_provider/operations/write_file.cc
index 2b363944..7e499da3 100644
--- a/chrome/browser/ash/file_system_provider/operations/write_file.cc
+++ b/chrome/browser/ash/file_system_provider/operations/write_file.cc
@@ -56,8 +56,8 @@
       "data",
       base::Value(base::as_bytes(base::make_span(buffer_->data(), length_))));
 
-  std::vector<base::Value> event_args;
-  event_args.push_back(std::move(options_as_value));
+  base::Value::List event_args;
+  event_args.Append(std::move(options_as_value));
 
   return SendEvent(
       request_id,
diff --git a/chrome/browser/ash/file_system_provider/operations/write_file_unittest.cc b/chrome/browser/ash/file_system_provider/operations/write_file_unittest.cc
index 8d127da..c59c81d 100644
--- a/chrome/browser/ash/file_system_provider/operations/write_file_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operations/write_file_unittest.cc
@@ -75,10 +75,10 @@
   EXPECT_EQ(
       extensions::api::file_system_provider::OnWriteFileRequested::kEventName,
       event->event_name);
-  base::ListValue* event_args = event->event_args.get();
-  ASSERT_EQ(1u, event_args->GetListDeprecated().size());
+  const base::Value::List& event_args = event->event_args;
+  ASSERT_EQ(1u, event_args.size());
 
-  const base::Value* options_as_value = &event_args->GetListDeprecated()[0];
+  const base::Value* options_as_value = &event_args[0];
   ASSERT_TRUE(options_as_value->is_dict());
 
   WriteFileRequestedOptions options;
diff --git a/chrome/browser/ash/file_system_provider/provided_file_system_unittest.cc b/chrome/browser/ash/file_system_provider/provided_file_system_unittest.cc
index 23a74370..3276ffa 100644
--- a/chrome/browser/ash/file_system_provider/provided_file_system_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/provided_file_system_unittest.cc
@@ -71,7 +71,7 @@
       const extensions::ExtensionId& extension_id,
       std::unique_ptr<extensions::Event> event) override {
     ASSERT_TRUE(file_system_);
-    const base::Value* dict = &event->event_args->GetListDeprecated()[0];
+    const base::Value* dict = &event->event_args[0];
     ASSERT_TRUE(dict->is_dict());
     const std::string* file_system_id = dict->FindStringKey("fileSystemId");
     EXPECT_NE(file_system_id, nullptr);
diff --git a/chrome/browser/ash/guest_os/guest_os_file_watcher.cc b/chrome/browser/ash/guest_os/guest_os_file_watcher.cc
new file mode 100644
index 0000000..4d9ef1e0
--- /dev/null
+++ b/chrome/browser/ash/guest_os/guest_os_file_watcher.cc
@@ -0,0 +1,82 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/guest_os/guest_os_file_watcher.h"
+
+#include "base/logging.h"
+#include "chromeos/ash/components/dbus/cicerone/cicerone_client.h"
+#include "chromeos/ash/components/dbus/cicerone/cicerone_service.pb.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace guest_os {
+
+GuestOsFileWatcher::GuestOsFileWatcher(std::string owner_id,
+                                       GuestId guest_id,
+                                       base::FilePath mount_path,
+                                       base::FilePath path)
+    : owner_id_(std::move(owner_id)),
+      guest_id_(std::move(guest_id)),
+      mount_path_(std::move(mount_path)),
+      path_(std::move(path)) {}
+
+GuestOsFileWatcher::~GuestOsFileWatcher() {
+  if (!file_watcher_callback_) {
+    return;
+  }
+  vm_tools::cicerone::RemoveFileWatchRequest req;
+  req.set_owner_id(owner_id_);
+  req.set_vm_name(guest_id_.vm_name);
+  req.set_container_name(guest_id_.container_name);
+  req.set_path(path_.value());
+
+  auto* client = ash::CiceroneClient::Get();
+  client->RemoveObserver(this);
+  client->RemoveFileWatch(req, base::DoNothing());
+}
+
+void GuestOsFileWatcher::Watch(
+    base::FilePathWatcher::Callback file_watcher_callback,
+    file_manager::FileWatcher::BoolCallback callback) {
+  auto* client = ash::CiceroneClient::Get();
+  DCHECK(!file_watcher_callback_);
+  file_watcher_callback_ = std::move(file_watcher_callback);
+  vm_tools::cicerone::AddFileWatchRequest req;
+  req.set_owner_id(owner_id_);
+  req.set_vm_name(guest_id_.vm_name);
+  req.set_container_name(guest_id_.container_name);
+  req.set_path(path_.value());
+  client->AddObserver(this);
+  client->AddFileWatch(
+      req, base::BindOnce(
+               [](file_manager::FileWatcher::BoolCallback callback,
+                  absl::optional<vm_tools::cicerone::AddFileWatchResponse>
+                      response) {
+                 if (!response ||
+                     response->status() !=
+                         vm_tools::cicerone::AddFileWatchResponse::SUCCEEDED) {
+                   LOG(ERROR) << "Error adding file watch: "
+                              << (response ? response->failure_reason()
+                                           : "empty response");
+                   std::move(callback).Run(false);
+                   return;
+                 }
+                 std::move(callback).Run(true);
+               },
+               std::move(callback)));
+}
+
+void GuestOsFileWatcher::OnFileWatchTriggered(
+    const vm_tools::cicerone::FileWatchTriggeredSignal& signal) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (signal.owner_id() != owner_id_ || signal.vm_name() != guest_id_.vm_name ||
+      signal.container_name() != guest_id_.container_name) {
+    return;
+  }
+
+  DCHECK(file_watcher_callback_);
+  file_watcher_callback_.Run(mount_path_.Append(signal.path()),
+                             /*error=*/false);
+}
+
+}  // namespace guest_os
diff --git a/chrome/browser/ash/guest_os/guest_os_file_watcher.h b/chrome/browser/ash/guest_os/guest_os_file_watcher.h
new file mode 100644
index 0000000..db3bcef
--- /dev/null
+++ b/chrome/browser/ash/guest_os/guest_os_file_watcher.h
@@ -0,0 +1,59 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_GUEST_OS_GUEST_OS_FILE_WATCHER_H_
+#define CHROME_BROWSER_ASH_GUEST_OS_GUEST_OS_FILE_WATCHER_H_
+
+#include "base/files/file_path_watcher.h"
+#include "chrome/browser/ash/file_manager/file_watcher.h"
+#include "chrome/browser/ash/guest_os/guest_id.h"
+#include "chromeos/ash/components/dbus/cicerone/cicerone_client.h"
+
+namespace guest_os {
+
+class GuestOsFileWatcher : public ash::CiceroneClient::Observer {
+ public:
+  // Creates a watcher for the given `guest_id`, which uses garcon and is
+  // sharing a directory mounted under `mount_path`, that watches for changes to
+  // `path` where `path` is relative to the share root. The created watcher is
+  // in an idle state, call Watch to actually start watching.
+  GuestOsFileWatcher(std::string owner_id,
+                     GuestId guest_id,
+                     base::FilePath mount_path,
+                     base::FilePath path);
+
+  ~GuestOsFileWatcher() override;
+
+  // Call this to start watching the path, destroy this watcher to stop
+  // watching. Will run `callback` once the watch is set up with either true on
+  // success or false on failure. If the watch is successfully set up,
+  // `file_watcher_callback` will be invoked on file changes with the path
+  // *outside* that's changed. For example, if the volume is mounted at
+  // /mnt/foo, the folder the VM is sharing is rooted at /home/user, and the
+  // watch is for baz, then if /home/user/baz is changed `file_watcher_callback`
+  // will be called with /mnt/foo/baz.
+  void Watch(base::FilePathWatcher::Callback file_watcher_callback,
+             file_manager::FileWatcher::BoolCallback callback);
+
+  // ash::CiceroneClient::Observer override.
+  void OnFileWatchTriggered(
+      const vm_tools::cicerone::FileWatchTriggeredSignal& signal) override;
+
+ private:
+  std::string owner_id_;
+  const guest_os::GuestId guest_id_;
+
+  // Runs this callback when the
+  base::FilePathWatcher::Callback file_watcher_callback_;
+
+  // The location on the host filesystem where the mount is rooted.
+  const base::FilePath mount_path_;
+
+  // The path, relative to the mount rooot, which is to be watched.
+  const base::FilePath path_;
+};
+
+}  // namespace guest_os
+
+#endif  // CHROME_BROWSER_ASH_GUEST_OS_GUEST_OS_FILE_WATCHER_H_
diff --git a/chrome/browser/ash/guest_os/guest_os_file_watcher_unittest.cc b/chrome/browser/ash/guest_os/guest_os_file_watcher_unittest.cc
new file mode 100644
index 0000000..17de3eb
--- /dev/null
+++ b/chrome/browser/ash/guest_os/guest_os_file_watcher_unittest.cc
@@ -0,0 +1,91 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/guest_os/guest_os_file_watcher.h"
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/callback_helpers.h"
+#include "base/test/bind.h"
+#include "base/test/task_environment.h"
+#include "chrome/browser/ash/guest_os/dbus_test_helper.h"
+#include "chrome/browser/ash/guest_os/public/types.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace guest_os {
+
+class GuestOsFileWatcherTest : public testing::Test,
+                               public guest_os::FakeVmServicesHelper {
+ public:
+  GuestOsFileWatcherTest() {
+    watcher_callback_ = base::BindLambdaForTesting(
+        [this](const base::FilePath& path, bool) { last_event_path_ = path; });
+    signal_.set_owner_id(owner_id_);
+    signal_.set_vm_name(guest_id_.vm_name);
+    signal_.set_container_name(guest_id_.container_name);
+  }
+
+  content::BrowserTaskEnvironment task_environment_;
+  TestingProfile profile_;
+  std::string owner_id_{"owner-id"};
+  GuestId guest_id_{VmType::UNKNOWN, "vm_name", ""};
+  absl::optional<base::FilePath> last_event_path_;
+  vm_tools::cicerone::FileWatchTriggeredSignal signal_;
+  base::FilePathWatcher::Callback watcher_callback_;
+};
+
+TEST_F(GuestOsFileWatcherTest, WatchNotTriggeredForWrongOwnerId) {
+  GuestOsFileWatcher watcher("wrong-id", guest_id_, base::FilePath(),
+                             base::FilePath());
+
+  watcher.Watch(watcher_callback_, base::DoNothing());
+  task_environment_.RunUntilIdle();
+  FakeCiceroneClient()->NotifyFileWatchTriggered(signal_);
+
+  EXPECT_EQ(last_event_path_, absl::nullopt);
+  EXPECT_EQ(FakeCiceroneClient()->add_file_watch_call_count(), 1);
+}
+
+TEST_F(GuestOsFileWatcherTest, WatchNotTriggeredForWrongContainerId) {
+  GuestOsFileWatcher watcher(owner_id_,
+                             GuestId(VmType::UNKNOWN, "DifferentVm", ""),
+                             base::FilePath(), base::FilePath());
+
+  watcher.Watch(watcher_callback_, base::DoNothing());
+  task_environment_.RunUntilIdle();
+  FakeCiceroneClient()->NotifyFileWatchTriggered(signal_);
+
+  EXPECT_EQ(last_event_path_, absl::nullopt);
+  EXPECT_EQ(FakeCiceroneClient()->add_file_watch_call_count(), 1);
+}
+
+// Tests the full lifecycle - creating a watch, triggered with the right values,
+// stops being triggered after getting destroyed.
+TEST_F(GuestOsFileWatcherTest, WatchFullLifecycle) {
+  auto watcher = std::make_unique<GuestOsFileWatcher>(
+      owner_id_, guest_id_, base::FilePath("/mnt/fuse"),
+      base::FilePath("a/path"));
+  signal_.set_path("a/path");
+  watcher->Watch(watcher_callback_, base::DoNothing());
+  task_environment_.RunUntilIdle();
+  EXPECT_EQ(FakeCiceroneClient()->add_file_watch_call_count(), 1);
+
+  FakeCiceroneClient()->NotifyFileWatchTriggered(signal_);
+  EXPECT_EQ(last_event_path_, base::FilePath("/mnt/fuse/a/path"));
+
+  // Should stop getting called after destroying the watcher.
+  last_event_path_ = absl::nullopt;
+  watcher.reset();
+
+  EXPECT_EQ(FakeCiceroneClient()->remove_file_watch_call_count(), 1);
+  FakeCiceroneClient()->NotifyFileWatchTriggered(signal_);
+  EXPECT_EQ(last_event_path_, absl::nullopt);
+}
+
+}  // namespace guest_os
diff --git a/chrome/browser/ash/guest_os/guest_os_test_helpers.cc b/chrome/browser/ash/guest_os/guest_os_test_helpers.cc
index 592f83e5..ee5f91e 100644
--- a/chrome/browser/ash/guest_os/guest_os_test_helpers.cc
+++ b/chrome/browser/ash/guest_os/guest_os_test_helpers.cc
@@ -3,12 +3,10 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ash/guest_os/guest_os_test_helpers.h"
+
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/ash/guest_os/public/types.h"
 
-#ifndef CHROME_BROWSER_ASH_GUEST_OS_PUBLIC_GUEST_OS_TEST_HELPERS_H_
-#define CHROME_BROWSER_ASH_GUEST_OS_PUBLIC_GUEST_OS_TEST_HELPERS_H_
-
 namespace guest_os {
 
 MockMountProvider::MockMountProvider()
@@ -30,6 +28,10 @@
   return container_id_;
 }
 
+VmType MockMountProvider::vm_type() {
+  return VmType::PLUGIN_VM;
+}
+
 void MockMountProvider::Prepare(
     base::OnceCallback<
         void(bool success, int cid, int port, base::FilePath homedir)>
@@ -37,10 +39,10 @@
   std::move(callback).Run(true, 41, 1234, base::FilePath());
 }
 
-VmType MockMountProvider::vm_type() {
-  return VmType::PLUGIN_VM;
+std::unique_ptr<GuestOsFileWatcher> MockMountProvider::CreateFileWatcher(
+    base::FilePath mount_path,
+    base::FilePath relative_path) {
+  return nullptr;
 }
 
 }  // namespace guest_os
-
-#endif  // CHROME_BROWSER_ASH_GUEST_OS_PUBLIC_GUEST_OS_TEST_HELPERS_H_
diff --git a/chrome/browser/ash/guest_os/guest_os_test_helpers.h b/chrome/browser/ash/guest_os/guest_os_test_helpers.h
index 93f16c9..f23a2362 100644
--- a/chrome/browser/ash/guest_os/guest_os_test_helpers.h
+++ b/chrome/browser/ash/guest_os/guest_os_test_helpers.h
@@ -24,6 +24,10 @@
                void(bool success, int cid, int port, base::FilePath homedir)>
                    callback) override;
 
+  std::unique_ptr<GuestOsFileWatcher> CreateFileWatcher(
+      base::FilePath mount_path,
+      base::FilePath relative_path) override;
+
   Profile* profile_;
   guest_os::GuestId container_id_;
 };
diff --git a/chrome/browser/ash/guest_os/public/guest_os_mount_provider.h b/chrome/browser/ash/guest_os/public/guest_os_mount_provider.h
index 22a93304..b6cc405 100644
--- a/chrome/browser/ash/guest_os/public/guest_os_mount_provider.h
+++ b/chrome/browser/ash/guest_os/public/guest_os_mount_provider.h
@@ -6,10 +6,12 @@
 #define CHROME_BROWSER_ASH_GUEST_OS_PUBLIC_GUEST_OS_MOUNT_PROVIDER_H_
 
 #include <string>
+
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/guest_os/guest_id.h"
+#include "chrome/browser/ash/guest_os/guest_os_file_watcher.h"
 #include "chrome/browser/ash/guest_os/public/types.h"
 
 class Profile;
@@ -46,6 +48,14 @@
   // Requests the provider to unmount.
   void Unmount();
 
+  // Creates a file watcher for the given path, specified by `mount_path` as the
+  // path to where the volume is mounted and `relative_path` is the path to
+  // watch relative to `mount_path`. The watcher starts off idle, call Watch to
+  // start watching.
+  virtual std::unique_ptr<GuestOsFileWatcher> CreateFileWatcher(
+      base::FilePath mount_path,
+      base::FilePath relative_path) = 0;
+
  protected:
   // Called prior to mounting a volume, for the mount provider to do any
   // needed setup (e.g. ensure the VM is running). Must call `callback` once
diff --git a/chrome/browser/ash/guest_os/public/guest_os_terminal_provider.h b/chrome/browser/ash/guest_os/public/guest_os_terminal_provider.h
index 766b54cf..9a03a14 100644
--- a/chrome/browser/ash/guest_os/public/guest_os_terminal_provider.h
+++ b/chrome/browser/ash/guest_os/public/guest_os_terminal_provider.h
@@ -23,8 +23,8 @@
   virtual std::string Label() = 0;
 
   // TODO(b/233287586): While we're migrating, some Crostini-specific code still
-  // needs a ContainerId. Eventually this should always be nullopt and then
-  // removed.
+  // needs a guest_os::GuestId. Eventually this should always be nullopt and
+  // then removed.
   virtual absl::optional<guest_os::GuestId> CrostiniContainerId() = 0;
 
  private:
diff --git a/chrome/browser/ash/input_method/assistive_suggester.cc b/chrome/browser/ash/input_method/assistive_suggester.cc
index cbe1709d..3cd03dd 100644
--- a/chrome/browser/ash/input_method/assistive_suggester.cc
+++ b/chrome/browser/ash/input_method/assistive_suggester.cc
@@ -138,10 +138,6 @@
   return engine_id == "xkb:us::eng";
 }
 
-bool IsLacrosEnabled() {
-  return base::FeatureList::IsEnabled(chromeos::features::kLacrosSupport);
-}
-
 void RecordTextInputStateMetric(AssistiveTextInputState state) {
   base::UmaHistogramEnumeration("InputMethod.Assistive.MultiWord.InputState",
                                 state);
@@ -151,11 +147,6 @@
     PrefService* pref_service,
     const std::string& engine_id,
     const AssistiveSuggesterSwitch::EnabledSuggestions& enabled_suggestions) {
-  if (IsLacrosEnabled()) {
-    RecordTextInputStateMetric(AssistiveTextInputState::kUnsupportedClient);
-    return;
-  }
-
   if (!enabled_suggestions.multi_word_suggestions) {
     RecordTextInputStateMetric(
         AssistiveTextInputState::kFeatureBlockedByDenylist);
diff --git a/chrome/browser/ash/input_method/assistive_suggester_unittest.cc b/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
index 11cf7cf..7197d241 100644
--- a/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
+++ b/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
@@ -342,7 +342,7 @@
       AssistiveTextInputState::kFeatureBlockedByPreference, 1);
 }
 
-TEST_F(AssistiveSuggesterTest, RecordsMultiWordTextInputAsDisabledByLacros) {
+TEST_F(AssistiveSuggesterTest, RecordsMultiWordTextInputAsEnabledByLacros) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{features::kAssistMultiWord,
@@ -361,7 +361,7 @@
       "InputMethod.Assistive.MultiWord.InputState", 1);
   histogram_tester_.ExpectUniqueSample(
       "InputMethod.Assistive.MultiWord.InputState",
-      AssistiveTextInputState::kUnsupportedClient, 1);
+      AssistiveTextInputState::kFeatureEnabled, 1);
 }
 
 TEST_F(AssistiveSuggesterTest,
diff --git a/chrome/browser/ash/input_method/assistive_window_controller.cc b/chrome/browser/ash/input_method/assistive_window_controller.cc
index 8b352d29..167bbcd 100644
--- a/chrome/browser/ash/input_method/assistive_window_controller.cc
+++ b/chrome/browser/ash/input_method/assistive_window_controller.cc
@@ -36,10 +36,6 @@
   return parent;
 }
 
-bool IsLacrosEnabled() {
-  return base::FeatureList::IsEnabled(chromeos::features::kLacrosSupport);
-}
-
 }  // namespace
 
 AssistiveWindowController::AssistiveWindowController(
diff --git a/chrome/browser/ash/kerberos/kerberos_credentials_manager_test.cc b/chrome/browser/ash/kerberos/kerberos_credentials_manager_test.cc
index cb30358..d5dec14 100644
--- a/chrome/browser/ash/kerberos/kerberos_credentials_manager_test.cc
+++ b/chrome/browser/ash/kerberos/kerberos_credentials_manager_test.cc
@@ -154,7 +154,7 @@
       : scoped_user_manager_(
             std::make_unique<testing::NiceMock<MockUserManager>>()),
         local_state_(TestingBrowserProcess::GetGlobal()) {
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    SessionManagerClient::InitializeFakeInMemory();
     KerberosClient::InitializeFake();
     client_test_interface()->SetTaskDelay(base::TimeDelta());
 
@@ -192,7 +192,7 @@
     profile_.reset();
     UserSessionManager::GetInstance()->Shutdown();
     KerberosClient::Shutdown();
-    chromeos::SessionManagerClient::Shutdown();
+    SessionManagerClient::Shutdown();
   }
 
   void SetPref(const char* name, base::Value value) {
diff --git a/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc b/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
index d8bd1bf..e20797a 100644
--- a/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
+++ b/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
@@ -100,8 +100,7 @@
         extensions::api::app_runtime::OnLaunched::kEventName) {
       return;
     }
-    ASSERT_TRUE(event.event_args);
-    const base::Value& arg_value = event.event_args->GetListDeprecated()[0];
+    const base::Value& arg_value = event.event_args[0];
     if (event.restrict_to_browser_context)
       EXPECT_EQ(context_, event.restrict_to_browser_context);
 
diff --git a/chrome/browser/ash/login/arc_terms_of_service_browsertest.cc b/chrome/browser/ash/login/arc_terms_of_service_browsertest.cc
index 43cb3b9f..8d0f421 100644
--- a/chrome/browser/ash/login/arc_terms_of_service_browsertest.cc
+++ b/chrome/browser/ash/login/arc_terms_of_service_browsertest.cc
@@ -636,7 +636,7 @@
 
   void SetUpInProcessBrowserTestFixture() override {
     ArcTermsOfServiceScreenTest::SetUpInProcessBrowserTestFixture();
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    SessionManagerClient::InitializeFakeInMemory();
     InitializePolicy();
   }
 
@@ -698,8 +698,8 @@
   }
 
  private:
-  chromeos::FakeSessionManagerClient* session_manager_client() {
-    return chromeos::FakeSessionManagerClient::Get();
+  FakeSessionManagerClient* session_manager_client() {
+    return FakeSessionManagerClient::Get();
   }
 
   void RefreshDevicePolicy() { policy_helper()->RefreshDevicePolicy(); }
diff --git a/chrome/browser/ash/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/ash/login/auth/cryptohome_authenticator_unittest.cc
index 92a353c..2d3fddf 100644
--- a/chrome/browser/ash/login/auth/cryptohome_authenticator_unittest.cc
+++ b/chrome/browser/ash/login/auth/cryptohome_authenticator_unittest.cc
@@ -35,11 +35,11 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/cryptohome/account_identifier_operators.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "components/ownership/mock_owner_key_util.h"
 #include "components/user_manager/scoped_user_manager.h"
diff --git a/chrome/browser/ash/login/crash_restore_browsertest.cc b/chrome/browser/ash/login/crash_restore_browsertest.cc
index d512400..14c460ec 100644
--- a/chrome/browser/ash/login/crash_restore_browsertest.cc
+++ b/chrome/browser/ash/login/crash_restore_browsertest.cc
@@ -32,7 +32,7 @@
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/user_manager/user.h"
diff --git a/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover.cc b/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover.cc
index e232c14..9dbf72d 100644
--- a/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover.cc
@@ -26,8 +26,8 @@
 #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user.h"
diff --git a/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover.h b/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover.h
index b7e6dd4..4b83536 100644
--- a/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover.h
+++ b/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover.h
@@ -12,7 +12,7 @@
 #include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "components/user_manager/user_manager.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/user_activity/user_activity_detector.h"
diff --git a/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover_unittest.cc b/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover_unittest.cc
index 863885c..06316e8 100644
--- a/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover_unittest.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_mode_resources_remover_unittest.cc
@@ -15,7 +15,7 @@
 #include "base/values.h"
 #include "chrome/browser/ash/login/demo_mode/demo_mode_test_helper.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/user_manager/scoped_user_manager.h"
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_create_keys_operation.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_create_keys_operation.cc
index e1319ea..87384a46 100644
--- a/chrome/browser/ash/login/easy_unlock/easy_unlock_create_keys_operation.cc
+++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_create_keys_operation.cc
@@ -20,9 +20,9 @@
 #include "base/strings/string_util.h"
 #include "chrome/browser/ash/login/easy_unlock/easy_unlock_key_manager.h"
 #include "chrome/browser/ash/login/easy_unlock/easy_unlock_types.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/easy_unlock/easy_unlock_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "crypto/encryptor.h"
 #include "crypto/random.h"
 #include "crypto/symmetric_key.h"
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_get_keys_operation.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_get_keys_operation.cc
index 83914c20..5d60f187 100644
--- a/chrome/browser/ash/login/easy_unlock/easy_unlock_get_keys_operation.cc
+++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_get_keys_operation.cc
@@ -13,8 +13,8 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "chrome/browser/ash/login/easy_unlock/easy_unlock_key_manager.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_remove_keys_operation.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_remove_keys_operation.cc
index b366193..20cd4e3 100644
--- a/chrome/browser/ash/login/easy_unlock/easy_unlock_remove_keys_operation.cc
+++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_remove_keys_operation.cc
@@ -10,7 +10,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "chrome/browser/ash/login/easy_unlock/easy_unlock_key_manager.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 
 namespace ash {
diff --git a/chrome/browser/ash/login/encryption_migration_browsertest.cc b/chrome/browser/ash/login/encryption_migration_browsertest.cc
index 63a4df7..c8a39a8 100644
--- a/chrome/browser/ash/login/encryption_migration_browsertest.cc
+++ b/chrome/browser/ash/login/encryption_migration_browsertest.cc
@@ -25,10 +25,10 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/account_identifier_operators.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/known_user.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc b/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc
index 54e99a1..0c65a19 100644
--- a/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc
+++ b/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc
@@ -31,9 +31,9 @@
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chromeos/ash/components/dbus/system_clock/system_clock_client.h"
 #include "chromeos/ash/components/dbus/system_clock/system_clock_sync_observation.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/install_attributes_client.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/device_event_log/device_event_log.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
diff --git a/chrome/browser/ash/login/enrollment/enrollment_screen.cc b/chrome/browser/ash/login/enrollment/enrollment_screen.cc
index 2b147087..1c7851fa 100644
--- a/chrome/browser/ash/login/enrollment/enrollment_screen.cc
+++ b/chrome/browser/ash/login/enrollment/enrollment_screen.cc
@@ -33,10 +33,10 @@
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/lifetime/browser_shutdown.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_util.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/install_attributes_util.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/user_manager/user_manager.h"
 #include "google_apis/gaia/gaia_auth_util.h"
diff --git a/chrome/browser/ash/login/error_screen_browsertest.cc b/chrome/browser/ash/login/error_screen_browsertest.cc
index 78e640201..b993bc3 100644
--- a/chrome/browser/ash/login/error_screen_browsertest.cc
+++ b/chrome/browser/ash/login/error_screen_browsertest.cc
@@ -29,8 +29,8 @@
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/shill/shill_profile_client.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ash/login/existing_user_controller.cc b/chrome/browser/ash/login/existing_user_controller.cc
index bd770cd..3dad9dd 100644
--- a/chrome/browser/ash/login/existing_user_controller.cc
+++ b/chrome/browser/ash/login/existing_user_controller.cc
@@ -99,9 +99,9 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/ash/components/hibernate/buildflags.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "components/account_id/account_id.h"
 #include "components/google/core/common/google_util.h"
diff --git a/chrome/browser/ash/login/existing_user_controller_browsertest.cc b/chrome/browser/ash/login/existing_user_controller_browsertest.cc
index 3bf97d4c..5c1048a3 100644
--- a/chrome/browser/ash/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/ash/login/existing_user_controller_browsertest.cc
@@ -73,9 +73,9 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/ash/components/dbus/authpolicy/fake_authpolicy_client.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "components/account_id/account_id.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
diff --git a/chrome/browser/ash/login/guest_login_browsertest.cc b/chrome/browser/ash/login/guest_login_browsertest.cc
index 3518f39b..6ec0712 100644
--- a/chrome/browser/ash/login/guest_login_browsertest.cc
+++ b/chrome/browser/ash/login/guest_login_browsertest.cc
@@ -19,8 +19,8 @@
 #include "chrome/browser/ui/webui/chromeos/login/user_creation_screen_handler.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/flags_ui/feature_entry_macros.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ash/login/lock/screen_locker_unittest.cc b/chrome/browser/ash/login/lock/screen_locker_unittest.cc
index 89174b5a..c9873aa9 100644
--- a/chrome/browser/ash/login/lock/screen_locker_unittest.cc
+++ b/chrome/browser/ash/login/lock/screen_locker_unittest.cc
@@ -37,11 +37,11 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/ash/components/dbus/biod/biod_client.h"
 #include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/audio/cras_audio_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "components/account_id/account_id.h"
diff --git a/chrome/browser/ash/login/login_browsertest.cc b/chrome/browser/ash/login/login_browsertest.cc
index 7e361fd9..2b35e87 100644
--- a/chrome/browser/ash/login/login_browsertest.cc
+++ b/chrome/browser/ash/login/login_browsertest.cc
@@ -47,7 +47,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/interactive_test_utils.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/user_manager/known_user.h"
diff --git a/chrome/browser/ash/login/oobe_browsertest.cc b/chrome/browser/ash/login/oobe_browsertest.cc
index 2c220ad2..cd7deb68 100644
--- a/chrome/browser/ash/login/oobe_browsertest.cc
+++ b/chrome/browser/ash/login/oobe_browsertest.cc
@@ -35,9 +35,9 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/key.pb.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/known_user.h"
 #include "components/user_manager/user.h"
diff --git a/chrome/browser/ash/login/oobe_interactive_ui_test.cc b/chrome/browser/ash/login/oobe_interactive_ui_test.cc
index 02c5f868..b0b614e 100644
--- a/chrome/browser/ash/login/oobe_interactive_ui_test.cc
+++ b/chrome/browser/ash/login/oobe_interactive_ui_test.cc
@@ -167,7 +167,7 @@
 void WaitForGaiaSignInScreen(bool wait_for_arc_preloading) {
   OobeScreenWaiter(GaiaView::kScreenId).Wait();
   test::OobeJS()
-      .CreateFocusWaiter({"gaia-signin", "signin-frame-dialog", "signin-frame"})
+      .CreateVisibilityWaiter(true, {"gaia-signin", "signin-frame-dialog"})
       ->Wait();
 
   // Arc terms of service content gets preloaded when GAIA screen is shown,
diff --git a/chrome/browser/ash/login/quick_unlock/pin_migration_browsertest.cc b/chrome/browser/ash/login/quick_unlock/pin_migration_browsertest.cc
index 2b21f1b..5710d2e 100644
--- a/chrome/browser/ash/login/quick_unlock/pin_migration_browsertest.cc
+++ b/chrome/browser/ash/login/quick_unlock/pin_migration_browsertest.cc
@@ -10,8 +10,8 @@
 #include "chrome/browser/ash/login/quick_unlock/quick_unlock_storage.h"
 #include "chrome/browser/ash/login/startup_utils.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc
index d3a9340..25ce30a4 100644
--- a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc
+++ b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc
@@ -19,8 +19,8 @@
 #include "chrome/browser/ash/login/quick_unlock/quick_unlock_utils.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 
 namespace ash::quick_unlock {
 namespace {
diff --git a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc
index 5a2eb85..66bd610 100644
--- a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc
+++ b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc
@@ -17,9 +17,9 @@
 #include "chrome/browser/ash/login/quick_unlock/fake_pin_salt_storage.h"
 #include "chrome/browser/ash/login/quick_unlock/pin_backend.h"
 #include "chrome/browser/ash/login/quick_unlock/quick_unlock_utils.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/login/saml/saml_browsertest.cc b/chrome/browser/ash/login/saml/saml_browsertest.cc
index ae75bd3..d2ac661 100644
--- a/chrome/browser/ash/login/saml/saml_browsertest.cc
+++ b/chrome/browser/ash/login/saml/saml_browsertest.cc
@@ -72,14 +72,14 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/attestation/fake_attestation_client.h"
 #include "chromeos/dbus/attestation/interface.pb.h"
 #include "chromeos/dbus/constants/attestation_constants.h"
 #include "chromeos/dbus/cryptohome/key.pb.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings_types.h"
@@ -148,7 +148,7 @@
                                            "saml-close-button"};
 constexpr test::UIPath kSamlBackButton = {"gaia-signin", "signin-frame-dialog",
                                           "saml-back-button"};
-const test::UIPath kGaiaLoading = {"gaia-signin", "gaia-loading"};
+const test::UIPath kGaiaLoading = {"gaia-signin", "step-loading"};
 const test::UIPath kSamlInterstitial = {"gaia-signin", "saml-interstitial"};
 
 constexpr test::UIPath kFatalErrorActionButton = {"signin-fatal-error",
diff --git a/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc b/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc
index b7b7295..1bcf04a 100644
--- a/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc
+++ b/chrome/browser/ash/login/saml/saml_lockscreen_browsertest.cc
@@ -18,13 +18,13 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/ui/login/login_handler.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/ash/components/network/proxy/proxy_config_handler.h"
 #include "chromeos/dbus/shill/fake_shill_manager_client.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_handler_callbacks.h"
-#include "chromeos/network/network_handler_test_helper.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "components/account_id/account_id.h"
 #include "components/network_session_configurator/common/network_switches.h"
 #include "components/proxy_config/proxy_config_dictionary.h"
diff --git a/chrome/browser/ash/login/screens/enable_adb_sideloading_screen.cc b/chrome/browser/ash/login/screens/enable_adb_sideloading_screen.cc
index 0101349..13009c23 100644
--- a/chrome/browser/ash/login/screens/enable_adb_sideloading_screen.cc
+++ b/chrome/browser/ash/login/screens/enable_adb_sideloading_screen.cc
@@ -71,8 +71,7 @@
 }
 
 void EnableAdbSideloadingScreen::ShowImpl() {
-  chromeos::SessionManagerClient* client =
-      chromeos::SessionManagerClient::Get();
+  SessionManagerClient* client = SessionManagerClient::Get();
   client->QueryAdbSideload(
       base::BindOnce(&EnableAdbSideloadingScreen::OnQueryAdbSideload,
                      weak_ptr_factory_.GetWeakPtr()));
@@ -127,8 +126,7 @@
 }
 
 void EnableAdbSideloadingScreen::OnEnable() {
-  chromeos::SessionManagerClient* client =
-      chromeos::SessionManagerClient::Get();
+  SessionManagerClient* client = SessionManagerClient::Get();
   client->EnableAdbSideload(
       base::BindOnce(&EnableAdbSideloadingScreen::OnEnableAdbSideload,
                      weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ash/login/screens/enable_debugging_screen.cc b/chrome/browser/ash/login/screens/enable_debugging_screen.cc
index 9baa265..5583e246 100644
--- a/chrome/browser/ash/login/screens/enable_debugging_screen.cc
+++ b/chrome/browser/ash/login/screens/enable_debugging_screen.cc
@@ -12,10 +12,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/prefs/pref_service.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/chrome/browser/ash/login/screens/encryption_migration_screen.cc b/chrome/browser/ash/login/screens/encryption_migration_screen.cc
index 4afd8f88..c4b88cc 100644
--- a/chrome/browser/ash/login/screens/encryption_migration_screen.cc
+++ b/chrome/browser/ash/login/screens/encryption_migration_screen.cc
@@ -30,11 +30,11 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/device_service.h"
diff --git a/chrome/browser/ash/login/screens/encryption_migration_screen.h b/chrome/browser/ash/login/screens/encryption_migration_screen.h
index c64febc8b..0de5aaa 100644
--- a/chrome/browser/ash/login/screens/encryption_migration_screen.h
+++ b/chrome/browser/ash/login/screens/encryption_migration_screen.h
@@ -18,9 +18,9 @@
 #include "ash/components/cryptohome/cryptohome_parameters.h"
 #include "chrome/browser/ash/login/ui/login_feedback.h"
 #include "chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/wake_lock.mojom.h"
 #include "third_party/cros_system_api/dbus/cryptohome/dbus-constants.h"
diff --git a/chrome/browser/ash/login/screens/encryption_migration_screen_unittest.cc b/chrome/browser/ash/login/screens/encryption_migration_screen_unittest.cc
index 614b47d..f137024c 100644
--- a/chrome/browser/ash/login/screens/encryption_migration_screen_unittest.cc
+++ b/chrome/browser/ash/login/screens/encryption_migration_screen_unittest.cc
@@ -16,10 +16,10 @@
 #include "chrome/browser/ash/login/users/mock_user_manager.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_webui_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/account_identifier_operators.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/user_names.h"
diff --git a/chrome/browser/ash/login/screens/error_screen.cc b/chrome/browser/ash/login/screens/error_screen.cc
index 79eb002..3c05d38e 100644
--- a/chrome/browser/ash/login/screens/error_screen.cc
+++ b/chrome/browser/ash/login/screens/error_screen.cc
@@ -31,6 +31,7 @@
 #include "chrome/browser/ui/webui/chromeos/connectivity_diagnostics_dialog.h"
 #include "chrome/browser/ui/webui/chromeos/internet_detail_dialog.h"
 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #include "chrome/grit/browser_resources.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
 #include "chromeos/ash/components/network/portal_detector/network_portal_detector.h"
@@ -83,11 +84,13 @@
 constexpr const char kUserActionReloadGaia[] = "reload-gaia";
 constexpr const char kUserActionCancelReset[] = "cancel-reset";
 constexpr const char kUserActionCancel[] = "cancel";
+constexpr const char kUserActionContinueAppLaunch[] = "continue-app-launch";
+constexpr const char kUserActionLaunchHelpApp[] = "launch-help-app";
 constexpr const char kUserActionOfflineLogin[] = "offline-login";
 
-ErrorScreen::ErrorScreen(ErrorScreenView* view)
+ErrorScreen::ErrorScreen(base::WeakPtr<ErrorScreenView> view)
     : BaseScreen(ErrorScreenView::kScreenId, OobeScreenPriority::DEFAULT),
-      view_(view) {
+      view_(std::move(view)) {
   network_state_informer_ = new NetworkStateInformer();
   network_state_informer_->Init();
   NetworkHandler::Get()->network_connection_handler()->AddObserver(this);
@@ -151,11 +154,6 @@
     captive_portal_window_proxy_->Close();
 }
 
-void ErrorScreen::OnViewDestroyed(ErrorScreenView* view) {
-  if (view_ == view)
-    view_ = nullptr;
-}
-
 void ErrorScreen::SetUIState(NetworkError::UIState ui_state) {
   ui_state_ = ui_state;
   if (view_)
@@ -283,7 +281,8 @@
     view_->Hide();
 }
 
-void ErrorScreen::OnUserActionDeprecated(const std::string& action_id) {
+void ErrorScreen::OnUserAction(const base::Value::List& args) {
+  const std::string& action_id = args[0].GetString();
   if (action_id == kUserActionShowCaptivePortalClicked) {
     ShowCaptivePortal();
   } else if (action_id == kUserActionOpenInternetDialog) {
@@ -308,8 +307,14 @@
     Hide();
   } else if (action_id == kUserActionOfflineLogin) {
     OnOfflineLoginClicked();
+  } else if (action_id == kUserActionContinueAppLaunch) {
+    OnContinueAppLaunchButtonClicked();
+  } else if (action_id == kUserActionLaunchHelpApp) {
+    CHECK_EQ(args.size(), 2);
+    const int help_topic_id = args[1].GetInt();
+    LaunchHelpApp(help_topic_id);
   } else {
-    BaseScreen::OnUserActionDeprecated(action_id);
+    BaseScreen::OnUserAction(args);
   }
 }
 
@@ -388,8 +393,27 @@
 }
 
 void ErrorScreen::OnReloadGaiaClicked() {
-  if (view_)
-    view_->OnReloadGaiaClicked();
+  DCHECK_EQ(parent_screen_, GaiaView::kScreenId.AsId());
+  WizardController::default_controller()
+      ->GetScreen<GaiaScreen>()
+      ->ReloadGaiaAuthenticator();
+}
+
+void ErrorScreen::OnContinueAppLaunchButtonClicked() {
+  DCHECK_EQ(parent_screen_, AppLaunchSplashScreenView::kScreenId.AsId());
+  // TODO(https://crbug.com/1199816, dkuzmin): Use exit_callback_ once
+  // available
+  auto* oobe_ui = LoginDisplayHost::default_host()->GetOobeUI();
+  oobe_ui->GetView<AppLaunchSplashScreenHandler>()->ContinueAppLaunch();
+}
+
+void ErrorScreen::LaunchHelpApp(int help_topic_id) {
+  if (!help_app_.get()) {
+    help_app_ = new HelpAppLauncher(
+        LoginDisplayHost::default_host()->GetNativeWindow());
+  }
+  help_app_->ShowHelpTopic(
+      static_cast<HelpAppLauncher::HelpTopic>(help_topic_id));
 }
 
 void ErrorScreen::ConnectToNetworkRequested(const std::string& service_path) {
diff --git a/chrome/browser/ash/login/screens/error_screen.h b/chrome/browser/ash/login/screens/error_screen.h
index afbfe7b..834358a 100644
--- a/chrome/browser/ash/login/screens/error_screen.h
+++ b/chrome/browser/ash/login/screens/error_screen.h
@@ -10,6 +10,7 @@
 #include "ash/components/login/auth/login_performer.h"
 #include "base/callback_list.h"
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/ash/login/help_app_launcher.h"
 #include "chrome/browser/ash/login/screens/base_screen.h"
 #include "chrome/browser/ash/login/screens/network_error.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
@@ -28,7 +29,7 @@
                     public LoginPerformer::Delegate,
                     public NetworkConnectionObserver {
  public:
-  explicit ErrorScreen(ErrorScreenView* view);
+  explicit ErrorScreen(base::WeakPtr<ErrorScreenView> view);
 
   ErrorScreen(const ErrorScreen&) = delete;
   ErrorScreen& operator=(const ErrorScreen&) = delete;
@@ -62,10 +63,6 @@
   // Called when we're asked to hide captive portal dialog.
   void HideCaptivePortal();
 
-  // This method is called, when view is being destroyed. Note, if model
-  // is destroyed earlier then it has to call Unbind().
-  void OnViewDestroyed(ErrorScreenView* view);
-
   // Sets current UI state.
   virtual void SetUIState(NetworkError::UIState ui_state);
 
@@ -112,7 +109,7 @@
   // BaseScreen:
   void ShowImpl() override;
   void HideImpl() override;
-  void OnUserActionDeprecated(const std::string& action_id) override;
+  void OnUserAction(const base::Value::List& args) override;
 
  private:
   // LoginPerformer::Delegate overrides:
@@ -151,6 +148,12 @@
   // Handle user action to reload gaia.
   void OnReloadGaiaClicked();
 
+  // Handle user action to continue app launch.
+  void OnContinueAppLaunchButtonClicked();
+
+  // Handle user action to open learn more.
+  void LaunchHelpApp(int help_topic_id);
+
   // If show is true offline login flow is enabled from the error screen.
   void ShowOfflineLoginOption(bool show);
 
@@ -162,7 +165,7 @@
   void StartGuestSessionAfterOwnershipCheck(
       DeviceSettingsService::OwnershipStatus ownership_status);
 
-  ErrorScreenView* view_ = nullptr;
+  base::WeakPtr<ErrorScreenView> view_;
 
   // We have the guest login logic in this screen because it might be required
   // quite early during OOBE. When Login screen is not yet shown and existing
@@ -188,6 +191,9 @@
   // Callbacks to be invoked when a connection attempt is requested.
   base::RepeatingCallbackList<void()> connect_request_callbacks_;
 
+  // Help application used for help dialogs.
+  scoped_refptr<HelpAppLauncher> help_app_;
+
   base::WeakPtrFactory<ErrorScreen> weak_factory_{this};
 };
 
diff --git a/chrome/browser/ash/login/screens/gaia_screen.cc b/chrome/browser/ash/login/screens/gaia_screen.cc
index 6c4db14..fea7d02 100644
--- a/chrome/browser/ash/login/screens/gaia_screen.cc
+++ b/chrome/browser/ash/login/screens/gaia_screen.cc
@@ -91,6 +91,12 @@
   view_->Reset();
 }
 
+void GaiaScreen::ReloadGaiaAuthenticator() {
+  if (!view_)
+    return;
+  view_->ReloadGaiaAuthenticator();
+}
+
 void GaiaScreen::ShowImpl() {
   if (!view_)
     return;
diff --git a/chrome/browser/ash/login/screens/gaia_screen.h b/chrome/browser/ash/login/screens/gaia_screen.h
index f2355c4..301a4e74 100644
--- a/chrome/browser/ash/login/screens/gaia_screen.h
+++ b/chrome/browser/ash/login/screens/gaia_screen.h
@@ -55,6 +55,8 @@
   void ShowAllowlistCheckFailedError();
   // Reset authenticator.
   void Reset();
+  // Calls authenticator reload on JS side.
+  void ReloadGaiaAuthenticator();
 
   // ScreenBacklightObserver:
   void OnScreenBacklightStateChanged(
diff --git a/chrome/browser/ash/login/screens/hid_detection_screen.cc b/chrome/browser/ash/login/screens/hid_detection_screen.cc
index 8d4a16c6..193e295 100644
--- a/chrome/browser/ash/login/screens/hid_detection_screen.cc
+++ b/chrome/browser/ash/login/screens/hid_detection_screen.cc
@@ -7,7 +7,9 @@
 #include <memory>
 #include <utility>
 
+#include "ash/components/hid_detection/hid_detection_manager_impl.h"
 #include "ash/components/hid_detection/hid_detection_utils.h"
+#include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
@@ -75,6 +77,13 @@
   return *binder;
 }
 
+std::unique_ptr<hid_detection::HidDetectionManager>&
+GetHidDetectionManagerOverrideForTesting() {
+  static base::NoDestructor<std::unique_ptr<hid_detection::HidDetectionManager>>
+      hid_detection_manager;
+  return *hid_detection_manager;
+}
+
 }  // namespace
 
 // static
@@ -115,6 +124,18 @@
   if (view_)
     view_->Bind(this);
 
+  if (ash::features::IsOobeHidDetectionRevampEnabled()) {
+    const auto& hid_detection_manager_override =
+        GetHidDetectionManagerOverrideForTesting();
+    hid_detection_manager_ =
+        hid_detection_manager_override
+            ? std::unique_ptr<hid_detection::HidDetectionManager>(
+                  hid_detection_manager_override.get())
+            : std::make_unique<hid_detection::HidDetectionManagerImpl>(
+                  &content::GetDeviceService());
+    return;
+  }
+
   device::BluetoothAdapterFactory::Get()->GetAdapter(base::BindOnce(
       &HIDDetectionScreen::InitializeAdapter, weak_ptr_factory_.GetWeakPtr()));
   ConnectToInputDeviceManager();
@@ -136,6 +157,12 @@
   GetInputDeviceManagerBinderOverride() = std::move(binder);
 }
 
+// static
+void HIDDetectionScreen::OverrideHidDetectionManagerForTesting(
+    std::unique_ptr<hid_detection::HidDetectionManager> hid_detection_manager) {
+  GetHidDetectionManagerOverrideForTesting() = std::move(hid_detection_manager);
+}
+
 void HIDDetectionScreen::OnContinueButtonClicked() {
   hid_detection::RecordBluetoothPairingAttempts(num_pairing_attempts_);
   CleanupOnExit();
@@ -165,6 +192,11 @@
 
 void HIDDetectionScreen::CheckIsScreenRequired(
     base::OnceCallback<void(bool)> on_check_done) {
+  if (ash::features::IsOobeHidDetectionRevampEnabled()) {
+    hid_detection_manager_->GetIsHidDetectionRequired(std::move(on_check_done));
+    return;
+  }
+
   DCHECK(input_device_manager_);
   input_device_manager_->GetDevices(
       base::BindOnce(&HIDDetectionScreen::OnGetInputDevicesListForCheck,
@@ -185,6 +217,10 @@
   if (!is_hidden())
     return;
 
+  // TODO(gordonseto): Implement UI with OOBE Revamp flag enabled.
+  if (ash::features::IsOobeHidDetectionRevampEnabled())
+    return;
+
   if (adapter_)
     adapter_->AddObserver(this);
 
diff --git a/chrome/browser/ash/login/screens/hid_detection_screen.h b/chrome/browser/ash/login/screens/hid_detection_screen.h
index b909571..432a532 100644
--- a/chrome/browser/ash/login/screens/hid_detection_screen.h
+++ b/chrome/browser/ash/login/screens/hid_detection_screen.h
@@ -18,6 +18,7 @@
 // TODO(https://crbug.com/1164001): move to forward declaration.
 #include "chrome/browser/ash/login/wizard_context.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
+#include "ash/components/hid_detection/hid_detection_manager.h"
 #include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_device.h"
@@ -73,6 +74,12 @@
   static void OverrideInputDeviceManagerBinderForTesting(
       InputDeviceManagerBinder binder);
 
+  // Allows tests to override what HidDetectionManager implementation is used
+  // when the kOobeHidDetectionRevamp flag is enabled.
+  static void OverrideHidDetectionManagerForTesting(
+      std::unique_ptr<hid_detection::HidDetectionManager>
+          hid_detection_manager);
+
   void InputDeviceAddedForTesting(InputDeviceInfoPtr info);
   const absl::optional<Result>& get_exit_result_for_testing() const {
     return exit_result_for_testing_;
@@ -260,6 +267,8 @@
 
   size_t num_pairing_attempts_ = 0;
 
+  std::unique_ptr<hid_detection::HidDetectionManager> hid_detection_manager_;
+
   base::WeakPtrFactory<HIDDetectionScreen> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ash/login/screens/hid_detection_screen_browsertest.cc b/chrome/browser/ash/login/screens/hid_detection_screen_browsertest.cc
index 50fcaa8..bc06728 100644
--- a/chrome/browser/ash/login/screens/hid_detection_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/hid_detection_screen_browsertest.cc
@@ -2,13 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "ash/components/hid_detection/fake_hid_detection_manager.h"
 #include "ash/components/hid_detection/hid_detection_utils.h"
+#include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_chromeos_version_info.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ash/login/login_wizard.h"
 #include "chrome/browser/ash/login/screens/base_screen.h"
 #include "chrome/browser/ash/login/screens/hid_detection_screen.h"
@@ -52,9 +55,19 @@
 
 // TODO(crbug/1173782): use INSTANTIATE_TEST_SUITE_P to test this for
 // chromebox, chromebase, chromebit
-class HIDDetectionScreenChromeboxTest : public OobeBaseTest {
+class HIDDetectionScreenChromeboxTest
+    : public OobeBaseTest,
+      public testing::WithParamInterface<bool> {
  public:
-  HIDDetectionScreenChromeboxTest() = default;
+  HIDDetectionScreenChromeboxTest() {
+    if (GetParam()) {
+      scoped_feature_list_.InitAndEnableFeature(
+          ash::features::kOobeHidDetectionRevamp);
+    } else {
+      scoped_feature_list_.InitAndDisableFeature(
+          ash::features::kOobeHidDetectionRevamp);
+    }
+  }
 
   HIDDetectionScreenChromeboxTest(const HIDDetectionScreenChromeboxTest&) =
       delete;
@@ -161,16 +174,21 @@
   base::test::ScopedChromeOSVersionInfo version_{"DEVICETYPE=CHROMEBOX",
                                                  base::Time::Now()};
 
+  base::test::ScopedFeatureList scoped_feature_list_;
   base::HistogramTester histogram_tester_;
 };
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromeboxTest, NoDevicesConnected) {
+INSTANTIATE_TEST_SUITE_P(All,
+                         HIDDetectionScreenChromeboxTest,
+                         testing::Values(false));
+
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenChromeboxTest, NoDevicesConnected) {
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
   test::OobeJS().ExpectDisabledPath(kHidContinueButton);
   EXPECT_FALSE(GetExitResult().has_value());
 }
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromeboxTest,
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenChromeboxTest,
                        BluetoothPairingAttemptsSimultaneous) {
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
 
@@ -197,7 +215,7 @@
   AssertBluetoothPairingAttemptsCount(/*count=*/3);
 }
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromeboxTest,
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenChromeboxTest,
                        BluetoothPairingAttemptsSequential) {
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
 
@@ -216,7 +234,7 @@
   AssertBluetoothPairingAttemptsCount(/*count=*/2);
 }
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromeboxTest, MouseKeyboardStates) {
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenChromeboxTest, MouseKeyboardStates) {
   // NOTE: State strings match those in hid_detection_screen.cc.
   // No devices added yet
   EXPECT_EQ("searching", handler()->mouse_state_for_test());
@@ -261,7 +279,7 @@
 
 // Test that if there is any Bluetooth device connected on HID screen, the
 // Bluetooth adapter should not be disabled after advancing to the next screen.
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromeboxTest,
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenChromeboxTest,
                        BluetoothDeviceConnected) {
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
 
@@ -282,7 +300,7 @@
 
 // Test that if there is no Bluetooth device connected on HID screen, the
 // Bluetooth adapter should be disabled after advancing to the next screen.
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromeboxTest,
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenChromeboxTest,
                        NoBluetoothDeviceConnected) {
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
 
@@ -298,7 +316,7 @@
 
 // Start without devices, connect them and proceed to the network screen.
 // Network screen should be saved in the local state.
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromeboxTest, PRE_ResumableScreen) {
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenChromeboxTest, PRE_ResumableScreen) {
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
   test::OobeJS().ExpectDisabledPath(kHidContinueButton);
 
@@ -314,7 +332,7 @@
 
 // Start without devices, connect them. Flow should proceed to the saved screen
 // (network screen).
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromeboxTest, ResumableScreen) {
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenChromeboxTest, ResumableScreen) {
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
   hid_controller_.ConnectUSBDevices();
   test::OobeJS().ExpectEnabledPath(kHidContinueButton);
@@ -323,7 +341,7 @@
 }
 
 // Tests that the connected 'ticks' are shown when the devices are connected.
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromeboxTest, TestTicks) {
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenChromeboxTest, TestTicks) {
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
   // When touch screen is not detected, the whole touchscreen row is hidden
   test::OobeJS().ExpectHiddenPath(kHidTouchscreenEntry);
@@ -337,19 +355,57 @@
   ContinueToWelcomeScreen();
 }
 
-class HIDDetectionSkipTest : public HIDDetectionScreenChromeboxTest {
+// TODO(crbug.com/1299099): Remove when kOobeHidDetectionRevamp is launched.
+class HIDDetectionSkipTestLegacy : public HIDDetectionScreenChromeboxTest {
  public:
-  HIDDetectionSkipTest() {
+  HIDDetectionSkipTestLegacy() {
     hid_controller_.set_wait_until_idle_after_device_update(false);
     hid_controller_.ConnectUSBDevices();
   }
-  ~HIDDetectionSkipTest() override = default;
+  ~HIDDetectionSkipTestLegacy() override = default;
 
  protected:
   base::HistogramTester histogram_tester;
 };
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionSkipTest, BothDevicesPreConnected) {
+INSTANTIATE_TEST_SUITE_P(All,
+                         HIDDetectionSkipTestLegacy,
+                         testing::Values(false));
+
+IN_PROC_BROWSER_TEST_P(HIDDetectionSkipTestLegacy, BothDevicesPreConnected) {
+  OobeScreenWaiter(WelcomeView::kScreenId).Wait();
+  EXPECT_FALSE(GetExitResult().has_value());
+  histogram_tester.ExpectTotalCount("OOBE.HidDetectionScreen.HidConnected", 0);
+}
+
+class HIDDetectionSkipTest : public HIDDetectionScreenChromeboxTest {
+ public:
+  HIDDetectionSkipTest() {
+    auto fake_hid_detection_manager =
+        std::make_unique<hid_detection::FakeHidDetectionManager>();
+    fake_hid_detection_manager_ = fake_hid_detection_manager.get();
+    HIDDetectionScreen::OverrideHidDetectionManagerForTesting(
+        std::move(fake_hid_detection_manager));
+  }
+  ~HIDDetectionSkipTest() override = default;
+
+  void SetUpOnMainThread() override {
+    ASSERT_TRUE(fake_hid_detection_manager_
+                    ->HasPendingIsHidDetectionRequiredCallback());
+    fake_hid_detection_manager_->InvokePendingIsHidDetectionRequiredCallback(
+        /*required=*/false);
+    HIDDetectionScreenChromeboxTest::SetUpOnMainThread();
+  }
+
+ protected:
+  base::HistogramTester histogram_tester;
+
+  hid_detection::FakeHidDetectionManager* fake_hid_detection_manager_;
+};
+
+INSTANTIATE_TEST_SUITE_P(All, HIDDetectionSkipTest, testing::Values(true));
+
+IN_PROC_BROWSER_TEST_P(HIDDetectionSkipTest, HIDDetectionNotRequired) {
   OobeScreenWaiter(WelcomeView::kScreenId).Wait();
   EXPECT_FALSE(GetExitResult().has_value());
   histogram_tester.ExpectTotalCount("OOBE.HidDetectionScreen.HidConnected", 0);
@@ -361,7 +417,11 @@
       &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED};
 };
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionDeviceOwnedTest, NoScreen) {
+INSTANTIATE_TEST_SUITE_P(All,
+                         HIDDetectionDeviceOwnedTest,
+                         testing::Values(false));
+
+IN_PROC_BROWSER_TEST_P(HIDDetectionDeviceOwnedTest, NoScreen) {
   OobeScreenWaiter(GetFirstSigninScreen()).Wait();
 }
 
@@ -372,7 +432,11 @@
       &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_UNOWNED};
 };
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionOobeCompletedUnowned, ShowScreen) {
+INSTANTIATE_TEST_SUITE_P(All,
+                         HIDDetectionOobeCompletedUnowned,
+                         testing::Values(false));
+
+IN_PROC_BROWSER_TEST_P(HIDDetectionOobeCompletedUnowned, ShowScreen) {
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
 }
 
@@ -402,7 +466,11 @@
   LocalStateMixin local_state_mixin_{&mixin_host_, this};
 };
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenDisabledAfterRestartTest,
+INSTANTIATE_TEST_SUITE_P(All,
+                         HIDDetectionScreenDisabledAfterRestartTest,
+                         testing::Values(false));
+
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenDisabledAfterRestartTest,
                        PRE_SkipToUpdate) {
   OobeScreenWaiter(chromeos::WelcomeView::kScreenId).Wait();
 
@@ -411,7 +479,7 @@
       HIDDetectionView::kScreenId));
 }
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenDisabledAfterRestartTest,
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenDisabledAfterRestartTest,
                        SkipToUpdate) {
   OobeScreenWaiter(chromeos::WelcomeView::kScreenId).Wait();
   // The pref should persist restart.
@@ -439,6 +507,9 @@
 class HIDDetectionScreenChromebaseTest : public OobeBaseTest {
  public:
   HIDDetectionScreenChromebaseTest() {
+    scoped_feature_list_.InitAndDisableFeature(
+        ash::features::kOobeHidDetectionRevamp);
+
     hid_controller_.set_wait_until_idle_after_device_update(false);
     hid_controller_.AddTouchscreen();
   }
@@ -453,6 +524,8 @@
   // with only a touchscreen.
   base::test::ScopedChromeOSVersionInfo version_{"DEVICETYPE=CHROMEBASE",
                                                  base::Time::Now()};
+
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromebaseTest, TouchscreenDetected) {
@@ -481,7 +554,11 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(HIDDetectionScreenPreConnectedDeviceTest,
+INSTANTIATE_TEST_SUITE_P(All,
+                         HIDDetectionScreenPreConnectedDeviceTest,
+                         testing::Values(false));
+
+IN_PROC_BROWSER_TEST_P(HIDDetectionScreenPreConnectedDeviceTest,
                        MousePreConnected) {
   // Continue button should be enabled if at least one device is connected.
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
diff --git a/chrome/browser/ash/login/screens/marketing_opt_in_screen.cc b/chrome/browser/ash/login/screens/marketing_opt_in_screen.cc
index 1cdfd477..40234bae 100644
--- a/chrome/browser/ash/login/screens/marketing_opt_in_screen.cc
+++ b/chrome/browser/ash/login/screens/marketing_opt_in_screen.cc
@@ -32,6 +32,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -116,9 +117,13 @@
   const bool legal_footer_visible =
       email_opt_in_visible_ && countries_with_legal_footer.count(country_);
 
+  const bool cloud_gaming_enabled =
+      chromeos::features::IsCloudGamingDeviceEnabled();
+
   view_->Show(/*opt_in_visible=*/email_opt_in_visible_,
               /*opt_in_default_state=*/IsDefaultOptInCountry(),
-              /*legal_footer_visible=*/legal_footer_visible);
+              /*legal_footer_visible=*/legal_footer_visible,
+              /*cloud_gaming_enabled=*/cloud_gaming_enabled);
 
   // Mark the screen as shown for this user.
   PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs();
diff --git a/chrome/browser/ash/login/screens/marketing_opt_in_screen_browsertest.cc b/chrome/browser/ash/login/screens/marketing_opt_in_screen_browsertest.cc
index 33120a3..62c548c 100644
--- a/chrome/browser/ash/login/screens/marketing_opt_in_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/marketing_opt_in_screen_browsertest.cc
@@ -38,6 +38,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test.h"
 #include "mojo/public/c/system/trap.h"
@@ -45,6 +46,10 @@
 namespace ash {
 namespace {
 
+const test::UIPath kChromebookGameTitle = {"marketing-opt-in",
+                                           "marketingOptInGameDeviceTitle"};
+const test::UIPath kChromebookGameSubtitle = {
+    "marketing-opt-in", "marketingOptInGameDeviceSubtitle"};
 const test::UIPath kChromebookEmailToggle = {"marketing-opt-in",
                                              "chromebookUpdatesOption"};
 const test::UIPath kChromebookEmailToggleDiv = {"marketing-opt-in",
@@ -640,5 +645,44 @@
             MarketingOptInScreen::Result::NOT_APPLICABLE);
 }
 
+class MarketingOptInScreenTestGameDevice : public MarketingOptInScreenTest {
+ public:
+  MarketingOptInScreenTestGameDevice() {
+    feature_list_.Reset();
+    feature_list_.InitWithFeatures(
+        {
+            ::features::kOobeMarketingDoubleOptInCountriesSupported,
+            ::features::kOobeMarketingAdditionalCountriesSupported,
+            chromeos::features::kCloudGamingDevice,
+        },
+        {});
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(MarketingOptInScreenTestGameDevice,
+                       ScreenElementsVisible) {
+  PerformLogin();
+  OobeScreenExitWaiter(GetFirstSigninScreen()).Wait();
+  // Expect the screen to not have been shown before.
+  EXPECT_FALSE(ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
+      prefs::kOobeMarketingOptInScreenFinished));
+  LoginDisplayHost::default_host()->StartWizard(
+      MarketingOptInScreenView::kScreenId);
+
+  OobeScreenWaiter(MarketingOptInScreenView::kScreenId).Wait();
+  // check the Screen is Visible
+  test::OobeJS().ExpectVisiblePath(
+      {"marketing-opt-in", "marketingOptInOverviewDialog"});
+  // check the correct game mode title is visible
+  test::OobeJS().ExpectVisiblePath(kChromebookGameTitle);
+  // check the correct game mode description is visible
+  test::OobeJS().ExpectVisiblePath(kChromebookGameSubtitle);
+  TapOnGetStartedAndWaitForScreenExit();
+
+  // Expect the screen to be marked as shown.
+  EXPECT_TRUE(ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
+      prefs::kOobeMarketingOptInScreenFinished));
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/chrome/browser/ash/login/screens/mock_error_screen.cc b/chrome/browser/ash/login/screens/mock_error_screen.cc
index 2c21336b..377416a 100644
--- a/chrome/browser/ash/login/screens/mock_error_screen.cc
+++ b/chrome/browser/ash/login/screens/mock_error_screen.cc
@@ -9,7 +9,8 @@
 using ::testing::AtLeast;
 using ::testing::_;
 
-MockErrorScreen::MockErrorScreen(ErrorScreenView* view) : ErrorScreen(view) {}
+MockErrorScreen::MockErrorScreen(base::WeakPtr<ErrorScreenView> view)
+    : ErrorScreen(std::move(view)) {}
 
 MockErrorScreen::~MockErrorScreen() {}
 
@@ -34,10 +35,7 @@
   EXPECT_CALL(*this, MockUnbind()).Times(AtLeast(1));
 }
 
-MockErrorScreenView::~MockErrorScreenView() {
-  if (screen_)
-    screen_->OnViewDestroyed(this);
-}
+MockErrorScreenView::~MockErrorScreenView() = default;
 
 void MockErrorScreenView::Bind(ErrorScreen* screen) {
   screen_ = screen;
diff --git a/chrome/browser/ash/login/screens/mock_error_screen.h b/chrome/browser/ash/login/screens/mock_error_screen.h
index 07117f8..6e0047a 100644
--- a/chrome/browser/ash/login/screens/mock_error_screen.h
+++ b/chrome/browser/ash/login/screens/mock_error_screen.h
@@ -14,7 +14,7 @@
 
 class MockErrorScreen : public ErrorScreen {
  public:
-  explicit MockErrorScreen(ErrorScreenView* view);
+  explicit MockErrorScreen(base::WeakPtr<ErrorScreenView> view);
   ~MockErrorScreen() override;
 
   void FixCaptivePortal() override;
@@ -50,7 +50,6 @@
   MOCK_METHOD1(SetUIState, void(NetworkError::UIState ui_state));
   MOCK_METHOD1(SetIsPersistentError, void(bool is_persistent));
   MOCK_METHOD0(OnCancelButtonClicked, void());
-  MOCK_METHOD0(OnReloadGaiaClicked, void());
 
  private:
   ErrorScreen* screen_ = nullptr;
diff --git a/chrome/browser/ash/login/screens/pin_setup_screen_browsertest.cc b/chrome/browser/ash/login/screens/pin_setup_screen_browsertest.cc
index b7d827d0..2b0d4a19 100644
--- a/chrome/browser/ash/login/screens/pin_setup_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/pin_setup_screen_browsertest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/ash/login/wizard_controller.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/webui/chromeos/login/pin_setup_screen_handler.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/user_manager/user_type.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ash/login/screens/terms_of_service_screen_browsertest.cc b/chrome/browser/ash/login/screens/terms_of_service_screen_browsertest.cc
index eadd796..0c819a79f 100644
--- a/chrome/browser/ash/login/screens/terms_of_service_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/terms_of_service_screen_browsertest.cc
@@ -113,7 +113,7 @@
 
   void SetUpInProcessBrowserTestFixture() override {
     OobeBaseTest::SetUpInProcessBrowserTestFixture();
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    SessionManagerClient::InitializeFakeInMemory();
     InitializePolicy();
   }
 
@@ -206,8 +206,8 @@
     original_callback_.Run(result_.value());
   }
 
-  chromeos::FakeSessionManagerClient* session_manager_client() {
-    return chromeos::FakeSessionManagerClient::Get();
+  FakeSessionManagerClient* session_manager_client() {
+    return FakeSessionManagerClient::Get();
   }
 
   absl::optional<TermsOfServiceScreen::Result> result_;
@@ -361,8 +361,8 @@
     original_callback_.Run(result_.value());
   }
 
-  chromeos::FakeSessionManagerClient* session_manager_client() {
-    return chromeos::FakeSessionManagerClient::Get();
+  FakeSessionManagerClient* session_manager_client() {
+    return FakeSessionManagerClient::Get();
   }
 
   bool TosFileExists() {
diff --git a/chrome/browser/ash/login/screens/update_required_screen_browsertest.cc b/chrome/browser/ash/login/screens/update_required_screen_browsertest.cc
index 155c97b..8e8ef6f9 100644
--- a/chrome/browser/ash/login/screens/update_required_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/update_required_screen_browsertest.cc
@@ -32,10 +32,10 @@
 #include "chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/constants/dbus_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/test/browser_test.h"
 #include "dbus/object_path.h"
diff --git a/chrome/browser/ash/login/screens/update_required_screen_unittest.cc b/chrome/browser/ash/login/screens/update_required_screen_unittest.cc
index 460675d..34ca3766 100644
--- a/chrome/browser/ash/login/screens/update_required_screen_unittest.cc
+++ b/chrome/browser/ash/login/screens/update_required_screen_unittest.cc
@@ -20,12 +20,12 @@
 #include "chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/portal_detector/mock_network_portal_detector.h"
 #include "chromeos/ash/components/network/portal_detector/network_portal_detector.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
 #include "chromeos/dbus/update_engine/update_engine_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -74,7 +74,7 @@
     network_portal_detector::SetNetworkPortalDetector(
         mock_network_portal_detector_);
     mock_error_screen_ =
-        std::make_unique<MockErrorScreen>(mock_error_view_.get());
+        std::make_unique<MockErrorScreen>(mock_error_view_.AsWeakPtr());
 
     // Ensure proper behavior of `UpdateRequiredScreen`'s supporting objects.
     EXPECT_CALL(*mock_network_portal_detector_, IsEnabled())
@@ -93,7 +93,6 @@
 
     wizard_context_.reset();
     update_required_screen_.reset();
-    mock_error_view_.reset();
     mock_error_screen_.reset();
 
     network_portal_detector::Shutdown();
@@ -109,7 +108,7 @@
   // Accessory objects needed by `UpdateRequiredScreen`.
   TestLoginScreen test_login_screen_;
   std::unique_ptr<FakeUpdateRequiredScreenHandler> fake_view_;
-  std::unique_ptr<MockErrorScreenView> mock_error_view_;
+  MockErrorScreenView mock_error_view_;
   std::unique_ptr<MockErrorScreen> mock_error_screen_;
   std::unique_ptr<WizardContext> wizard_context_;
   // Will be deleted in `network_portal_detector::Shutdown()`.
diff --git a/chrome/browser/ash/login/screens/update_screen_unittest.cc b/chrome/browser/ash/login/screens/update_screen_unittest.cc
index a0e6f26c..ca216a3 100644
--- a/chrome/browser/ash/login/screens/update_screen_unittest.cc
+++ b/chrome/browser/ash/login/screens/update_screen_unittest.cc
@@ -15,13 +15,13 @@
 #include "chrome/browser/ash/login/wizard_context.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/portal_detector/mock_network_portal_detector.h"
 #include "chromeos/ash/components/network/portal_detector/network_portal_detector.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
 #include "chromeos/dbus/update_engine/update_engine_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -82,7 +82,8 @@
     mock_network_portal_detector_ = new MockNetworkPortalDetector();
     network_portal_detector::SetNetworkPortalDetector(
         mock_network_portal_detector_);
-    mock_error_screen_ = std::make_unique<MockErrorScreen>(&mock_error_view_);
+    mock_error_screen_ =
+        std::make_unique<MockErrorScreen>(mock_error_view_.AsWeakPtr());
 
     // Ensure proper behavior of UpdateScreen's supporting objects.
     EXPECT_CALL(*mock_network_portal_detector_, IsEnabled())
diff --git a/chrome/browser/ash/login/screens/user_selection_screen.cc b/chrome/browser/ash/login/screens/user_selection_screen.cc
index da5632b..ad3ff7d 100644
--- a/chrome/browser/ash/login/screens/user_selection_screen.cc
+++ b/chrome/browser/ash/login/screens/user_selection_screen.cc
@@ -50,10 +50,10 @@
 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/known_user.h"
diff --git a/chrome/browser/ash/login/screens/user_selection_screen_browsertest.cc b/chrome/browser/ash/login/screens/user_selection_screen_browsertest.cc
index de24738..40cab87b 100644
--- a/chrome/browser/ash/login/screens/user_selection_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/user_selection_screen_browsertest.cc
@@ -10,6 +10,7 @@
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/login_accelerators.h"
 #include "ash/public/cpp/login_screen_test_api.h"
+#include "ash/public/cpp/style/color_mode_observer.h"
 #include "ash/public/cpp/style/color_provider.h"
 #include "base/command_line.h"
 #include "base/run_loop.h"
@@ -30,8 +31,8 @@
 #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/user_creation_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/constants/chromeos_features.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/known_user.h"
 #include "content/public/test/browser_test.h"
@@ -265,7 +266,8 @@
   test::OobeJS().ExpectVisiblePath(kErrorMessageOfflineSigninLink);
 }
 
-class DarkLightEnabledTest : public LoginManagerTest {
+class DarkLightEnabledTest : public LoginManagerTest,
+                             public ash::ColorModeObserver {
  public:
   DarkLightEnabledTest() {
     feature_list_.InitAndEnableFeature(chromeos::features::kDarkLightMode);
@@ -273,11 +275,15 @@
 
  protected:
   void StartLogin(const AccountId& account_id) {
+    ash::ColorProvider::Get()->AddObserver(this);
+    wait_for_color_mode_change_ = true;
     LoginDisplayHost::default_host()
         ->GetWizardContext()
         ->defer_oobe_flow_finished_for_tests = true;
     login_manager_mixin_.LoginWithDefaultContext(
         LoginManagerMixin::TestUserInfo(account_id));
+    WaitForColorModeChange();
+    ash::ColorProvider::Get()->RemoveObserver(this);
   }
   void FinishLogin() {
     LoginDisplayHost::default_host()
@@ -286,9 +292,28 @@
     login_manager_mixin_.SkipPostLoginScreens();
     login_manager_mixin_.WaitForActiveSession();
   }
+
+  void OnColorModeChanged(bool dark_mode_enabled) override {
+    wait_for_color_mode_change_ = false;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+
+  void OnColorModeThemed(bool is_themed) override {}
+
+  void WaitForColorModeChange() {
+    if (!wait_for_color_mode_change_)
+      return;
+
+    run_loop_ = std::make_unique<base::RunLoop>();
+    run_loop_->Run();
+    run_loop_.reset();
+  }
   LoginManagerMixin login_manager_mixin_{&mixin_host_};
   const AccountId user1{AccountId::FromUserEmailGaiaId(kUser1Email, kGaia1ID)};
   const AccountId user2{AccountId::FromUserEmailGaiaId(kUser2Email, kGaia2ID)};
+  bool wait_for_color_mode_change_ = false;
+  std::unique_ptr<base::RunLoop> run_loop_;
 
  private:
   base::test::ScopedFeatureList feature_list_;
@@ -349,7 +374,7 @@
 }
 
 // Test focusing different pods.
-IN_PROC_BROWSER_TEST_F(DarkLightEnabledTest, DISABLED_OobeLogin) {
+IN_PROC_BROWSER_TEST_F(DarkLightEnabledTest, OobeLogin) {
   ASSERT_EQ(LoginScreenTestApi::GetFocusedUser(), user2);
   EXPECT_FALSE(ash::ColorProvider::Get()->IsDarkModeEnabled());
 
diff --git a/chrome/browser/ash/login/security_token_login_browsertest.cc b/chrome/browser/ash/login/security_token_login_browsertest.cc
index c7bbfbb..ae8bc64f 100644
--- a/chrome/browser/ash/login/security_token_login_browsertest.cc
+++ b/chrome/browser/ash/login/security_token_login_browsertest.cc
@@ -43,10 +43,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
 #include "chromeos/dbus/cryptohome/key.pb.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
diff --git a/chrome/browser/ash/login/session/chrome_session_manager.cc b/chrome/browser/ash/login/session/chrome_session_manager.cc
index 7f2c5b6d..b57fb72 100644
--- a/chrome/browser/ash/login/session/chrome_session_manager.cc
+++ b/chrome/browser/ash/login/session/chrome_session_manager.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "ash/components/account_manager/account_manager_factory.h"
 #include "ash/components/cryptohome/cryptohome_parameters.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
@@ -14,6 +15,7 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "chrome/browser/ash/account_manager/account_manager_util.h"
 #include "chrome/browser/ash/app_mode/app_launch_utils.h"
 #include "chrome/browser/ash/app_mode/kiosk_cryptohome_remover.h"
 #include "chrome/browser/ash/arc/session/arc_service_launcher.h"
@@ -56,6 +58,7 @@
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
 #include "components/account_id/account_id.h"
 #include "components/prefs/pref_service.h"
+#include "components/signin/public/identity_manager/accounts_mutator.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/primary_account_mutator.h"
 #include "components/user_manager/user_manager.h"
@@ -96,6 +99,51 @@
   }
 }
 
+// Seed the stub user account in the same way as it's done in
+// `UserSessionManager::InitProfilePreferences` for regular users.
+void UpsertStubUserToAccountManager(Profile* user_profile,
+                                    const user_manager::User* user) {
+  // 1. Make sure that the account is present in
+  // `account_manager::AccountManager`.
+  account_manager::AccountManager* account_manager =
+      g_browser_process->platform_part()
+          ->GetAccountManagerFactory()
+          ->GetAccountManager(user_profile->GetPath().value());
+
+  DCHECK(account_manager->IsInitialized());
+
+  const ::account_manager::AccountKey account_key{
+      user->GetAccountId().GetGaiaId(), account_manager::AccountType::kGaia};
+
+  account_manager->UpsertAccount(
+      account_key, /*raw_email=*/user->GetDisplayEmail(),
+      account_manager::AccountManager::kInvalidToken);
+
+  DCHECK(account_manager->IsTokenAvailable(account_key));
+
+  // 2. Seed it into `IdentityManager`.
+  signin::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(user_profile);
+  signin::AccountsMutator* accounts_mutator =
+      identity_manager->GetAccountsMutator();
+  CoreAccountId account_id = accounts_mutator->SeedAccountInfo(
+      user->GetAccountId().GetGaiaId(), user->GetDisplayEmail());
+
+  // 3. Set it as the Primary Account.
+  identity_manager->GetPrimaryAccountMutator()->SetPrimaryAccount(
+      account_id, signin::ConsentLevel::kSync);
+
+  CHECK(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
+  CHECK_EQ(
+      identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync).gaia,
+      user->GetAccountId().GetGaiaId());
+
+  DCHECK_EQ(account_id, identity_manager->GetPrimaryAccountId(
+                            signin::ConsentLevel::kSignin));
+  VLOG(1) << "Seed IdentityManager for stub account, "
+          << "success=" << !account_id.empty();
+}
+
 // Starts Chrome with an existing user session. Possible cases:
 // 1. Chrome is restarted after crash.
 // 2. Chrome is restarted for Guest session.
@@ -106,6 +154,9 @@
 void StartUserSession(Profile* user_profile, const std::string& login_user_id) {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
 
+  bool is_running_test = command_line->HasSwitch(::switches::kTestName) ||
+                         command_line->HasSwitch(::switches::kTestType);
+
   if (command_line->HasSwitch(switches::kLoginUser)) {
     // TODO(https://crbug.com/977489): There's a lot of code duplication with
     // UserSessionManager::FinalizePrepareProfile, which is (only!) run for
@@ -136,6 +187,16 @@
 
     SigninProfileHandler::Get()->ProfileStartUp(user_profile);
 
+    if (!is_running_test &&
+        user_manager->IsStubAccountId(user->GetAccountId())) {
+      // Add stub user to Account Manager. (But not when running tests: this
+      // allows tests to setup appropriate environment)
+      ash::InitializeAccountManager(
+          user_profile->GetPath(),
+          /*initialization_callback=*/base::BindOnce(
+              &UpsertStubUserToAccountManager, user_profile, user));
+    }
+
     user_session_mgr->NotifyUserProfileLoaded(user_profile, user);
 
     // This call will set session state to SESSION_STATE_ACTIVE (same one).
@@ -147,8 +208,6 @@
     user_session_mgr->RestoreActiveSessions();
   }
 
-  bool is_running_test = command_line->HasSwitch(::switches::kTestName) ||
-                         command_line->HasSwitch(::switches::kTestType);
   if (!is_running_test) {
     // We did not log in (we crashed or are debugging), so we need to
     // restore Sync.
diff --git a/chrome/browser/ash/login/session/chrome_session_manager_browsertest.cc b/chrome/browser/ash/login/session/chrome_session_manager_browsertest.cc
index 3dfc5f7..61e04d79 100644
--- a/chrome/browser/ash/login/session/chrome_session_manager_browsertest.cc
+++ b/chrome/browser/ash/login/session/chrome_session_manager_browsertest.cc
@@ -141,8 +141,9 @@
   LoginManagerMixin login_manager_{&mixin_host_};
 };
 
+// http://crbug.com/1338401
 IN_PROC_BROWSER_TEST_F(ChromeSessionManagerExistingUsersTest,
-                       LoginExistingUsers) {
+                       DISABLED_LoginExistingUsers) {
   // Verify that session state is LOGIN_PRIMARY with existing user data dir.
   session_manager::SessionManager* manager =
       session_manager::SessionManager::Get();
diff --git a/chrome/browser/ash/login/shill_profile_loading_browsertest.cc b/chrome/browser/ash/login/shill_profile_loading_browsertest.cc
index b77a943..ef2ebb93 100644
--- a/chrome/browser/ash/login/shill_profile_loading_browsertest.cc
+++ b/chrome/browser/ash/login/shill_profile_loading_browsertest.cc
@@ -104,7 +104,7 @@
   void SetUpInProcessBrowserTestFixture() override {
     LoginManagerTest::SetUpInProcessBrowserTestFixture();
 
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    SessionManagerClient::InitializeFakeInMemory();
   }
 
   const LoginManagerMixin::TestUserInfo unmanaged_user_{
diff --git a/chrome/browser/ash/login/signin_partition_manager.cc b/chrome/browser/ash/login/signin_partition_manager.cc
index f155000c..8d885bc8 100644
--- a/chrome/browser/ash/login/signin_partition_manager.cc
+++ b/chrome/browser/ash/login/signin_partition_manager.cc
@@ -17,6 +17,7 @@
 #include "content/public/browser/storage_partition_config.h"
 #include "content/public/browser/web_contents.h"
 #include "services/network/public/mojom/network_context.mojom.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "url/gurl.h"
 
 namespace ash {
@@ -34,8 +35,9 @@
                            base::OnceClosure partition_data_cleared) {
   storage_partition->ClearData(
       content::StoragePartition::REMOVE_DATA_MASK_ALL,
-      content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
-      base::Time(), base::Time::Max(), std::move(partition_data_cleared));
+      content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+      blink::StorageKey(), base::Time(), base::Time::Max(),
+      std::move(partition_data_cleared));
 }
 
 network::mojom::NetworkContext* GetSystemNetworkContext() {
@@ -74,7 +76,7 @@
       get_system_network_context_task_(
           base::BindRepeating(&GetSystemNetworkContext)) {}
 
-SigninPartitionManager::~SigninPartitionManager() {}
+SigninPartitionManager::~SigninPartitionManager() = default;
 
 void SigninPartitionManager::StartSigninSession(
     content::WebContents* embedder_web_contents,
@@ -111,8 +113,11 @@
     std::move(partition_data_cleared).Run();
     return;
   }
-  clear_storage_partition_task_.Run(current_storage_partition_,
-                                    std::move(partition_data_cleared));
+  clear_storage_partition_task_.Run(
+      current_storage_partition_,
+      base::BindOnce(&SigninPartitionManager::OnStoragePartitionCleared,
+                     weak_ptr_factory_.GetWeakPtr(), current_storage_partition_,
+                     std::move(partition_data_cleared)));
   current_storage_partition_ = nullptr;
   current_storage_partition_name_.clear();
 }
@@ -153,12 +158,37 @@
   return IsInSigninSession() && storage_partition == current_storage_partition_;
 }
 
+void SigninPartitionManager::DisposeOldStoragePartitions() {
+  if (pending_removal_partitions_.empty())
+    return;
+
+  // Disposes all but the last storage partition. The last storage partition
+  // represents the last gaia load and there might still be references to it,
+  // e.g. fast gaia reload in All/SshWarningTest.VisibilityOnEnrollment/0 test.
+
+  content::StoragePartition* last = pending_removal_partitions_.back();
+  pending_removal_partitions_.pop_back();
+
+  for (auto* partition : pending_removal_partitions_)
+    browser_context_->DisposeStoragePartition(partition);
+
+  pending_removal_partitions_.clear();
+  pending_removal_partitions_.push_back(last);
+}
+
+void SigninPartitionManager::OnStoragePartitionCleared(
+    content::StoragePartition* storage_partition,
+    base::OnceClosure partition_data_cleared) {
+  pending_removal_partitions_.push_back(storage_partition);
+  std::move(partition_data_cleared).Run();
+}
+
 SigninPartitionManager::Factory::Factory()
     : BrowserContextKeyedServiceFactory(
           "SigninPartitionManager",
           BrowserContextDependencyManager::GetInstance()) {}
 
-SigninPartitionManager::Factory::~Factory() {}
+SigninPartitionManager::Factory::~Factory() = default;
 
 // static
 SigninPartitionManager* SigninPartitionManager::Factory::GetForBrowserContext(
diff --git a/chrome/browser/ash/login/signin_partition_manager.h b/chrome/browser/ash/login/signin_partition_manager.h
index 8c152b2f..ccea2610 100644
--- a/chrome/browser/ash/login/signin_partition_manager.h
+++ b/chrome/browser/ash/login/signin_partition_manager.h
@@ -6,10 +6,12 @@
 #define CHROME_BROWSER_ASH_LOGIN_SIGNIN_PARTITION_MANAGER_H_
 
 #include <string>
+#include <vector>
 
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
 
@@ -87,6 +89,10 @@
   bool IsCurrentSigninStoragePartition(
       const content::StoragePartition* storage_partition) const;
 
+  // Disposes old storage partitions. Note that callers need to be sure that
+  // old partitions will not be referenced again.
+  void DisposeOldStoragePartitions();
+
   void SetClearStoragePartitionTaskForTesting(
       ClearStoragePartitionTask clear_storage_partition_task);
   void SetGetSystemNetworkContextForTesting(
@@ -118,6 +124,10 @@
   };
 
  private:
+  // Invoked after `storage_partition` is cleared.
+  void OnStoragePartitionCleared(content::StoragePartition* storage_partition,
+                                 base::OnceClosure partition_data_cleared);
+
   content::BrowserContext* const browser_context_;
 
   ClearStoragePartitionTask clear_storage_partition_task_;
@@ -133,6 +143,17 @@
   // The StoragePartition identified by `storage_partition_domain_` and
   // `current_storage_partition_name_`.
   content::StoragePartition* current_storage_partition_ = nullptr;
+
+  // Storage partitions that should be disposed. Storage partitions for previous
+  // gaia loads are added here. It if only safe to remove them when there are no
+  // outstanding references. The current assumption is that all references are
+  // gone after the gaia loading webview is fully navigated away. The vector
+  // here is maintained in the time order of gaia loads and the last element
+  // is used as a barrier to indicate all previous ones could be safely
+  // disposed.
+  std::vector<content::StoragePartition*> pending_removal_partitions_;
+
+  base::WeakPtrFactory<SigninPartitionManager> weak_ptr_factory_{this};
 };
 
 }  // namespace login
diff --git a/chrome/browser/ash/login/test/cryptohome_mixin.cc b/chrome/browser/ash/login/test/cryptohome_mixin.cc
index 92a2b47..278f259b 100644
--- a/chrome/browser/ash/login/test/cryptohome_mixin.cc
+++ b/chrome/browser/ash/login/test/cryptohome_mixin.cc
@@ -7,8 +7,8 @@
 #include "ash/components/cryptohome/cryptohome_parameters.h"
 #include "chrome/browser/ash/login/test/login_manager_mixin.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 
 namespace ash {
diff --git a/chrome/browser/ash/login/test/cryptohome_mixin_unittest.cc b/chrome/browser/ash/login/test/cryptohome_mixin_unittest.cc
index 7758dd5f..47a77165 100644
--- a/chrome/browser/ash/login/test/cryptohome_mixin_unittest.cc
+++ b/chrome/browser/ash/login/test/cryptohome_mixin_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "ash/components/cryptohome/cryptohome_parameters.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/login/test/device_state_mixin.cc b/chrome/browser/ash/login/test/device_state_mixin.cc
index 2ed6329..852b2d5 100644
--- a/chrome/browser/ash/login/test/device_state_mixin.cc
+++ b/chrome/browser/ash/login/test/device_state_mixin.cc
@@ -87,8 +87,8 @@
 void DeviceStateMixin::SetUpInProcessBrowserTestFixture() {
   // Make sure session manager client has been initialized as in-memory. This is
   // requirement for setting policy blobs.
-  if (!chromeos::SessionManagerClient::Get())
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+  if (!SessionManagerClient::Get())
+    SessionManagerClient::InitializeFakeInMemory();
 
   session_manager_initialized_ = true;
 
diff --git a/chrome/browser/ash/login/test/offline_login_test_mixin.cc b/chrome/browser/ash/login/test/offline_login_test_mixin.cc
index 7102d91..5c49601 100644
--- a/chrome/browser/ash/login/test/offline_login_test_mixin.cc
+++ b/chrome/browser/ash/login/test/offline_login_test_mixin.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "chromeos/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "content/public/test/test_utils.h"
 
 namespace ash {
diff --git a/chrome/browser/ash/login/test/offline_login_test_mixin.h b/chrome/browser/ash/login/test/offline_login_test_mixin.h
index 8c71152..d3385654 100644
--- a/chrome/browser/ash/login/test/offline_login_test_mixin.h
+++ b/chrome/browser/ash/login/test/offline_login_test_mixin.h
@@ -10,7 +10,7 @@
 
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
-#include "chromeos/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 
 class AccountId;
 
diff --git a/chrome/browser/ash/login/test/user_policy_mixin.cc b/chrome/browser/ash/login/test/user_policy_mixin.cc
index 7ab097b..878db52 100644
--- a/chrome/browser/ash/login/test/user_policy_mixin.cc
+++ b/chrome/browser/ash/login/test/user_policy_mixin.cc
@@ -17,9 +17,9 @@
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 
 namespace ash {
@@ -42,8 +42,8 @@
 
   // Make sure session manager client has been initialized as in-memory. This is
   // requirement for setting policy blobs.
-  if (!chromeos::SessionManagerClient::Get())
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+  if (!SessionManagerClient::Get())
+    SessionManagerClient::InitializeFakeInMemory();
 
   session_manager_initialized_ = true;
 
diff --git a/chrome/browser/ash/login/ui/login_display_host_webui.cc b/chrome/browser/ash/login/ui/login_display_host_webui.cc
index c185623..a7c9004 100644
--- a/chrome/browser/ash/login/ui/login_display_host_webui.cc
+++ b/chrome/browser/ash/login/ui/login_display_host_webui.cc
@@ -691,7 +691,7 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// LoginDisplayHostWebUI, chromeos::SessionManagerClient::Observer:
+// LoginDisplayHostWebUI, SessionManagerClient::Observer:
 
 void LoginDisplayHostWebUI::EmitLoginPromptVisibleCalled() {
   OnLoginPromptVisible();
diff --git a/chrome/browser/ash/login/ui/login_display_host_webui.h b/chrome/browser/ash/login/ui/login_display_host_webui.h
index dedb25e4..30718e2 100644
--- a/chrome/browser/ash/login/ui/login_display_host_webui.h
+++ b/chrome/browser/ash/login/ui/login_display_host_webui.h
@@ -51,7 +51,7 @@
 class LoginDisplayHostWebUI : public LoginDisplayHostCommon,
                               public session_manager::SessionManagerObserver,
                               public content::WebContentsObserver,
-                              public chromeos::SessionManagerClient::Observer,
+                              public SessionManagerClient::Observer,
                               public CrasAudioHandler::AudioObserver,
                               public chromeos::OobeConfiguration::Observer,
                               public display::DisplayObserver,
@@ -129,7 +129,7 @@
   void PrimaryMainFrameRenderProcessGone(
       base::TerminationStatus status) override;
 
-  // chromeos::SessionManagerClient::Observer:
+  // SessionManagerClient::Observer:
   void EmitLoginPromptVisibleCalled() override;
 
   // chromeos::OobeConfiguration::Observer:
diff --git a/chrome/browser/ash/login/ui/login_web_dialog.h b/chrome/browser/ash/login/ui/login_web_dialog.h
index c1ab8651..c815844f 100644
--- a/chrome/browser/ash/login/ui/login_web_dialog.h
+++ b/chrome/browser/ash/login/ui/login_web_dialog.h
@@ -23,6 +23,7 @@
 class LoginWebDialog : public ui::WebDialogDelegate {
  public:
   // Delegate class to get notifications from the dialog.
+  // TODO(https://crbug.com/1338520): It isn't used anywhere. Remove.
   class Delegate {
    public:
     // Called when dialog has been closed.
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc
index bd2ec37..c378e32b 100644
--- a/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc
+++ b/chrome/browser/ash/login/users/avatar/user_image_manager_browsertest.cc
@@ -49,8 +49,8 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/ownership/mock_owner_key_util.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
@@ -559,7 +559,7 @@
     owner_key_util_->SetPublicKeyFromPrivateKey(
         *device_policy_.GetSigningKey());
     // Override FakeSessionManagerClient. This will be shut down by the browser.
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    SessionManagerClient::InitializeFakeInMemory();
     FakeSessionManagerClient::Get()->set_device_policy(
         device_policy_.GetBlob());
 
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
index 7a265c6..da8564bd 100644
--- a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
+++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
@@ -84,13 +84,13 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/ash/components/dbus/upstart/upstart_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/ash/components/network/proxy/proxy_config_service_impl.h"
 #include "chromeos/components/onc/certificate_scope.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "components/account_id/account_id.h"
 #include "components/crash/core/common/crash_key.h"
diff --git a/chrome/browser/ash/login/users/wallpaper_policy_browsertest.cc b/chrome/browser/ash/login/users/wallpaper_policy_browsertest.cc
index 9c6180a..548bf527 100644
--- a/chrome/browser/ash/login/users/wallpaper_policy_browsertest.cc
+++ b/chrome/browser/ash/login/users/wallpaper_policy_browsertest.cc
@@ -41,9 +41,9 @@
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/ownership/mock_owner_key_util.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
@@ -168,7 +168,7 @@
         owner_key_util_);
     owner_key_util_->SetPublicKeyFromPrivateKey(
         *device_policy_.GetSigningKey());
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    SessionManagerClient::InitializeFakeInMemory();
     FakeSessionManagerClient::Get()->set_device_policy(
         device_policy_.GetBlob());
 
diff --git a/chrome/browser/ash/login/version_info_updater.cc b/chrome/browser/ash/login/version_info_updater.cc
index e1177451..1bd6cde9 100644
--- a/chrome/browser/ash/login/version_info_updater.cc
+++ b/chrome/browser/ash/login/version_info_updater.cc
@@ -106,8 +106,7 @@
   // Get ADB sideloading status if supported on device. Otherwise, default is to
   // not show.
   if (base::FeatureList::IsEnabled(features::kArcAdbSideloadingFeature)) {
-    chromeos::SessionManagerClient* client =
-        chromeos::SessionManagerClient::Get();
+    SessionManagerClient* client = SessionManagerClient::Get();
     client->QueryAdbSideload(
         base::BindOnce(&VersionInfoUpdater::OnQueryAdbSideload,
                        weak_pointer_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ash/login/version_updater/version_updater_unittest.cc b/chrome/browser/ash/login/version_updater/version_updater_unittest.cc
index bbdb81e..eff4493 100644
--- a/chrome/browser/ash/login/version_updater/version_updater_unittest.cc
+++ b/chrome/browser/ash/login/version_updater/version_updater_unittest.cc
@@ -16,12 +16,12 @@
 #include "chrome/browser/ash/net/network_portal_detector_test_impl.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/portal_detector/mock_network_portal_detector.h"
 #include "chromeos/ash/components/network/portal_detector/network_portal_detector.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
 #include "chromeos/dbus/update_engine/update_engine_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/ash/login/webview_login_browsertest.cc b/chrome/browser/ash/login/webview_login_browsertest.cc
index da0b28f..666f0f90 100644
--- a/chrome/browser/ash/login/webview_login_browsertest.cc
+++ b/chrome/browser/ash/login/webview_login_browsertest.cc
@@ -939,6 +939,20 @@
   // The StoragePartition which is not in use is supposed to have been cleared.
   EXPECT_EQ("", GetAllCookies(signin_frame_partition_1));
   EXPECT_NE("", GetAllCookies(signin_frame_partition_2));
+
+  // Trigger another gaia load.
+  test::OobeJS().ClickOnPath(kBackButton);
+  WaitForGaiaPageBackButtonUpdate();
+  ExpectIdentifierPage();
+
+  // `signin_frame_partition_1` is disposed and no longer accessible.
+  bool found_signin_frame_partition_1 = false;
+  browser_context->ForEachStoragePartition(
+      base::BindLambdaForTesting([&](content::StoragePartition* partition) {
+        if (partition == signin_frame_partition_1)
+          found_signin_frame_partition_1 = true;
+      }));
+  EXPECT_FALSE(found_signin_frame_partition_1);
 }
 
 // Tests that requesting webcam access from the login screen works correctly.
@@ -1208,7 +1222,7 @@
  protected:
   void SetUpInProcessBrowserTestFixture() override {
     // Override FakeSessionManagerClient. This will be shut down by the browser.
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    SessionManagerClient::InitializeFakeInMemory();
     device_policy_builder_.Build();
     FakeSessionManagerClient::Get()->set_device_policy(
         device_policy_builder_.GetBlob());
diff --git a/chrome/browser/ash/login/wizard_controller_browsertest.cc b/chrome/browser/ash/login/wizard_controller_browsertest.cc
index 68af468..b49f588 100644
--- a/chrome/browser/ash/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/ash/login/wizard_controller_browsertest.cc
@@ -90,10 +90,10 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/dbus/system_clock/system_clock_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/dbus/constants/dbus_switches.h"
 #include "chromeos/dbus/shill/fake_shill_manager_client.h"
-#include "chromeos/dbus/userdataauth/fake_install_attributes_client.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/system/fake_statistics_provider.h"
diff --git a/chrome/browser/ash/mobile/mobile_activator_unittest.cc b/chrome/browser/ash/mobile/mobile_activator_unittest.cc
index 5665871e..d7808a3 100644
--- a/chrome/browser/ash/mobile/mobile_activator_unittest.cc
+++ b/chrome/browser/ash/mobile/mobile_activator_unittest.cc
@@ -9,8 +9,8 @@
 
 #include "base/test/task_environment.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/network/network_connection_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ash/net/network_diagnostics/network_diagnostics_test_helper.h b/chrome/browser/ash/net/network_diagnostics/network_diagnostics_test_helper.h
index d68e29c..c9673f76 100644
--- a/chrome/browser/ash/net/network_diagnostics/network_diagnostics_test_helper.h
+++ b/chrome/browser/ash/net/network_diagnostics/network_diagnostics_test_helper.h
@@ -7,10 +7,10 @@
 
 #include <memory>
 
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/services/network_config/cros_network_config.h"
 #include "chromeos/services/network_config/in_process_instance.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chrome/browser/ash/net/network_health/network_health.h b/chrome/browser/ash/net/network_health/network_health.h
index 54ed1d99..6e29f48d 100644
--- a/chrome/browser/ash/net/network_health/network_health.h
+++ b/chrome/browser/ash/net/network_health/network_health.h
@@ -11,7 +11,7 @@
 
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/net/network_health/signal_strength_tracker.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "chromeos/services/network_health/public/mojom/network_health.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -24,7 +24,7 @@
 
 class NetworkHealth
     : public chromeos::network_health::mojom::NetworkHealthService,
-      public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+      public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   NetworkHealth();
 
@@ -59,9 +59,6 @@
   void OnNetworkStateChanged(
       chromeos::network_config::mojom::NetworkStatePropertiesPtr network_state)
       override;
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
   // Signal strength changes larger than
   // |kMaxSignalStrengthFluctuationTolerance| trigger a signal strength change
diff --git a/chrome/browser/ash/net/network_portal_detector_impl_unittest.cc b/chrome/browser/ash/net/network_portal_detector_impl_unittest.cc
index 71172200..2c92a9e 100644
--- a/chrome/browser/ash/net/network_portal_detector_impl_unittest.cc
+++ b/chrome/browser/ash/net/network_portal_detector_impl_unittest.cc
@@ -25,12 +25,12 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/portal_detector/network_portal_detector_strategy.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/captive_portal/core/captive_portal_detector.h"
diff --git a/chrome/browser/ash/net/network_pref_state_observer_unittest.cc b/chrome/browser/ash/net/network_pref_state_observer_unittest.cc
index 3a9ce3b3..f79c87b 100644
--- a/chrome/browser/ash/net/network_pref_state_observer_unittest.cc
+++ b/chrome/browser/ash/net/network_pref_state_observer_unittest.cc
@@ -12,9 +12,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/proxy/ui_proxy_config_service.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/onc/onc_constants.h"
 #include "components/prefs/pref_service.h"
 #include "components/proxy_config/proxy_config_pref_names.h"
diff --git a/chrome/browser/ash/net/network_throttling_observer_unittest.cc b/chrome/browser/ash/net/network_throttling_observer_unittest.cc
index 74f63a3..2c5da0c 100644
--- a/chrome/browser/ash/net/network_throttling_observer_unittest.cc
+++ b/chrome/browser/ash/net/network_throttling_observer_unittest.cc
@@ -8,8 +8,8 @@
 
 #include "base/test/task_environment.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/net/rollback_network_config/rollback_network_config_unittest.cc b/chrome/browser/ash/net/rollback_network_config/rollback_network_config_unittest.cc
index 0482a86..60fb540 100644
--- a/chrome/browser/ash/net/rollback_network_config/rollback_network_config_unittest.cc
+++ b/chrome/browser/ash/net/rollback_network_config/rollback_network_config_unittest.cc
@@ -21,9 +21,9 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/onc/onc_constants.h"
diff --git a/chrome/browser/ash/net/secure_dns_manager_unittest.cc b/chrome/browser/ash/net/secure_dns_manager_unittest.cc
index 19b6bfb..3abc88f 100644
--- a/chrome/browser/ash/net/secure_dns_manager_unittest.cc
+++ b/chrome/browser/ash/net/secure_dns_manager_unittest.cc
@@ -9,8 +9,8 @@
 #include "base/values.h"
 #include "chrome/browser/net/secure_dns_config.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/net/system_proxy_manager_unittest.cc b/chrome/browser/ash/net/system_proxy_manager_unittest.cc
index 2cc5c3e..69a803a 100644
--- a/chrome/browser/ash/net/system_proxy_manager_unittest.cc
+++ b/chrome/browser/ash/net/system_proxy_manager_unittest.cc
@@ -18,8 +18,8 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/dbus/system_proxy/system_proxy_client.h"
 #include "chromeos/ash/components/dbus/system_proxy/system_proxy_service.pb.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/prefs/pref_service.h"
 #include "components/proxy_config/proxy_config_pref_names.h"
 #include "components/proxy_config/proxy_prefs.h"
diff --git a/chrome/browser/ash/net/traffic_counters_handler.h b/chrome/browser/ash/net/traffic_counters_handler.h
index a1525666a..705d6a1b 100644
--- a/chrome/browser/ash/net/traffic_counters_handler.h
+++ b/chrome/browser/ash/net/traffic_counters_handler.h
@@ -10,7 +10,7 @@
 
 #include "base/component_export.h"
 #include "base/memory/weak_ptr.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
@@ -27,7 +27,7 @@
 // years. Similarly, if the user specified day was 31, the actual day of reset
 // for April would be April 30th.
 class COMPONENT_EXPORT(CHROMEOS_NETWORK) TrafficCountersHandler
-    : public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+    : public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   using TimeGetter = base::RepeatingCallback<base::Time()>;
 
@@ -41,17 +41,9 @@
   void Start();
 
   // CrosNetworkConfigObserver
-  void OnNetworkStateListChanged() override {}
-  void OnDeviceStateListChanged() override {}
   void OnActiveNetworksChanged(
       std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
           active_networks) override;
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr network_state)
-      override {}
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
   void SetTimeGetterForTest(TimeGetter time_getter);
   void RunForTesting();
diff --git a/chrome/browser/ash/net/traffic_counters_handler_unittest.cc b/chrome/browser/ash/net/traffic_counters_handler_unittest.cc
index 30fca03..6c64549 100644
--- a/chrome/browser/ash/net/traffic_counters_handler_unittest.cc
+++ b/chrome/browser/ash/net/traffic_counters_handler_unittest.cc
@@ -9,10 +9,10 @@
 #include "base/time/clock.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/net/traffic_counters_handler.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_metadata_store.h"
 #include "chromeos/services/network_config/cros_network_config.h"
 #include "chromeos/services/network_config/in_process_instance.h"
diff --git a/chrome/browser/ash/network_change_manager_client_browsertest.cc b/chrome/browser/ash/network_change_manager_client_browsertest.cc
index 842b8cc..691d0f6 100644
--- a/chrome/browser/ash/network_change_manager_client_browsertest.cc
+++ b/chrome/browser/ash/network_change_manager_client_browsertest.cc
@@ -64,6 +64,8 @@
  public:
   NetworkServiceObserver() {
     content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this);
+    // TODO(b/229673213): Remove log once flakiness is fixed.
+    LOG(INFO) << "NetworkServiceObserver get connection type";
     content::GetNetworkConnectionTracker()->GetConnectionType(
         &last_connection_type_,
         base::BindOnce(&NetworkServiceObserver::OnConnectionChanged,
@@ -87,6 +89,11 @@
   void OnConnectionChanged(network::mojom::ConnectionType type) override {
     change_count_++;
     last_connection_type_ = type;
+
+    // TODO(b/229673213): Remove log once flakiness is fixed.
+    LOG(INFO) << "NetworkServiceObserver was called, change count increased to "
+              << change_count_
+              << " Last connection type is now: " << last_connection_type_;
     if (run_loop_)
       run_loop_->Quit();
   }
@@ -108,6 +115,12 @@
     service_client_ = ShillServiceClient::Get()->GetTestInterface();
     service_client_->ClearServices();
 
+    // Make sure everyone thinks we have an ethernet connection.
+    NetObserver().WaitForConnectionType(
+        net::NetworkChangeNotifier::CONNECTION_ETHERNET);
+    NetworkServiceObserver().WaitForConnectionType(
+        network::mojom::ConnectionType::CONNECTION_ETHERNET);
+
     // Wait for all services to be removed.
     base::RunLoop().RunUntilIdle();
     // TODO(b/229673213): Remove log once flakiness is fixed.
@@ -131,6 +144,8 @@
   NetObserver net_observer;
   NetworkServiceObserver network_service_observer;
 
+  // TODO(b/229673213): Remove log once flakiness is fixed.
+  LOG(INFO) << "ReceiveNotificationsTEST: Add service test start";
   service_client()->AddService("wifi", "wifi", "wifi", shill::kTypeWifi,
                                shill::kStateOnline, true);
 
diff --git a/chrome/browser/ash/network_change_manager_client_unittest.cc b/chrome/browser/ash/network_change_manager_client_unittest.cc
index b47d667..4963ae7 100644
--- a/chrome/browser/ash/network_change_manager_client_unittest.cc
+++ b/chrome/browser/ash/network_change_manager_client_unittest.cc
@@ -9,8 +9,8 @@
 #include <string>
 
 #include "base/strings/string_split.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "content/public/test/browser_task_environment.h"
 #include "net/base/network_change_notifier.h"
diff --git a/chrome/browser/ash/note_taking_helper_unittest.cc b/chrome/browser/ash/note_taking_helper_unittest.cc
index e280453..426fa253 100644
--- a/chrome/browser/ash/note_taking_helper_unittest.cc
+++ b/chrome/browser/ash/note_taking_helper_unittest.cc
@@ -171,8 +171,8 @@
   ~NoteTakingHelperTest() override = default;
 
   void SetUp() override {
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
-    chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
+    SessionManagerClient::InitializeFakeInMemory();
+    FakeSessionManagerClient::Get()->set_arc_available(true);
 
     BrowserWithTestWindowTest::SetUp();
     InitExtensionService(profile());
@@ -196,7 +196,7 @@
     }
     extensions::ExtensionSystem::Get(profile())->Shutdown();
     BrowserWithTestWindowTest::TearDown();
-    chromeos::SessionManagerClient::Shutdown();
+    SessionManagerClient::Shutdown();
   }
 
  protected:
diff --git a/chrome/browser/ash/notifications/low_disk_notification.h b/chrome/browser/ash/notifications/low_disk_notification.h
index ea6115dc..c7cf6400 100644
--- a/chrome/browser/ash/notifications/low_disk_notification.h
+++ b/chrome/browser/ash/notifications/low_disk_notification.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 
 namespace message_center {
 class Notification;
diff --git a/chrome/browser/ash/notifications/low_disk_notification_unittest.cc b/chrome/browser/ash/notifications/low_disk_notification_unittest.cc
index bef2b5f..ce7f3ca7 100644
--- a/chrome/browser/ash/notifications/low_disk_notification_unittest.cc
+++ b/chrome/browser/ash/notifications/low_disk_notification_unittest.cc
@@ -18,8 +18,8 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/user_manager/fake_user_manager.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ash/notifications/update_required_notification_unittest.cc b/chrome/browser/ash/notifications/update_required_notification_unittest.cc
index 6c6863d..60ca00a3 100644
--- a/chrome/browser/ash/notifications/update_required_notification_unittest.cc
+++ b/chrome/browser/ash/notifications/update_required_notification_unittest.cc
@@ -23,10 +23,10 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ash/ownership/owner_settings_service_ash.cc b/chrome/browser/ash/ownership/owner_settings_service_ash.cc
index 1b2082c..fd2e49d 100644
--- a/chrome/browser/ash/ownership/owner_settings_service_ash.cc
+++ b/chrome/browser/ash/ownership/owner_settings_service_ash.cc
@@ -202,8 +202,8 @@
     : ownership::OwnerSettingsService(owner_key_util),
       device_settings_service_(device_settings_service),
       profile_(profile) {
-  if (chromeos::SessionManagerClient::Get())
-    chromeos::SessionManagerClient::Get()->AddObserver(this);
+  if (SessionManagerClient::Get())
+    SessionManagerClient::Get()->AddObserver(this);
 
   if (device_settings_service_)
     device_settings_service_->AddObserver(this);
@@ -242,8 +242,8 @@
   if (device_settings_service_)
     device_settings_service_->RemoveObserver(this);
 
-  if (chromeos::SessionManagerClient::Get())
-    chromeos::SessionManagerClient::Get()->RemoveObserver(this);
+  if (SessionManagerClient::Get())
+    SessionManagerClient::Get()->RemoveObserver(this);
 }
 
 OwnerSettingsServiceAsh* OwnerSettingsServiceAsh::FromWebUI(
diff --git a/chrome/browser/ash/ownership/owner_settings_service_ash.h b/chrome/browser/ash/ownership/owner_settings_service_ash.h
index ef002bdd..98001a0 100644
--- a/chrome/browser/ash/ownership/owner_settings_service_ash.h
+++ b/chrome/browser/ash/ownership/owner_settings_service_ash.h
@@ -48,7 +48,7 @@
 // (crbug.com/230018).
 class OwnerSettingsServiceAsh : public ownership::OwnerSettingsService,
                                 public ProfileManagerObserver,
-                                public chromeos::SessionManagerClient::Observer,
+                                public SessionManagerClient::Observer,
                                 public DeviceSettingsService::Observer {
  public:
   struct ManagementSettings {
diff --git a/chrome/browser/ash/policy/active_directory/active_directory_migration_manager.cc b/chrome/browser/ash/policy/active_directory/active_directory_migration_manager.cc
index 8e8844d4..ecc247d 100644
--- a/chrome/browser/ash/policy/active_directory/active_directory_migration_manager.cc
+++ b/chrome/browser/ash/policy/active_directory/active_directory_migration_manager.cc
@@ -186,8 +186,7 @@
                         base::Time::Now());
 
   // Unsigned remote powerwash requests are allowed in AD mode.
-  chromeos::SessionManagerClient::Get()->StartRemoteDeviceWipe(
-      em::SignedData());
+  ash::SessionManagerClient::Get()->StartRemoteDeviceWipe(em::SignedData());
 }
 
 void ActiveDirectoryMigrationManager::MaybeRunStatusCallback(bool started,
diff --git a/chrome/browser/ash/policy/active_directory/active_directory_migration_manager_unittest.cc b/chrome/browser/ash/policy/active_directory/active_directory_migration_manager_unittest.cc
index d341c23..c7f4257 100644
--- a/chrome/browser/ash/policy/active_directory/active_directory_migration_manager_unittest.cc
+++ b/chrome/browser/ash/policy/active_directory/active_directory_migration_manager_unittest.cc
@@ -33,8 +33,8 @@
   ActiveDirectoryMigrationManagerTest()
       : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
         local_state_(TestingBrowserProcess::GetGlobal()) {
-    chromeos::SessionManagerClient::InitializeFake();
-    session_manager_client_ = chromeos::FakeSessionManagerClient::Get();
+    ash::SessionManagerClient::InitializeFake();
+    session_manager_client_ = ash::FakeSessionManagerClient::Get();
 
     SetEnrollmentIdUploadedPref(/*value=*/false);
     SetChromadMigrationEnabledPref(/*value=*/false);
@@ -44,7 +44,7 @@
   ~ActiveDirectoryMigrationManagerTest() override {
     migration_manager_->Shutdown();
     migration_manager_.reset();
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
   }
 
  protected:
@@ -90,7 +90,7 @@
   }
 
   session_manager::SessionManager session_manager_;
-  raw_ptr<chromeos::FakeSessionManagerClient> session_manager_client_;
+  raw_ptr<ash::FakeSessionManagerClient> session_manager_client_;
   content::BrowserTaskEnvironment task_environment_;
   base::RunLoop run_loop_first_;
   base::RunLoop run_loop_following_;
diff --git a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_browsertest.cc b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_browsertest.cc
index a8c8255..e6845b5 100644
--- a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_browsertest.cc
+++ b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_browsertest.cc
@@ -143,7 +143,7 @@
     builder_.set_payload(policy);
     builder_.Build();
     base::RunLoop run_loop;
-    chromeos::FakeSessionManagerClient::Get()->StorePolicy(
+    ash::FakeSessionManagerClient::Get()->StorePolicy(
         descriptor, builder_.GetBlob(),
         base::BindOnce(&ExpectSuccess, run_loop.QuitClosure()));
     run_loop.Run();
diff --git a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever.cc b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever.cc
index d065172..f585b531 100644
--- a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever.cc
+++ b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever.cc
@@ -77,7 +77,7 @@
   descriptor.set_domain(MapPolicyDomain(ns.domain));
   descriptor.set_component_id(ns.component_id);
 
-  chromeos::SessionManagerClient::Get()->RetrievePolicy(
+  ash::SessionManagerClient::Get()->RetrievePolicy(
       descriptor,
       base::BindOnce(
           &ComponentActiveDirectoryPolicyRetriever::OnPolicyRetrieved,
diff --git a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever.h b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever.h
index 592d201..47616fa 100644
--- a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever.h
+++ b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever.h
@@ -22,8 +22,7 @@
 class ComponentActiveDirectoryPolicyRetriever {
  public:
   // Response type from a policy retrieval request for a single namespace.
-  using ResponseType =
-      chromeos::SessionManagerClient::RetrievePolicyResponseType;
+  using ResponseType = ash::SessionManagerClient::RetrievePolicyResponseType;
 
   // Result from a policy retrieval request for a single policy namespace.
   struct RetrieveResult {
diff --git a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever_unittest.cc b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever_unittest.cc
index b023634..d8a5907 100644
--- a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever_unittest.cc
+++ b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_retriever_unittest.cc
@@ -54,7 +54,7 @@
 
   base::test::TaskEnvironment task_environment_;
   std::vector<RetrieveResult> results_;
-  chromeos::ScopedFakeInMemorySessionManagerClient scoped_session_manager_;
+  ash::ScopedFakeInMemorySessionManagerClient scoped_session_manager_;
   bool policy_stored_ = false;
   bool callback_called_ = false;
 };
@@ -97,8 +97,8 @@
   descriptor.set_account_type(login_manager::ACCOUNT_TYPE_DEVICE);
   descriptor.set_domain(login_manager::POLICY_DOMAIN_EXTENSIONS);
   descriptor.set_component_id(kExtensionId);
-  chromeos::SessionManagerClient::Get()->StorePolicy(descriptor, policy_blob,
-                                                     CreateStoredCallback());
+  ash::SessionManagerClient::Get()->StorePolicy(descriptor, policy_blob,
+                                                CreateStoredCallback());
   task_environment_.RunUntilIdle();
   EXPECT_TRUE(policy_stored_);
 
diff --git a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_service_unittest.cc b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_service_unittest.cc
index 60583299..e1b500cc 100644
--- a/chrome/browser/ash/policy/active_directory/component_active_directory_policy_service_unittest.cc
+++ b/chrome/browser/ash/policy/active_directory/component_active_directory_policy_service_unittest.cc
@@ -162,7 +162,7 @@
     descriptor.set_component_id(component_id);
 
     builder_.Build();
-    chromeos::SessionManagerClient::Get()->StorePolicy(
+    ash::SessionManagerClient::Get()->StorePolicy(
         descriptor, builder_.GetBlob(),
         base::BindOnce(
             &ComponentActiveDirectoryPolicyServiceTest::OnPolicyStored,
@@ -209,8 +209,7 @@
   }
 
   ComponentActiveDirectoryPolicyBuilder builder_;
-  chromeos::ScopedFakeInMemorySessionManagerClient
-      scoped_session_manager_client_;
+  ash::ScopedFakeInMemorySessionManagerClient scoped_session_manager_client_;
   std::string curr_schema_;
   int store_policy_call_count_ = 0;
   int store_policy_succeeded_count_ = 0;
diff --git a/chrome/browser/ash/policy/affiliation/affiliation_mixin.cc b/chrome/browser/ash/policy/affiliation/affiliation_mixin.cc
index 2a7aee3..5c4f884 100644
--- a/chrome/browser/ash/policy/affiliation/affiliation_mixin.cc
+++ b/chrome/browser/ash/policy/affiliation/affiliation_mixin.cc
@@ -82,7 +82,7 @@
 }
 
 AffiliationTestHelper AffiliationMixin::GetAffiliationTestHelper() const {
-  auto* session_manager_client = chromeos::FakeSessionManagerClient::Get();
+  auto* session_manager_client = ash::FakeSessionManagerClient::Get();
   CHECK(session_manager_client);
   if (is_for_active_directory_) {
     auto* fake_auth_policy_client = ash::FakeAuthPolicyClient::Get();
diff --git a/chrome/browser/ash/policy/affiliation/affiliation_mixin.h b/chrome/browser/ash/policy/affiliation/affiliation_mixin.h
index bf16940..1d319a2 100644
--- a/chrome/browser/ash/policy/affiliation/affiliation_mixin.h
+++ b/chrome/browser/ash/policy/affiliation/affiliation_mixin.h
@@ -19,9 +19,9 @@
 // Mixin to set up device and user affiliation ids. By default, device and user
 // affiliation ids will be identical, and the user will be affiliated.
 // `set_affiliated(false)` can be used to change this behavior.
-// This mixin relies on an available `chromeos::FakeSessionManagerClient` during
+// This mixin relies on an available `ash::FakeSessionManagerClient` during
 // `SetUpInProcessBrowserTestFixture()`. Users of this mixin can run
-// `chromeos::SessionManagerClient::InitializeFakeInMemory();` to ensure this is
+// `ash::SessionManagerClient::InitializeFakeInMemory();` to ensure this is
 // the case.
 class AffiliationMixin final : public InProcessBrowserTestMixin {
  public:
diff --git a/chrome/browser/ash/policy/affiliation/affiliation_test_helper.cc b/chrome/browser/ash/policy/affiliation/affiliation_test_helper.cc
index aeb4521ec..b2c6867 100644
--- a/chrome/browser/ash/policy/affiliation/affiliation_test_helper.cc
+++ b/chrome/browser/ash/policy/affiliation/affiliation_test_helper.cc
@@ -30,8 +30,8 @@
 #include "chromeos/ash/components/dbus/authpolicy/fake_authpolicy_client.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
@@ -81,7 +81,7 @@
 
 // static
 AffiliationTestHelper AffiliationTestHelper::CreateForCloud(
-    chromeos::FakeSessionManagerClient* fake_session_manager_client) {
+    ash::FakeSessionManagerClient* fake_session_manager_client) {
   return AffiliationTestHelper(ManagementType::kCloud,
                                fake_session_manager_client,
                                nullptr /* fake_authpolicy_client */);
@@ -89,7 +89,7 @@
 
 // static
 AffiliationTestHelper AffiliationTestHelper::CreateForActiveDirectory(
-    chromeos::FakeSessionManagerClient* fake_session_manager_client,
+    ash::FakeSessionManagerClient* fake_session_manager_client,
     ash::FakeAuthPolicyClient* fake_authpolicy_client) {
   return AffiliationTestHelper(ManagementType::kActiveDirectory,
                                fake_session_manager_client,
@@ -101,7 +101,7 @@
 
 AffiliationTestHelper::AffiliationTestHelper(
     ManagementType management_type,
-    chromeos::FakeSessionManagerClient* fake_session_manager_client,
+    ash::FakeSessionManagerClient* fake_session_manager_client,
     ash::FakeAuthPolicyClient* fake_authpolicy_client)
     : management_type_(management_type),
       fake_session_manager_client_(fake_session_manager_client),
diff --git a/chrome/browser/ash/policy/affiliation/affiliation_test_helper.h b/chrome/browser/ash/policy/affiliation/affiliation_test_helper.h
index 853b61e5..ae201b6 100644
--- a/chrome/browser/ash/policy/affiliation/affiliation_test_helper.h
+++ b/chrome/browser/ash/policy/affiliation/affiliation_test_helper.h
@@ -14,16 +14,13 @@
 
 namespace ash {
 class FakeAuthPolicyClient;
-}
+class FakeSessionManagerClient;
+}  // namespace ash
 
 namespace base {
 class CommandLine;
 }  // namespace base
 
-namespace chromeos {
-class FakeSessionManagerClient;
-}  // namespace chromeos
-
 namespace policy {
 
 class DevicePolicyCrosTestHelper;
@@ -34,12 +31,12 @@
   // accounts). The |fake_session_manager_client| pointer must outlive this
   // object.
   static AffiliationTestHelper CreateForCloud(
-      chromeos::FakeSessionManagerClient* fake_session_manager_client);
+      ash::FakeSessionManagerClient* fake_session_manager_client);
 
   // Creates an |AffiliationTestHelper| for Active Directory management (Active
   // Directory accounts). The pointers must outlive this object.
   static AffiliationTestHelper CreateForActiveDirectory(
-      chromeos::FakeSessionManagerClient* fake_session_manager_client,
+      ash::FakeSessionManagerClient* fake_session_manager_client,
       ash::FakeAuthPolicyClient* fake_authpolicy_client);
 
   // Allow move construction, so the static constructors can be used despite
@@ -89,15 +86,14 @@
 
   AffiliationTestHelper(
       ManagementType management_type,
-      chromeos::FakeSessionManagerClient* fake_session_manager_client,
+      ash::FakeSessionManagerClient* fake_session_manager_client,
       ash::FakeAuthPolicyClient* fake_authpolicy_client);
 
   // ASSERTs on pointer validity.
   void CheckPreconditions();
 
   ManagementType management_type_;
-  chromeos::FakeSessionManagerClient*
-      fake_session_manager_client_;                         // Not owned.
+  ash::FakeSessionManagerClient* fake_session_manager_client_;  // Not owned.
   ash::FakeAuthPolicyClient* fake_authpolicy_client_;       // Not owned.
 };
 
diff --git a/chrome/browser/ash/policy/affiliation/user_affiliation_browsertest.cc b/chrome/browser/ash/policy/affiliation/user_affiliation_browsertest.cc
index c9792ae..5296786 100644
--- a/chrome/browser/ash/policy/affiliation/user_affiliation_browsertest.cc
+++ b/chrome/browser/ash/policy/affiliation/user_affiliation_browsertest.cc
@@ -23,8 +23,8 @@
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chromeos/ash/components/dbus/authpolicy/fake_authpolicy_client.h"
 #include "chromeos/ash/components/dbus/upstart/upstart_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
 #include "components/user_manager/user.h"
@@ -149,7 +149,7 @@
 
     // Initialize clients here so they are available during setup. They will be
     // shutdown in ChromeBrowserMain.
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
     ash::UpstartClient::InitializeFake();
     if (GetParam().active_directory) {
       ash::AuthPolicyClient::InitializeFake();
diff --git a/chrome/browser/ash/policy/core/browser_policy_connector_ash.cc b/chrome/browser/ash/policy/core/browser_policy_connector_ash.cc
index 8b51dfe..ea16ab4 100644
--- a/chrome/browser/ash/policy/core/browser_policy_connector_ash.cc
+++ b/chrome/browser/ash/policy/core/browser_policy_connector_ash.cc
@@ -159,7 +159,7 @@
               device_active_directory_policy_manager_));
     } else {
       state_keys_broker_ = std::make_unique<ServerBackedStateKeysBroker>(
-          chromeos::SessionManagerClient::Get());
+          ash::SessionManagerClient::Get());
 
       const base::FilePath device_policy_external_data_path =
           base::PathService::CheckedGet(ash::DIR_DEVICE_POLICY_EXTERNAL_DATA);
@@ -211,8 +211,8 @@
   if (!ash::InstallAttributes::Get()->IsActiveDirectoryManaged()) {
     device_local_account_policy_service_ =
         std::make_unique<DeviceLocalAccountPolicyService>(
-            chromeos::SessionManagerClient::Get(),
-            ash::DeviceSettingsService::Get(), ash::CrosSettings::Get(),
+            ash::SessionManagerClient::Get(), ash::DeviceSettingsService::Get(),
+            ash::CrosSettings::Get(),
             affiliated_invalidation_service_provider_.get(),
             CreateBackgroundTaskRunner(), CreateBackgroundTaskRunner(),
             CreateBackgroundTaskRunner(), url_loader_factory);
@@ -221,7 +221,7 @@
     // Initialize state keys and enrollment ID upload mechanisms to DM Server in
     // Active Directory mode.
     state_keys_broker_ = std::make_unique<ServerBackedStateKeysBroker>(
-        chromeos::SessionManagerClient::Get());
+        ash::SessionManagerClient::Get());
     active_directory_device_state_uploader_ =
         std::make_unique<ActiveDirectoryDeviceStateUploader>(
             /*client_id=*/GetInstallAttributes()->GetDeviceId(),
diff --git a/chrome/browser/ash/policy/core/cached_policy_key_loader.cc b/chrome/browser/ash/policy/core/cached_policy_key_loader.cc
index 17cf177..4192ae0 100644
--- a/chrome/browser/ash/policy/core/cached_policy_key_loader.cc
+++ b/chrome/browser/ash/policy/core/cached_policy_key_loader.cc
@@ -17,7 +17,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/task_runner_util.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 
 namespace policy {
 
diff --git a/chrome/browser/ash/policy/core/cached_policy_key_loader_unittest.cc b/chrome/browser/ash/policy/core/cached_policy_key_loader_unittest.cc
index 9f39d61..dd90da3 100644
--- a/chrome/browser/ash/policy/core/cached_policy_key_loader_unittest.cc
+++ b/chrome/browser/ash/policy/core/cached_policy_key_loader_unittest.cc
@@ -15,8 +15,8 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/test/task_environment.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
diff --git a/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash_unittest.cc b/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash_unittest.cc
index ab44fb8..4143be43d 100644
--- a/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash_unittest.cc
+++ b/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash_unittest.cc
@@ -40,9 +40,9 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/fake_install_attributes_client.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
@@ -166,7 +166,7 @@
 
 class DeviceCloudPolicyManagerAshTest
     : public ash::DeviceSettingsTestBase,
-      public chromeos::SessionManagerClient::Observer {
+      public ash::SessionManagerClient::Observer {
  public:
   DeviceCloudPolicyManagerAshTest(const DeviceCloudPolicyManagerAshTest&) =
       delete;
diff --git a/chrome/browser/ash/policy/core/device_cloud_policy_store_ash_unittest.cc b/chrome/browser/ash/policy/core/device_cloud_policy_store_ash_unittest.cc
index 50932934..d245e7cc 100644
--- a/chrome/browser/ash/policy/core/device_cloud_policy_store_ash_unittest.cc
+++ b/chrome/browser/ash/policy/core/device_cloud_policy_store_ash_unittest.cc
@@ -18,10 +18,10 @@
 #include "chrome/browser/ash/settings/device_settings_test_helper.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_util.h"
 #include "chromeos/components/onc/onc_test_utils.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/fake_install_attributes_client.h"
-#include "chromeos/dbus/userdataauth/install_attributes_util.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
 #include "components/policy/core/common/cloud/test/policy_builder.h"
diff --git a/chrome/browser/ash/policy/core/device_local_account_policy_service.cc b/chrome/browser/ash/policy/core/device_local_account_policy_service.cc
index 25f3d86..df1d8e92 100644
--- a/chrome/browser/ash/policy/core/device_local_account_policy_service.cc
+++ b/chrome/browser/ash/policy/core/device_local_account_policy_service.cc
@@ -82,7 +82,7 @@
 }  // namespace
 
 DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
-    chromeos::SessionManagerClient* session_manager_client,
+    ash::SessionManagerClient* session_manager_client,
     ash::DeviceSettingsService* device_settings_service,
     ash::CrosSettings* cros_settings,
     AffiliatedInvalidationServiceProvider* invalidation_service_provider,
diff --git a/chrome/browser/ash/policy/core/device_local_account_policy_service.h b/chrome/browser/ash/policy/core/device_local_account_policy_service.h
index a404d6a..7983fa07 100644
--- a/chrome/browser/ash/policy/core/device_local_account_policy_service.h
+++ b/chrome/browser/ash/policy/core/device_local_account_policy_service.h
@@ -25,16 +25,13 @@
 
 namespace ash {
 class DeviceSettingsService;
+class SessionManagerClient;
 }  // namespace ash
 
 namespace base {
 class SequencedTaskRunner;
 }  // namespace base
 
-namespace chromeos {
-class SessionManagerClient;
-}  // namespace chromeos
-
 namespace network {
 class SharedURLLoaderFactory;
 }  // namespace network
@@ -64,7 +61,7 @@
   };
 
   DeviceLocalAccountPolicyService(
-      chromeos::SessionManagerClient* session_manager_client,
+      ash::SessionManagerClient* session_manager_client,
       ash::DeviceSettingsService* device_settings_service,
       ash::CrosSettings* cros_settings,
       AffiliatedInvalidationServiceProvider* invalidation_service_provider,
@@ -141,7 +138,7 @@
 
   base::ObserverList<Observer, true>::Unchecked observers_;
 
-  raw_ptr<chromeos::SessionManagerClient> session_manager_client_;
+  raw_ptr<ash::SessionManagerClient> session_manager_client_;
   raw_ptr<ash::DeviceSettingsService> device_settings_service_;
   raw_ptr<ash::CrosSettings> cros_settings_;
   raw_ptr<AffiliatedInvalidationServiceProvider> invalidation_service_provider_;
diff --git a/chrome/browser/ash/policy/core/device_local_account_policy_store.cc b/chrome/browser/ash/policy/core/device_local_account_policy_store.cc
index 3f35d99..d2861633 100644
--- a/chrome/browser/ash/policy/core/device_local_account_policy_store.cc
+++ b/chrome/browser/ash/policy/core/device_local_account_policy_store.cc
@@ -20,7 +20,7 @@
 #include "components/policy/proto/device_management_backend.pb.h"
 
 using RetrievePolicyResponseType =
-    chromeos::SessionManagerClient::RetrievePolicyResponseType;
+    ash::SessionManagerClient::RetrievePolicyResponseType;
 
 namespace em = enterprise_management;
 
@@ -28,7 +28,7 @@
 
 DeviceLocalAccountPolicyStore::DeviceLocalAccountPolicyStore(
     const std::string& account_id,
-    chromeos::SessionManagerClient* session_manager_client,
+    ash::SessionManagerClient* session_manager_client,
     ash::DeviceSettingsService* device_settings_service,
     scoped_refptr<base::SequencedTaskRunner> background_task_runner)
     : UserCloudPolicyStoreBase(background_task_runner,
diff --git a/chrome/browser/ash/policy/core/device_local_account_policy_store.h b/chrome/browser/ash/policy/core/device_local_account_policy_store.h
index 8594b60..88ed59b 100644
--- a/chrome/browser/ash/policy/core/device_local_account_policy_store.h
+++ b/chrome/browser/ash/policy/core/device_local_account_policy_store.h
@@ -32,7 +32,7 @@
  public:
   DeviceLocalAccountPolicyStore(
       const std::string& account_id,
-      chromeos::SessionManagerClient* client,
+      ash::SessionManagerClient* client,
       ash::DeviceSettingsService* device_settings_service,
       scoped_refptr<base::SequencedTaskRunner> background_task_runner);
 
@@ -70,7 +70,7 @@
   // success and triggers policy validation.
   void ValidateLoadedPolicyBlob(
       bool validate_in_background,
-      chromeos::SessionManagerClient::RetrievePolicyResponseType response_type,
+      ash::SessionManagerClient::RetrievePolicyResponseType response_type,
       const std::string& policy_blob);
 
   // Updates state after validation and notifies observers.
@@ -102,7 +102,7 @@
       ash::DeviceSettingsService::OwnershipStatus ownership_status);
 
   const std::string account_id_;
-  chromeos::SessionManagerClient* session_manager_client_;
+  ash::SessionManagerClient* session_manager_client_;
   ash::DeviceSettingsService* device_settings_service_;
 
   base::WeakPtrFactory<DeviceLocalAccountPolicyStore> weak_factory_{this};
diff --git a/chrome/browser/ash/policy/core/device_policy_cros_browser_test.cc b/chrome/browser/ash/policy/core/device_policy_cros_browser_test.cc
index d2c92d4..88402855 100644
--- a/chrome/browser/ash/policy/core/device_policy_cros_browser_test.cc
+++ b/chrome/browser/ash/policy/core/device_policy_cros_browser_test.cc
@@ -177,9 +177,8 @@
 }
 
 void DevicePolicyCrosTestHelper::RefreshDevicePolicy() {
-  chromeos::FakeSessionManagerClient::Get()->set_device_policy(
-      device_policy_blob());
-  chromeos::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
+  ash::FakeSessionManagerClient::Get()->set_device_policy(device_policy_blob());
+  ash::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
 }
 
 void DevicePolicyCrosTestHelper::RefreshPolicyAndWaitUntilDeviceSettingsUpdated(
@@ -227,9 +226,9 @@
 
 DevicePolicyCrosBrowserTest::~DevicePolicyCrosBrowserTest() = default;
 
-chromeos::FakeSessionManagerClient*
+ash::FakeSessionManagerClient*
 DevicePolicyCrosBrowserTest::session_manager_client() {
-  return chromeos::FakeSessionManagerClient::Get();
+  return ash::FakeSessionManagerClient::Get();
 }
 
 }  // namespace policy
diff --git a/chrome/browser/ash/policy/core/device_policy_cros_browser_test.h b/chrome/browser/ash/policy/core/device_policy_cros_browser_test.h
index 6504fa07..da2f83f0 100644
--- a/chrome/browser/ash/policy/core/device_policy_cros_browser_test.h
+++ b/chrome/browser/ash/policy/core/device_policy_cros_browser_test.h
@@ -16,7 +16,7 @@
 #include "components/policy/core/common/cloud/test/policy_builder.h"
 #include "components/prefs/pref_change_registrar.h"
 
-namespace chromeos {
+namespace ash {
 class FakeSessionManagerClient;
 }
 
@@ -124,7 +124,7 @@
     return policy_helper()->device_policy();
   }
 
-  chromeos::FakeSessionManagerClient* session_manager_client();
+  ash::FakeSessionManagerClient* session_manager_client();
 
   ash::DeviceStateMixin device_state_{
       &mixin_host_,
diff --git a/chrome/browser/ash/policy/core/dm_token_storage_unittest.cc b/chrome/browser/ash/policy/core/dm_token_storage_unittest.cc
index d7cff2b..4723778 100644
--- a/chrome/browser/ash/policy/core/dm_token_storage_unittest.cc
+++ b/chrome/browser/ash/policy/core/dm_token_storage_unittest.cc
@@ -12,8 +12,8 @@
 #include "base/run_loop.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/policy/core/user_cloud_policy_store_ash.cc b/chrome/browser/ash/policy/core/user_cloud_policy_store_ash.cc
index f7069b2b..ec7775c 100644
--- a/chrome/browser/ash/policy/core/user_cloud_policy_store_ash.cc
+++ b/chrome/browser/ash/policy/core/user_cloud_policy_store_ash.cc
@@ -21,7 +21,7 @@
 #include "google_apis/gaia/gaia_auth_util.h"
 
 using RetrievePolicyResponseType =
-    chromeos::SessionManagerClient::RetrievePolicyResponseType;
+    ash::SessionManagerClient::RetrievePolicyResponseType;
 
 namespace em = enterprise_management;
 
@@ -38,7 +38,7 @@
 
 UserCloudPolicyStoreAsh::UserCloudPolicyStoreAsh(
     chromeos::CryptohomeMiscClient* cryptohome_misc_client,
-    chromeos::SessionManagerClient* session_manager_client,
+    ash::SessionManagerClient* session_manager_client,
     scoped_refptr<base::SequencedTaskRunner> background_task_runner,
     const AccountId& account_id,
     const base::FilePath& user_policy_key_dir,
diff --git a/chrome/browser/ash/policy/core/user_cloud_policy_store_ash.h b/chrome/browser/ash/policy/core/user_cloud_policy_store_ash.h
index 87a83588..aa1c256 100644
--- a/chrome/browser/ash/policy/core/user_cloud_policy_store_ash.h
+++ b/chrome/browser/ash/policy/core/user_cloud_policy_store_ash.h
@@ -42,7 +42,7 @@
   // is only set when install attributes are locked into Active Directory mode.
   UserCloudPolicyStoreAsh(
       chromeos::CryptohomeMiscClient* cryptohome_misc_client,
-      chromeos::SessionManagerClient* session_manager_client,
+      ash::SessionManagerClient* session_manager_client,
       scoped_refptr<base::SequencedTaskRunner> background_task_runner,
       const AccountId& account_id,
       const base::FilePath& user_policy_key_dir,
@@ -80,7 +80,7 @@
 
   // Called back from SessionManagerClient for policy load operations.
   void OnPolicyRetrieved(
-      chromeos::SessionManagerClient::RetrievePolicyResponseType response,
+      ash::SessionManagerClient::RetrievePolicyResponseType response,
       const std::string& policy_blob);
 
   // Starts validation of the loaded |policy| before installing it.
@@ -94,7 +94,7 @@
   std::unique_ptr<UserCloudPolicyValidator> CreateValidatorForLoad(
       std::unique_ptr<enterprise_management::PolicyFetchResponse> policy);
 
-  chromeos::SessionManagerClient* session_manager_client_;
+  ash::SessionManagerClient* session_manager_client_;
   const AccountId account_id_;
   bool is_active_directory_;
 
diff --git a/chrome/browser/ash/policy/core/user_cloud_policy_store_ash_unittest.cc b/chrome/browser/ash/policy/core/user_cloud_policy_store_ash_unittest.cc
index d623f40..d199d11d 100644
--- a/chrome/browser/ash/policy/core/user_cloud_policy_store_ash_unittest.cc
+++ b/chrome/browser/ash/policy/core/user_cloud_policy_store_ash_unittest.cc
@@ -20,10 +20,10 @@
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/components/onc/onc_test_utils.h"
 #include "chromeos/dbus/cryptohome/account_identifier_operators.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
 #include "components/policy/core/common/cloud/test/policy_builder.h"
@@ -37,7 +37,7 @@
 namespace em = enterprise_management;
 
 using RetrievePolicyResponseType =
-    chromeos::SessionManagerClient::RetrievePolicyResponseType;
+    ash::SessionManagerClient::RetrievePolicyResponseType;
 
 using testing::_;
 using testing::AllOf;
@@ -76,7 +76,7 @@
 
 // For detailed test for UserCloudPolicyStoreAsh, this supports
 // public key file update emulation.
-class FakeSessionManagerClient : public chromeos::FakeSessionManagerClient {
+class FakeSessionManagerClient : public ash::FakeSessionManagerClient {
  public:
   explicit FakeSessionManagerClient(const base::FilePath& user_policy_dir)
       : user_policy_dir_(user_policy_dir) {}
@@ -88,7 +88,7 @@
   void StorePolicyForUser(const cryptohome::AccountIdentifier& cryptohome_id,
                           const std::string& policy_blob,
                           chromeos::VoidDBusMethodCallback callback) override {
-    chromeos::FakeSessionManagerClient::StorePolicyForUser(
+    ash::FakeSessionManagerClient::StorePolicyForUser(
         cryptohome_id, policy_blob,
         base::BindOnce(&FakeSessionManagerClient::OnStorePolicyForUser,
                        weak_ptr_factory_.GetWeakPtr(), cryptohome_id,
diff --git a/chrome/browser/ash/policy/core/user_policy_manager_builder_ash.cc b/chrome/browser/ash/policy/core/user_policy_manager_builder_ash.cc
index b91a4bc3..e4cb91d 100644
--- a/chrome/browser/ash/policy/core/user_policy_manager_builder_ash.cc
+++ b/chrome/browser/ash/policy/core/user_policy_manager_builder_ash.cc
@@ -33,8 +33,8 @@
 #include "chrome/browser/policy/schema_registry_service.h"
 #include "chrome/common/chrome_features.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/cloud/cloud_external_data_manager.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
@@ -250,8 +250,8 @@
   std::unique_ptr<UserCloudPolicyStoreAsh> store =
       std::make_unique<UserCloudPolicyStoreAsh>(
           chromeos::CryptohomeMiscClient::Get(),
-          chromeos::SessionManagerClient::Get(), background_task_runner,
-          account_id, policy_key_dir, is_active_directory);
+          ash::SessionManagerClient::Get(), background_task_runner, account_id,
+          policy_key_dir, is_active_directory);
 
   scoped_refptr<base::SequencedTaskRunner> backend_task_runner =
       base::ThreadPool::CreateSequencedTaskRunner(
diff --git a/chrome/browser/ash/policy/display/device_display_cros_browser_test.cc b/chrome/browser/ash/policy/display/device_display_cros_browser_test.cc
index 652b33ea..b66aad9 100644
--- a/chrome/browser/ash/policy/display/device_display_cros_browser_test.cc
+++ b/chrome/browser/ash/policy/display/device_display_cros_browser_test.cc
@@ -95,7 +95,7 @@
 }
 
 void DeviceDisplayPolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture() {
-  chromeos::SessionManagerClient::InitializeFakeInMemory();
+  ash::SessionManagerClient::InitializeFakeInMemory();
   ash::DisplayConfigurationController::DisableAnimatorForTest();
   DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
 }
diff --git a/chrome/browser/ash/policy/display/display_resolution_handler_browsertest.cc b/chrome/browser/ash/policy/display/display_resolution_handler_browsertest.cc
index 9ed3e0e..691f154 100644
--- a/chrome/browser/ash/policy/display/display_resolution_handler_browsertest.cc
+++ b/chrome/browser/ash/policy/display/display_resolution_handler_browsertest.cc
@@ -322,7 +322,7 @@
 
   void SetUpInProcessBrowserTestFixture() override {
     // Override FakeSessionManagerClient. This will be shut down by the browser.
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
     ash::DisplayConfigurationController::DisableAnimatorForTest();
     MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
   }
@@ -352,9 +352,9 @@
           ash::kDeviceDisplayResolution, run_loop.QuitClosure());
   device_policy->SetDefaultSigningKey();
   device_policy->Build();
-  chromeos::FakeSessionManagerClient::Get()->set_device_policy(
+  ash::FakeSessionManagerClient::Get()->set_device_policy(
       device_policy->GetBlob());
-  chromeos::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
+  ash::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
   run_loop.Run();
   // Allow tasks posted by CrosSettings observers to complete:
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/ash/policy/display/display_rotation_default_handler_browsertest.cc b/chrome/browser/ash/policy/display/display_rotation_default_handler_browsertest.cc
index 2ecd077..9147f4b 100644
--- a/chrome/browser/ash/policy/display/display_rotation_default_handler_browsertest.cc
+++ b/chrome/browser/ash/policy/display/display_rotation_default_handler_browsertest.cc
@@ -190,7 +190,7 @@
   ~DisplayRotationBootTest() override = default;
 
   void SetUpInProcessBrowserTestFixture() override {
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
     ash::DisplayConfigurationController::DisableAnimatorForTest();
     MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
   }
@@ -222,9 +222,9 @@
           ash::kDisplayRotationDefault, run_loop.QuitClosure());
   device_policy->SetDefaultSigningKey();
   device_policy->Build();
-  chromeos::FakeSessionManagerClient::Get()->set_device_policy(
+  ash::FakeSessionManagerClient::Get()->set_device_policy(
       device_policy->GetBlob());
-  chromeos::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
+  ash::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
   run_loop.Run();
   // Allow tasks posted by CrosSettings observers to complete:
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/ash/policy/enrollment/enrollment_handler.h b/chrome/browser/ash/policy/enrollment/enrollment_handler.h
index b687f31..b5c4ed3 100644
--- a/chrome/browser/ash/policy/enrollment/enrollment_handler.h
+++ b/chrome/browser/ash/policy/enrollment/enrollment_handler.h
@@ -17,8 +17,8 @@
 #include "chrome/browser/ash/policy/enrollment/enrollment_config.h"
 #include "chrome/browser/policy/device_account_initializer.h"
 #include "chromeos/ash/components/dbus/authpolicy/authpolicy_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/constants/attestation_constants.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
diff --git a/chrome/browser/ash/policy/handlers/adb_sideloading_allowance_mode_policy_handler.cc b/chrome/browser/ash/policy/handlers/adb_sideloading_allowance_mode_policy_handler.cc
index bb516ce..c9adcd22 100644
--- a/chrome/browser/ash/policy/handlers/adb_sideloading_allowance_mode_policy_handler.cc
+++ b/chrome/browser/ash/policy/handlers/adb_sideloading_allowance_mode_policy_handler.cc
@@ -176,9 +176,9 @@
     return;
   }
 
-  using ResponseCode = chromeos::SessionManagerClient::AdbSideloadResponseCode;
+  using ResponseCode = ash::SessionManagerClient::AdbSideloadResponseCode;
 
-  auto* client = chromeos::SessionManagerClient::Get();
+  auto* client = ash::SessionManagerClient::Get();
   client->QueryAdbSideload(base::BindOnce(
       [](base::OnceCallback<void(bool)> callback, ResponseCode response_code,
          bool enabled) {
diff --git a/chrome/browser/ash/policy/handlers/device_dock_mac_address_source_handler_unittest.cc b/chrome/browser/ash/policy/handlers/device_dock_mac_address_source_handler_unittest.cc
index 3519969a..1d1150c 100644
--- a/chrome/browser/ash/policy/handlers/device_dock_mac_address_source_handler_unittest.cc
+++ b/chrome/browser/ash/policy/handlers/device_dock_mac_address_source_handler_unittest.cc
@@ -10,7 +10,7 @@
 
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
-#include "chromeos/network/mock_network_device_handler.h"
+#include "chromeos/ash/components/network/mock_network_device_handler.h"
 #include "chromeos/network/network_device_handler.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/policy/handlers/device_name_policy_handler_impl_unittest.cc b/chrome/browser/ash/policy/handlers/device_name_policy_handler_impl_unittest.cc
index ec13ea5..998e4284 100644
--- a/chrome/browser/ash/policy/handlers/device_name_policy_handler_impl_unittest.cc
+++ b/chrome/browser/ash/policy/handlers/device_name_policy_handler_impl_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/test/task_environment.h"
 #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h"
 #include "chrome/browser/ash/settings/stub_cros_settings_provider.h"
-#include "chromeos/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "components/policy/core/common/cloud/test/policy_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager.cc b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager.cc
index 2854f6a..aca03d9 100644
--- a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager.cc
+++ b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 
 using RebootOnSignOutPolicy =
diff --git a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc
index 95d36d6..613c800 100644
--- a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc
+++ b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc
@@ -26,9 +26,9 @@
 #include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "chromeos/dbus/anomaly_detector/anomaly_detector_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
diff --git a/chrome/browser/ash/policy/handlers/minimum_version_policy_handler_browsertest.cc b/chrome/browser/ash/policy/handlers/minimum_version_policy_handler_browsertest.cc
index 7e834c4..31de0c7 100644
--- a/chrome/browser/ash/policy/handlers/minimum_version_policy_handler_browsertest.cc
+++ b/chrome/browser/ash/policy/handlers/minimum_version_policy_handler_browsertest.cc
@@ -53,10 +53,10 @@
 #include "chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h"
 #include "chrome/browser/upgrade_detector/upgrade_detector.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/constants/dbus_switches.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_type.h"
diff --git a/chrome/browser/ash/policy/handlers/minimum_version_policy_handler_unittest.cc b/chrome/browser/ash/policy/handlers/minimum_version_policy_handler_unittest.cc
index 532e84b..f39b2ec 100644
--- a/chrome/browser/ash/policy/handlers/minimum_version_policy_handler_unittest.cc
+++ b/chrome/browser/ash/policy/handlers/minimum_version_policy_handler_unittest.cc
@@ -21,11 +21,11 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
 #include "chromeos/dbus/update_engine/update_engine_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ash/policy/handlers/power_policy_browsertest.cc b/chrome/browser/ash/policy/handlers/power_policy_browsertest.cc
index a366af79..0ff3a77a 100644
--- a/chrome/browser/ash/policy/handlers/power_policy_browsertest.cc
+++ b/chrome/browser/ash/policy/handlers/power_policy_browsertest.cc
@@ -32,12 +32,12 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/power_manager/policy.pb.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
diff --git a/chrome/browser/ash/policy/handlers/powerwash_requirements_checker.cc b/chrome/browser/ash/policy/handlers/powerwash_requirements_checker.cc
index 0e3f018..d18cc1a 100644
--- a/chrome/browser/ash/policy/handlers/powerwash_requirements_checker.cc
+++ b/chrome/browser/ash/policy/handlers/powerwash_requirements_checker.cc
@@ -20,8 +20,8 @@
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
 #include "chrome/grit/generated_resources.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/vector_icons/vector_icons.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/ash/policy/handlers/powerwash_requirements_checker_unittest.cc b/chrome/browser/ash/policy/handlers/powerwash_requirements_checker_unittest.cc
index 66f5735..193f04b 100644
--- a/chrome/browser/ash/policy/handlers/powerwash_requirements_checker_unittest.cc
+++ b/chrome/browser/ash/policy/handlers/powerwash_requirements_checker_unittest.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
 #include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ash/policy/handlers/site_isolation_flag_handling_browsertest.cc b/chrome/browser/ash/policy/handlers/site_isolation_flag_handling_browsertest.cc
index 0c05d1a..1f7c91f8 100644
--- a/chrome/browser/ash/policy/handlers/site_isolation_flag_handling_browsertest.cc
+++ b/chrome/browser/ash/policy/handlers/site_isolation_flag_handling_browsertest.cc
@@ -181,7 +181,7 @@
                                                    "1111111111")) {}
 
   void SetUpInProcessBrowserTestFixture() override {
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
 
     // Mark that chrome restart can be requested.
     // Note that AttemptRestart() is mocked out in UserSessionManager through
diff --git a/chrome/browser/ash/policy/handlers/system_proxy_handler_unittest.cc b/chrome/browser/ash/policy/handlers/system_proxy_handler_unittest.cc
index f1bd01a2..5a4c69e 100644
--- a/chrome/browser/ash/policy/handlers/system_proxy_handler_unittest.cc
+++ b/chrome/browser/ash/policy/handlers/system_proxy_handler_unittest.cc
@@ -20,8 +20,8 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/dbus/system_proxy/system_proxy_client.h"
 #include "chromeos/ash/components/dbus/system_proxy/system_proxy_service.pb.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/proxy_config/proxy_config_pref_names.h"
 #include "components/proxy_config/proxy_prefs.h"
 
diff --git a/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler.cc b/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler.cc
index eb94c8f..7926bdd55 100644
--- a/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler.cc
+++ b/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler.cc
@@ -138,8 +138,7 @@
   if (!update_available)
     return;
 
-  chromeos::SessionManagerClient::Get()->StartTPMFirmwareUpdate(
-      "preserve_stateful");
+  ash::SessionManagerClient::Get()->StartTPMFirmwareUpdate("preserve_stateful");
 }
 
 void TPMAutoUpdateModePolicyHandler::SetUpdateCheckerCallbackForTesting(
diff --git a/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler_unittest.cc b/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler_unittest.cc
index cdc71fe6..59c7167b 100644
--- a/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler_unittest.cc
+++ b/chrome/browser/ash/policy/handlers/tpm_auto_update_mode_policy_handler_unittest.cc
@@ -43,11 +43,11 @@
       : local_state_(TestingBrowserProcess::GetGlobal()),
         user_manager_(new ash::FakeChromeUserManager()),
         user_manager_enabler_(base::WrapUnique(user_manager_)) {
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
   }
 
   ~TPMAutoUpdateModePolicyHandlerTest() override {
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
   }
 
   void SetAutoUpdateMode(AutoUpdateMode auto_update_mode) {
@@ -96,7 +96,7 @@
 
   update_available_ = true;
 
-  auto* fake_session_manager_client = chromeos::FakeSessionManagerClient::Get();
+  auto* fake_session_manager_client = ash::FakeSessionManagerClient::Get();
 
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
@@ -136,7 +136,7 @@
 
   SetAutoUpdateMode(AutoUpdateMode::kWithoutAcknowledgment);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
+  EXPECT_EQ(0, ash::FakeSessionManagerClient::Get()
                    ->start_tpm_firmware_update_call_count());
 }
 
@@ -166,7 +166,7 @@
   base::RunLoop().RunUntilIdle();
 
   // TPM update is not triggered.
-  EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
+  EXPECT_EQ(0, ash::FakeSessionManagerClient::Get()
                    ->start_tpm_firmware_update_call_count());
 
   EXPECT_EQ(last_shown_notification_,
@@ -203,7 +203,7 @@
   base::RunLoop().RunUntilIdle();
 
   // TPM update is not triggered.
-  EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
+  EXPECT_EQ(0, ash::FakeSessionManagerClient::Get()
                    ->start_tpm_firmware_update_call_count());
 
   // Show planned update notification.
@@ -239,7 +239,7 @@
 
   SetAutoUpdateMode(AutoUpdateMode::kUserAcknowledgment);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
+  EXPECT_EQ(0, ash::FakeSessionManagerClient::Get()
                    ->start_tpm_firmware_update_call_count());
 
   // Show planned update notification.
@@ -273,7 +273,7 @@
   base::RunLoop().RunUntilIdle();
 
   // Update is triggered.
-  EXPECT_EQ(1, chromeos::FakeSessionManagerClient::Get()
+  EXPECT_EQ(1, ash::FakeSessionManagerClient::Get()
                    ->start_tpm_firmware_update_call_count());
 }
 
diff --git a/chrome/browser/ash/policy/invalidation/affiliated_invalidation_service_provider_impl_unittest.cc b/chrome/browser/ash/policy/invalidation/affiliated_invalidation_service_provider_impl_unittest.cc
index 438bf610..e378b3b 100644
--- a/chrome/browser/ash/policy/invalidation/affiliated_invalidation_service_provider_impl_unittest.cc
+++ b/chrome/browser/ash/policy/invalidation/affiliated_invalidation_service_provider_impl_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 #include "components/invalidation/impl/fake_invalidation_handler.h"
 #include "components/invalidation/impl/fake_invalidation_service.h"
 #include "components/invalidation/impl/fcm_invalidation_service.h"
diff --git a/chrome/browser/ash/policy/networking/euicc_status_uploader_unittest.cc b/chrome/browser/ash/policy/networking/euicc_status_uploader_unittest.cc
index 01b9a39b6..8eeacc9 100644
--- a/chrome/browser/ash/policy/networking/euicc_status_uploader_unittest.cc
+++ b/chrome/browser/ash/policy/networking/euicc_status_uploader_unittest.cc
@@ -10,11 +10,11 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/values_test_util.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/components/onc/onc_utils.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/managed_cellular_pref_handler.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_ui_data.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job.cc
index e6d67329..928ad94 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job.cc
@@ -13,7 +13,7 @@
 #include "base/syslog_logging.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 
 namespace policy {
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job.h b/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job.h
index 9ec27e7..38612a82 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job.h
+++ b/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "components/policy/core/common/remote_commands/remote_command_job.h"
 
 namespace policy {
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job_unittest.cc
index 2007f5b..5b05541 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_get_available_routines_job_unittest.cc
@@ -13,8 +13,8 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job.cc
index 4df76c5..1ce996d8 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job.cc
@@ -16,7 +16,7 @@
 #include "base/syslog_logging.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job.h b/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job.h
index 9e85cfa..86d8f1b1 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job.h
+++ b/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job.h
@@ -8,7 +8,7 @@
 #include <cstdint>
 
 #include "base/memory/weak_ptr.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "components/policy/core/common/remote_commands/remote_command_job.h"
 
 namespace policy {
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job_unittest.cc
index a530933..72712514 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_get_routine_update_job_unittest.cc
@@ -13,8 +13,8 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job.cc
index 49bd1db..1a9f66d 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job.cc
@@ -29,7 +29,7 @@
 constexpr base::TimeDelta kFailsafeTimerTimeout = base::Seconds(10);
 
 void StartPowerwash(enterprise_management::SignedData signed_command) {
-  chromeos::SessionManagerClient::Get()->StartRemoteDeviceWipe(signed_command);
+  ash::SessionManagerClient::Get()->StartRemoteDeviceWipe(signed_command);
 }
 
 }  // namespace
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job_unittest.cc
index 965ae61d..501feb2 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job_unittest.cc
@@ -93,7 +93,7 @@
 
   const std::unique_ptr<MockCloudPolicyClient> client_;
   const std::unique_ptr<TestingRemoteCommandsService> service_;
-  chromeos::ScopedFakeInMemorySessionManagerClient scoped_session_manager_;
+  ash::ScopedFakeInMemorySessionManagerClient scoped_session_manager_;
 };
 
 DeviceCommandRemotePowerwashJobTest::DeviceCommandRemotePowerwashJobTest()
@@ -120,8 +120,8 @@
       CreateRemotePowerwashJob(kCommandAge, service_.get());
 
   // No powerwash at this point.
-  EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
-                   ->start_device_wipe_call_count());
+  EXPECT_EQ(
+      0, ash::FakeSessionManagerClient::Get()->start_device_wipe_call_count());
 
   EXPECT_TRUE(job->Run(base::Time::Now(), base::TimeTicks::Now(),
                        run_loop_.QuitClosure()));
@@ -134,7 +134,7 @@
   // server the powerwash would start.
 
   base::RunLoop run_loop2;
-  chromeos::FakeSessionManagerClient::Get()->set_on_start_device_wipe_callback(
+  ash::FakeSessionManagerClient::Get()->set_on_start_device_wipe_callback(
       base::BindLambdaForTesting([&]() { run_loop2.Quit(); }));
 
   // Simulate a response from the server by posting a task and waiting for
@@ -144,8 +144,8 @@
   run_loop2.Run();
 
   // One powerwash coming up.
-  EXPECT_EQ(1, chromeos::FakeSessionManagerClient::Get()
-                   ->start_device_wipe_call_count());
+  EXPECT_EQ(
+      1, ash::FakeSessionManagerClient::Get()->start_device_wipe_call_count());
 }
 
 // Make sure that the failsafe timer starts the powerwash in case of no ACK.
@@ -154,8 +154,8 @@
       CreateRemotePowerwashJob(kCommandAge, service_.get());
 
   // No powerwash at this point.
-  EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
-                   ->start_device_wipe_call_count());
+  EXPECT_EQ(
+      0, ash::FakeSessionManagerClient::Get()->start_device_wipe_call_count());
 
   // Run job + succeeded_callback.
   EXPECT_TRUE(job->Run(base::Time::Now(), base::TimeTicks::Now(),
@@ -164,13 +164,13 @@
 
   // After 5s the timer is not run yet.
   task_runner_->FastForwardBy(base::Seconds(5));
-  EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
-                   ->start_device_wipe_call_count());
+  EXPECT_EQ(
+      0, ash::FakeSessionManagerClient::Get()->start_device_wipe_call_count());
 
   // After 10s the timer is run.
   task_runner_->FastForwardBy(base::Seconds(5));
-  EXPECT_EQ(1, chromeos::FakeSessionManagerClient::Get()
-                   ->start_device_wipe_call_count());
+  EXPECT_EQ(
+      1, ash::FakeSessionManagerClient::Get()->start_device_wipe_call_count());
 }
 
 }  // namespace policy
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job_unittest.cc
index e70cf0b..0729163 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job_unittest.cc
@@ -10,13 +10,13 @@
 #include "chrome/browser/notifications/system_notification_helper.h"
 #include "chrome/test/base/chrome_ash_test_base.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/hermes/hermes_clients.h"
 #include "chromeos/dbus/hermes/hermes_euicc_client.h"
 #include "chromeos/dbus/hermes/hermes_manager_client.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/prefs/testing_pref_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.cc
index 3e0ba886..e45c6e5 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.cc
@@ -18,7 +18,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.h b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.h
index 3b53fde..9e36eda 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.h
+++ b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job.h
@@ -7,7 +7,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "components/policy/core/common/remote_commands/remote_command_job.h"
 
 namespace policy {
@@ -45,8 +45,8 @@
   // Which routine the DeviceCommandRunRoutineJob will run.
   chromeos::cros_healthd::mojom::DiagnosticRoutineEnum routine_enum_;
   // Parameters for the routine to be run. See
-  // chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom for details
-  // on the parameters accepted by each individual routine.
+  // chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
+  // details on the parameters accepted by each individual routine.
   base::Value params_dict_;
 
   base::WeakPtrFactory<DeviceCommandRunRoutineJob> weak_ptr_factory_{this};
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job_unittest.cc
index 27f9c07c..2865861 100644
--- a/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/device_command_run_routine_job_unittest.cc
@@ -13,8 +13,8 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/ash/policy/reporting/arc_app_install_event_log_collector_unittest.cc b/chrome/browser/ash/policy/reporting/arc_app_install_event_log_collector_unittest.cc
index 440fbc89..fde7003 100644
--- a/chrome/browser/ash/policy/reporting/arc_app_install_event_log_collector_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/arc_app_install_event_log_collector_unittest.cc
@@ -18,9 +18,9 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chrome/browser/ash/policy/reporting/arc_app_install_event_logger_unittest.cc b/chrome/browser/ash/policy/reporting/arc_app_install_event_logger_unittest.cc
index 1708ef6f..0e0f20fb 100644
--- a/chrome/browser/ash/policy/reporting/arc_app_install_event_logger_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/arc_app_install_event_logger_unittest.cc
@@ -17,8 +17,8 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/policy/policy_constants.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/policy/reporting/extension_install_event_log_collector_unittest.cc b/chrome/browser/ash/policy/reporting/extension_install_event_log_collector_unittest.cc
index e6b2671..be1bad0 100644
--- a/chrome/browser/ash/policy/reporting/extension_install_event_log_collector_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/extension_install_event_log_collector_unittest.cc
@@ -16,9 +16,9 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/user_manager/scoped_user_manager.h"
diff --git a/chrome/browser/ash/policy/reporting/extension_install_event_logger_unittest.cc b/chrome/browser/ash/policy/reporting/extension_install_event_logger_unittest.cc
index 09eee32..d9b2a4a 100644
--- a/chrome/browser/ash/policy/reporting/extension_install_event_logger_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/extension_install_event_logger_unittest.cc
@@ -13,8 +13,8 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/policy/policy_constants.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.cc
index ec05adf..7e07216 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
 
 namespace reporting {
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.h b/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.h
index 9b6c9d14..21e6fc8 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.h
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_ASH_POLICY_REPORTING_METRICS_REPORTING_AUDIO_AUDIO_EVENTS_OBSERVER_H_
 
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_events_observer_base.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
 
 namespace reporting {
 
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer_unittest.cc
index c2b1713..e0d1667 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/audio/audio_events_observer_unittest.cc
@@ -9,8 +9,8 @@
 #include <utility>
 
 #include "base/test/task_environment.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "components/reporting/util/test_support_callbacks.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_events_observer_base_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_events_observer_base_unittest.cc
index 4ff29a8..75ff4b5 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_events_observer_base_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_events_observer_base_unittest.cc
@@ -11,9 +11,9 @@
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.cc
index e58bf0d..e8f704d 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h"
 
 #include "base/logging.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace cros_healthd = chromeos::cros_healthd::mojom;
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h
index 22fe014..1ad7090 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_ASH_POLICY_REPORTING_METRICS_REPORTING_CROS_HEALTHD_METRIC_SAMPLER_H_
 #define CHROME_BROWSER_ASH_POLICY_REPORTING_METRICS_REPORTING_CROS_HEALTHD_METRIC_SAMPLER_H_
 
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "components/reporting/metrics/sampler.h"
 
 namespace reporting {
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc
index f20c882..067c161 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
 #include "components/reporting/util/test_support_callbacks.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h
index bf134d7..95ed9aee 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h
@@ -19,7 +19,7 @@
 #include "chrome/browser/ash/policy/status_collector/managed_session_service.h"
 #include "chrome/browser/ash/settings/device_settings_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "components/reporting/proto/synced/record_constants.pb.h"
 
 namespace reporting {
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_sampler_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_sampler_unittest.cc
index 1902598..2e6767b0 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_sampler_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/https_latency_sampler_unittest.cc
@@ -17,8 +17,8 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/net/network_diagnostics/network_diagnostics.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
 #include "components/reporting/util/test_support_callbacks.h"
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_events_observer.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_events_observer.cc
index f02ca74f..cb690873 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_events_observer.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_events_observer.cc
@@ -6,9 +6,9 @@
 
 #include <utility>
 
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_type_pattern.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
 
 namespace reporting {
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_events_observer_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_events_observer_unittest.cc
index 5e5a1d4..4ce7efc 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_events_observer_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_events_observer_unittest.cc
@@ -9,8 +9,8 @@
 
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
-#include "chromeos/network/network_handler_test_helper.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_info_sampler_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_info_sampler_unittest.cc
index c1dc25a..a0f1ac6 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_info_sampler_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_info_sampler_unittest.cc
@@ -13,10 +13,10 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/hermes/hermes_manager_client.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
 #include "dbus/object_path.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler.cc
index a0c7cdda..e013b70 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler.cc
@@ -15,10 +15,10 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_type_pattern.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
 
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler.h b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler.h
index e7f5d133..047c400 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler.h
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_ASH_POLICY_REPORTING_METRICS_REPORTING_NETWORK_NETWORK_TELEMETRY_SAMPLER_H_
 
 #include "base/memory/weak_ptr.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "components/reporting/metrics/sampler.h"
 
 namespace reporting {
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc
index 72be274..c622c6f 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/network/network_telemetry_sampler_unittest.cc
@@ -15,13 +15,13 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/metric_reporting_manager.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
 #include "chromeos/dbus/shill/shill_ipconfig_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/tether_constants.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
 #include "components/reporting/metrics/fake_sampler.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
 #include "components/reporting/util/test_support_callbacks.h"
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer.cc
index 5c68136..36425a03 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "components/reporting/proto/synced/metric_data.pb.h"
 
 using UsbEventInfoPtr = chromeos::cros_healthd::mojom::UsbEventInfoPtr;
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer.h b/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer.h
index 8863c6b..3596d5b 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer.h
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_ASH_POLICY_REPORTING_METRICS_REPORTING_USB_USB_EVENTS_OBSERVER_H_
 
 #include "chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_events_observer_base.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
 
 using UsbEventInfoPtr = chromeos::cros_healthd::mojom::UsbEventInfoPtr;
 
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer_unittest.cc
index c0cf11a..a7d0edf7 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/usb/usb_events_observer_unittest.cc
@@ -8,8 +8,8 @@
 
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "components/reporting/util/test_support_callbacks.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/policy/rsu/lookup_key_uploader.cc b/chrome/browser/ash/policy/rsu/lookup_key_uploader.cc
index e57c681..14d9dbd 100644
--- a/chrome/browser/ash/policy/rsu/lookup_key_uploader.cc
+++ b/chrome/browser/ash/policy/rsu/lookup_key_uploader.cc
@@ -10,8 +10,8 @@
 #include "base/time/default_clock.h"
 #include "chrome/browser/ash/policy/core/device_cloud_policy_store_ash.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 #include "components/prefs/pref_service.h"
 
diff --git a/chrome/browser/ash/policy/rsu/lookup_key_uploader_unittest.cc b/chrome/browser/ash/policy/rsu/lookup_key_uploader_unittest.cc
index 4e49623..ee41c89b 100644
--- a/chrome/browser/ash/policy/rsu/lookup_key_uploader_unittest.cc
+++ b/chrome/browser/ash/policy/rsu/lookup_key_uploader_unittest.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/ash/attestation/mock_enrollment_certificate_uploader.h"
 #include "chrome/browser/ash/settings/device_settings_test_helper.h"
 #include "chrome/common/pref_names.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/pref_registry_simple.h"
diff --git a/chrome/browser/ash/policy/scheduled_task_handler/test/device_scheduled_update_checker_unittest.cc b/chrome/browser/ash/policy/scheduled_task_handler/test/device_scheduled_update_checker_unittest.cc
index cecae04..37c9fc3 100644
--- a/chrome/browser/ash/policy/scheduled_task_handler/test/device_scheduled_update_checker_unittest.cc
+++ b/chrome/browser/ash/policy/scheduled_task_handler/test/device_scheduled_update_checker_unittest.cc
@@ -34,6 +34,7 @@
 #include "chrome/browser/ash/settings/stub_cros_settings_provider.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
@@ -42,7 +43,6 @@
 #include "chromeos/dbus/update_engine/update_engine_client.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "components/policy/core/common/policy_service.h"
 #include "services/device/public/cpp/test/test_wake_lock_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.cc b/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.cc
index 46fdec6..9b3bbbe5 100644
--- a/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.cc
+++ b/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.cc
@@ -29,7 +29,7 @@
 }  // namespace
 
 ServerBackedStateKeysBroker::ServerBackedStateKeysBroker(
-    chromeos::SessionManagerClient* session_manager_client)
+    ash::SessionManagerClient* session_manager_client)
     : session_manager_client_(session_manager_client), requested_(false) {}
 
 ServerBackedStateKeysBroker::~ServerBackedStateKeysBroker() {}
diff --git a/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.h b/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.h
index 1d021d3..0ca9e3a 100644
--- a/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.h
+++ b/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.h
@@ -13,12 +13,12 @@
 #include "base/callback_list.h"
 #include "base/memory/weak_ptr.h"
 
-namespace base {
-class TimeDelta;
+namespace ash {
+class SessionManagerClient;
 }
 
-namespace chromeos {
-class SessionManagerClient;
+namespace base {
+class TimeDelta;
 }
 
 namespace policy {
@@ -35,7 +35,7 @@
   using StateKeysCallback = StateKeysCallbackList::CallbackType;
 
   explicit ServerBackedStateKeysBroker(
-      chromeos::SessionManagerClient* session_manager_client);
+      ash::SessionManagerClient* session_manager_client);
 
   ServerBackedStateKeysBroker(const ServerBackedStateKeysBroker&) = delete;
   ServerBackedStateKeysBroker& operator=(const ServerBackedStateKeysBroker&) =
@@ -82,7 +82,7 @@
   // Stores newly-received state keys and notifies consumers.
   void StoreStateKeys(const std::vector<std::string>& state_keys);
 
-  chromeos::SessionManagerClient* session_manager_client_;
+  ash::SessionManagerClient* session_manager_client_;
 
   // The current set of state keys.
   std::vector<std::string> state_keys_;
diff --git a/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker_unittest.cc b/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker_unittest.cc
index ad7b6c6..d8496ff 100644
--- a/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker_unittest.cc
+++ b/chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker_unittest.cc
@@ -49,7 +49,7 @@
  protected:
   base::test::SingleThreadTaskEnvironment task_environment_;
   base::ScopedMockTimeMessageLoopTaskRunner mocked_main_runner_;
-  chromeos::FakeSessionManagerClient fake_session_manager_client_;
+  ash::FakeSessionManagerClient fake_session_manager_client_;
   ServerBackedStateKeysBroker broker_;
   std::vector<std::string> state_keys_;
   bool updated_;
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector.cc b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
index 7f799b0f..73d1fc8 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
@@ -67,6 +67,7 @@
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/dbus/attestation/attestation_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/hermes/hermes_euicc_client.h"
@@ -81,7 +82,6 @@
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector.h b/chrome/browser/ash/policy/status_collector/device_status_collector.h
index d54d7ee..fcadffd 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector.h
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector.h
@@ -26,10 +26,10 @@
 #include "base/timer/timer.h"
 #include "chrome/browser/ash/policy/status_collector/app_info_generator.h"
 #include "chrome/browser/ash/policy/status_collector/status_collector.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/pref_member.h"
 #include "ui/base/idle/idle.h"
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
index ed5eeddd..7b9443b 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
@@ -68,6 +68,11 @@
 #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h"
 #include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/dbus/attestation/attestation_client.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -79,16 +84,11 @@
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
 #include "chromeos/dbus/update_engine/update_engine_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "components/account_id/account_id.h"
 #include "components/ownership/mock_owner_key_util.h"
diff --git a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.cc b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.cc
index b070d2f..117ec3c 100644
--- a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.cc
+++ b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.cc
@@ -66,6 +66,8 @@
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/dbus/attestation/attestation_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
@@ -78,8 +80,6 @@
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
diff --git a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h
index 93ee63f2..47e09b8 100644
--- a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h
+++ b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector.h
@@ -26,9 +26,9 @@
 #include "chrome/browser/ash/policy/status_collector/app_info_generator.h"
 #include "chrome/browser/ash/policy/status_collector/device_status_collector.h"
 #include "chrome/browser/ash/policy/status_collector/status_collector.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "components/prefs/pref_member.h"
 #include "ui/base/idle/idle.h"
diff --git a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc
index b26a1e7..f83cfcd 100644
--- a/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/legacy_device_status_collector_browsertest.cc
@@ -66,6 +66,10 @@
 #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h"
 #include "chromeos/ash/components/dbus/concierge/concierge_client.h"
 #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/dbus/attestation/attestation_client.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -77,15 +81,11 @@
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
 #include "chromeos/dbus/update_engine/update_engine_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/vm_applications/apps.pb.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "components/account_id/account_id.h"
 #include "components/ownership/mock_owner_key_util.h"
diff --git a/chrome/browser/ash/printing/cups_printers_manager.cc b/chrome/browser/ash/printing/cups_printers_manager.cc
index 0b20434..82f1750 100644
--- a/chrome/browser/ash/printing/cups_printers_manager.cc
+++ b/chrome/browser/ash/printing/cups_printers_manager.cc
@@ -39,7 +39,7 @@
 #include "chromeos/printing/cups_printer_status.h"
 #include "chromeos/printing/printing_constants.h"
 #include "chromeos/printing/uri.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "components/device_event_log/device_event_log.h"
 #include "components/policy/policy_constants.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -81,7 +81,7 @@
       public EnterprisePrintersProvider::Observer,
       public PrintServersManager::Observer,
       public SyncedPrintersManager::Observer,
-      public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+      public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   // Identifiers for each of the underlying PrinterDetectors this
   // class observes.
@@ -282,7 +282,7 @@
     NotifyObservers({PrinterClass::kEnterprise});
   }
 
-  // mojom::CrosNetworkConfigObserver implementation.
+  // CrosNetworkConfigObserver implementation.
   void OnActiveNetworksChanged(
       std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
           networks) override {
@@ -303,15 +303,6 @@
     RebuildDetectedLists();
   }
 
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr /* network */)
-      override {}
-  void OnNetworkStateListChanged() override {}
-  void OnDeviceStateListChanged() override {}
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
-
   // Callback for PrinterDetectors.
   void OnPrintersFound(
       int detector_id,
diff --git a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc
index 5ad4dc6..4e0c56a0 100644
--- a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc
+++ b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc
@@ -11,8 +11,11 @@
 
 #include "base/bind.h"
 #include "base/check.h"
+#include "base/containers/contains.h"
+#include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "chrome/common/channel_info.h"
+#include "chromeos/printing/uri.h"
 #include "components/sync/base/report_unrecoverable_error.h"
 #include "components/sync/model/client_tag_based_model_type_processor.h"
 #include "components/sync/model/entity_change.h"
@@ -22,6 +25,7 @@
 #include "components/sync/model/model_type_store.h"
 #include "components/sync/model/model_type_store_base.h"
 #include "components/sync/model/model_type_sync_bridge.h"
+#include "components/sync/model/mutable_data_batch.h"
 #include "components/sync/protocol/entity_data.h"
 #include "components/sync/protocol/entity_specifics.pb.h"
 #include "components/sync/protocol/printers_authorization_server_specifics.pb.h"
@@ -29,6 +33,25 @@
 
 namespace ash::printing::oauth2 {
 
+namespace {
+
+sync_pb::PrintersAuthorizationServerSpecifics ToSpecifics(
+    const std::string& uri) {
+  sync_pb::PrintersAuthorizationServerSpecifics specifics;
+  specifics.set_uri(uri);
+  return specifics;
+}
+
+std::unique_ptr<syncer::EntityData> ToEntityDataPtr(const std::string& uri) {
+  auto entity_data = std::make_unique<syncer::EntityData>();
+  *entity_data->specifics.mutable_printers_authorization_server() =
+      ToSpecifics(uri);
+  entity_data->name = uri;
+  return entity_data;
+}
+
+}  // namespace
+
 std::unique_ptr<ProfileAuthServersSyncBridge>
 ProfileAuthServersSyncBridge::Create(
     Observer* observer,
@@ -55,6 +78,22 @@
 
 ProfileAuthServersSyncBridge::~ProfileAuthServersSyncBridge() = default;
 
+void ProfileAuthServersSyncBridge::AddAuthorizationServer(
+    const chromeos::Uri& server_uri) {
+  DCHECK(initialization_completed_);
+  const std::string key = server_uri.GetNormalized(/*always_print_port=*/false);
+  servers_uris_.insert(key);
+  auto batch = store_->CreateWriteBatch();
+  batch->WriteData(key, ToSpecifics(key).SerializeAsString());
+  if (change_processor()->IsTrackingMetadata()) {
+    change_processor()->Put(key, ToEntityDataPtr(key),
+                            batch->GetMetadataChangeList());
+  }
+  store_->CommitWriteBatch(
+      std::move(batch), base::BindOnce(&ProfileAuthServersSyncBridge::OnCommit,
+                                       weak_ptr_factory_.GetWeakPtr()));
+}
+
 ProfileAuthServersSyncBridge::ProfileAuthServersSyncBridge(
     std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
     syncer::OnceModelTypeStoreFactory store_factory,
@@ -113,6 +152,7 @@
     return;
   }
   change_processor()->ModelReadyToSync(std::move(metadata_batch));
+  initialization_completed_ = true;
   observer_->OnProfileAuthorizationServersInitialized();
 }
 
@@ -124,6 +164,35 @@
 absl::optional<syncer::ModelError> ProfileAuthServersSyncBridge::MergeSyncData(
     std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
     syncer::EntityChangeList entity_data) {
+  // Every local URI is considered unsynced until the contrary is proven, i.e.
+  // until the same URI is seen in the incoming |entity_data|.
+  std::set<std::string> unsynced_local_uris = servers_uris_;
+  std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch =
+      store_->CreateWriteBatch();
+
+  for (const std::unique_ptr<syncer::EntityChange>& change : entity_data) {
+    const sync_pb::PrintersAuthorizationServerSpecifics& specifics =
+        change->data().specifics.printers_authorization_server();
+    const std::string remote_uri = specifics.uri();
+    DCHECK_EQ(change->storage_key(), remote_uri);
+    auto [unused, is_new] = servers_uris_.insert(remote_uri);
+    if (is_new) {
+      batch->WriteData(remote_uri, specifics.SerializeAsString());
+    } else {
+      unsynced_local_uris.erase(remote_uri);
+    }
+  }
+
+  for (const std::string& uri : unsynced_local_uris) {
+    change_processor()->Put(uri, ToEntityDataPtr(uri),
+                            metadata_change_list.get());
+  }
+
+  batch->TakeMetadataChangesFrom(std::move(metadata_change_list));
+  store_->CommitWriteBatch(
+      std::move(batch), base::BindOnce(&ProfileAuthServersSyncBridge::OnCommit,
+                                       weak_ptr_factory_.GetWeakPtr()));
+
   return absl::nullopt;
 }
 
@@ -138,7 +207,13 @@
                                            DataCallback callback) {}
 
 void ProfileAuthServersSyncBridge::GetAllDataForDebugging(
-    DataCallback callback) {}
+    DataCallback callback) {
+  auto batch = std::make_unique<syncer::MutableDataBatch>();
+  for (const auto& uri : servers_uris_) {
+    batch->Put(uri, ToEntityDataPtr(uri));
+  }
+  std::move(callback).Run(std::move(batch));
+}
 
 std::string ProfileAuthServersSyncBridge::GetClientTag(
     const syncer::EntityData& entity_data) {
@@ -151,4 +226,13 @@
   return entity_data.specifics.printers_authorization_server().uri();
 }
 
+void ProfileAuthServersSyncBridge::OnCommit(
+    const absl::optional<syncer::ModelError>& error) {
+  if (error) {
+    LOG(WARNING) << "Failed to commit operation to store in "
+                    "ProfileAuthServersSyncBridge";
+    change_processor()->ReportError(*error);
+  }
+}
+
 }  // namespace ash::printing::oauth2
diff --git a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h
index 3b1d96bea..f245f5e 100644
--- a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h
+++ b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h
@@ -17,6 +17,10 @@
 #include "components/sync/model/model_type_sync_bridge.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
+namespace chromeos {
+class Uri;
+}
+
 namespace syncer {
 struct EntityData;
 class ModelTypeChangeProcessor;
@@ -58,6 +62,10 @@
 
   ~ProfileAuthServersSyncBridge() override;
 
+  // This method must be called when new Authorization Server is added to the
+  // list of trusted Authorization Servers.
+  void AddAuthorizationServer(const chromeos::Uri& server);
+
  private:
   ProfileAuthServersSyncBridge(
       std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
@@ -91,8 +99,17 @@
   std::string GetClientTag(const syncer::EntityData& entity_data) override;
   std::string GetStorageKey(const syncer::EntityData& entity_data) override;
 
+  // Callback to handle commit errors.
+  void OnCommit(const absl::optional<syncer::ModelError>& error);
+
+  // This is set to true when the object is ready to use. Use the callback
+  // from the Observer to check this. This field is used only for internal
+  // validation.
+  bool initialization_completed_ = false;
+
   // The current trusted list of Authorization Servers URIs.
   std::set<std::string> servers_uris_;
+
   // The local storage.
   std::unique_ptr<syncer::ModelTypeStore> store_;
 
diff --git a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc
index ab73d239..d35f30a5 100644
--- a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc
+++ b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc
@@ -7,8 +7,14 @@
 #include <memory>
 
 #include "base/run_loop.h"
+#include "base/test/bind.h"
 #include "base/test/task_environment.h"
+#include "chromeos/printing/uri.h"
+#include "components/sync/model/data_batch.h"
+#include "components/sync/model/entity_change.h"
+#include "components/sync/model/in_memory_metadata_change_list.h"
 #include "components/sync/model/model_type_store.h"
+#include "components/sync/protocol/entity_data.h"
 #include "components/sync/test/model/mock_model_type_change_processor.h"
 #include "components/sync/test/model/model_type_store_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -17,6 +23,13 @@
 namespace ash::printing::oauth2 {
 namespace {
 
+syncer::EntityData ToEntityData(const std::string& uri) {
+  syncer::EntityData entity_data;
+  entity_data.specifics.mutable_printers_authorization_server()->set_uri(uri);
+  entity_data.name = uri;
+  return entity_data;
+}
+
 class MockProfileAuthServersSyncBridgeObserver
     : public ProfileAuthServersSyncBridge::Observer {
  public:
@@ -34,6 +47,43 @@
         &mock_observer_, mock_processor_.CreateForwardingProcessor(),
         syncer::ModelTypeStoreTestUtil::FactoryForForwardingStore(
             store_.get()));
+    base::RunLoop loop;
+    EXPECT_CALL(mock_observer_, OnProfileAuthorizationServersInitialized())
+        .Times(1)
+        .WillOnce([&loop] { loop.Quit(); });
+    loop.Run();
+  }
+
+  void DoInitialMerge(const std::vector<std::string>& records) {
+    syncer::ModelTypeSyncBridge* bridge = bridge_.get();
+    syncer::EntityChangeList data_change_list;
+    for (const std::string& uri : records) {
+      data_change_list.push_back(
+          syncer::EntityChange::CreateAdd(uri, ToEntityData(uri)));
+    }
+    ON_CALL(mock_processor_, IsTrackingMetadata())
+        .WillByDefault(testing::Return(true));
+    bridge->MergeSyncData(bridge->CreateMetadataChangeList(),
+                          std::move(data_change_list));
+  }
+
+  std::vector<std::string> GetAllData() {
+    std::unique_ptr<syncer::DataBatch> output;
+    syncer::ModelTypeSyncBridge* bridge = bridge_.get();
+    base::RunLoop loop;
+    auto callback = [&output, &loop](std::unique_ptr<syncer::DataBatch> data) {
+      output = std::move(data);
+      loop.Quit();
+    };
+    bridge->GetAllDataForDebugging(base::BindLambdaForTesting(callback));
+    loop.Run();
+
+    std::vector<std::string> uris;
+    while (output->HasNext()) {
+      auto [key, data] = output->Next();
+      uris.emplace_back(key);
+    }
+    return uris;
   }
 
   // In memory model type store needs to be able to post tasks.
@@ -46,12 +96,51 @@
 };
 
 TEST_F(PrintingOAuth2ProfileAuthServersSyncBridgeTest, Initialization) {
-  base::RunLoop loop;
   CreateBridge();
-  EXPECT_CALL(mock_observer_, OnProfileAuthorizationServersInitialized())
-      .Times(1)
-      .WillOnce([&loop] { loop.Quit(); });
-  loop.Run();
+}
+
+TEST_F(PrintingOAuth2ProfileAuthServersSyncBridgeTest, MergeSyncData) {
+  const std::string uri_1 = "https://a.b.c/123";
+  const std::string uri_2 = "https://d.e.f:123/g/h/i";
+  CreateBridge();
+  DoInitialMerge({uri_1, uri_2});
+
+  const std::vector<std::string> uris = GetAllData();
+  EXPECT_EQ(uris, (std::vector{uri_1, uri_2}));
+}
+
+TEST_F(PrintingOAuth2ProfileAuthServersSyncBridgeTest,
+       ServersAddedWhenSyncDisabled) {
+  const std::string uri_1 = "https://a.b.c/123";
+  CreateBridge();
+  bridge_->AddAuthorizationServer(chromeos::Uri(uri_1));
+
+  const std::vector<std::string> uris = GetAllData();
+  EXPECT_EQ(uris, std::vector{uri_1});
+}
+
+TEST_F(PrintingOAuth2ProfileAuthServersSyncBridgeTest,
+       ServersAddedAfterInitialMerge) {
+  const std::string uri_1 = "https://a.b.c/123";
+  const std::string uri_2 = "https://d.e.f:123/g/h/i";
+  CreateBridge();
+  DoInitialMerge({uri_2});
+  bridge_->AddAuthorizationServer(chromeos::Uri(uri_1));
+
+  const std::vector<std::string> uris = GetAllData();
+  EXPECT_EQ(uris, (std::vector{uri_1, uri_2}));
+}
+
+TEST_F(PrintingOAuth2ProfileAuthServersSyncBridgeTest,
+       ServersAddedBeforeInitialMerge) {
+  const std::string uri_1 = "https://a.b.c/123";
+  const std::string uri_2 = "https://d.e.f:123/g/h/i";
+  CreateBridge();
+  bridge_->AddAuthorizationServer(chromeos::Uri(uri_1));
+  DoInitialMerge({uri_2});
+
+  const std::vector<std::string> uris = GetAllData();
+  EXPECT_EQ(uris, (std::vector{uri_1, uri_2}));
 }
 
 }  // namespace
diff --git a/chrome/browser/ash/proxy_config_service_impl_unittest.cc b/chrome/browser/ash/proxy_config_service_impl_unittest.cc
index 243ac95..d010a85e 100644
--- a/chrome/browser/ash/proxy_config_service_impl_unittest.cc
+++ b/chrome/browser/ash/proxy_config_service_impl_unittest.cc
@@ -15,11 +15,11 @@
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/proxy/proxy_config_handler.h"
 #include "chromeos/ash/components/network/proxy/proxy_config_service_impl.h"
 #include "chromeos/components/onc/onc_utils.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/ash/settings/device_settings_service.cc b/chrome/browser/ash/settings/device_settings_service.cc
index 2822532..c9cb26a 100644
--- a/chrome/browser/ash/settings/device_settings_service.cc
+++ b/chrome/browser/ash/settings/device_settings_service.cc
@@ -96,7 +96,7 @@
 }
 
 void DeviceSettingsService::SetSessionManager(
-    chromeos::SessionManagerClient* session_manager_client,
+    SessionManagerClient* session_manager_client,
     scoped_refptr<OwnerKeyUtil> owner_key_util) {
   DCHECK(session_manager_client);
   DCHECK(owner_key_util.get());
diff --git a/chrome/browser/ash/settings/device_settings_service.h b/chrome/browser/ash/settings/device_settings_service.h
index 773c488..46749ff 100644
--- a/chrome/browser/ash/settings/device_settings_service.h
+++ b/chrome/browser/ash/settings/device_settings_service.h
@@ -48,7 +48,7 @@
 //
 // DeviceSettingsService generates notifications for key and policy update
 // events so interested parties can reload state as appropriate.
-class DeviceSettingsService : public chromeos::SessionManagerClient::Observer {
+class DeviceSettingsService : public SessionManagerClient::Observer {
  public:
   // Indicates ownership status of the device (listed in upgrade order).
   enum OwnershipStatus {
@@ -112,7 +112,7 @@
   ~DeviceSettingsService() override;
 
   // To be called on startup once threads are initialized and D-Bus is ready.
-  void SetSessionManager(chromeos::SessionManagerClient* session_manager_client,
+  void SetSessionManager(SessionManagerClient* session_manager_client,
                          scoped_refptr<ownership::OwnerKeyUtil> owner_key_util);
 
   // Prevents the service from making further calls to session_manager_client
@@ -259,7 +259,7 @@
   // Processes pending callbacks from GetOwnershipStatusAsync().
   void RunPendingOwnershipStatusCallbacks();
 
-  chromeos::SessionManagerClient* session_manager_client_ = nullptr;
+  SessionManagerClient* session_manager_client_ = nullptr;
   scoped_refptr<ownership::OwnerKeyUtil> owner_key_util_;
 
   Status store_status_ = STORE_SUCCESS;
diff --git a/chrome/browser/ash/settings/device_settings_test_helper.cc b/chrome/browser/ash/settings/device_settings_test_helper.cc
index 1155430..3b769a9 100644
--- a/chrome/browser/ash/settings/device_settings_test_helper.cc
+++ b/chrome/browser/ash/settings/device_settings_test_helper.cc
@@ -15,10 +15,10 @@
 #include "chrome/browser/ash/settings/device_settings_service.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/dbus/concierge/concierge_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/ownership/mock_owner_key_util.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ash/settings/session_manager_operation.cc b/chrome/browser/ash/settings/session_manager_operation.cc
index 9c6fbd70..c00706eb 100644
--- a/chrome/browser/ash/settings/session_manager_operation.cc
+++ b/chrome/browser/ash/settings/session_manager_operation.cc
@@ -20,8 +20,6 @@
 #include "crypto/rsa_private_key.h"
 #include "crypto/signature_creator.h"
 
-using RetrievePolicyResponseType =
-    chromeos::SessionManagerClient::RetrievePolicyResponseType;
 using ownership::OwnerKeyUtil;
 using ownership::PublicKey;
 
@@ -29,13 +27,16 @@
 
 namespace ash {
 
+using RetrievePolicyResponseType =
+    SessionManagerClient::RetrievePolicyResponseType;
+
 SessionManagerOperation::SessionManagerOperation(Callback callback)
     : callback_(std::move(callback)) {}
 
 SessionManagerOperation::~SessionManagerOperation() {}
 
 void SessionManagerOperation::Start(
-    chromeos::SessionManagerClient* session_manager_client,
+    SessionManagerClient* session_manager_client,
     scoped_refptr<OwnerKeyUtil> owner_key_util,
     scoped_refptr<PublicKey> public_key) {
   session_manager_client_ = session_manager_client;
diff --git a/chrome/browser/ash/settings/session_manager_operation.h b/chrome/browser/ash/settings/session_manager_operation.h
index 397caed..77094d1 100644
--- a/chrome/browser/ash/settings/session_manager_operation.h
+++ b/chrome/browser/ash/settings/session_manager_operation.h
@@ -45,7 +45,7 @@
   virtual ~SessionManagerOperation();
 
   // Starts the operation.
-  void Start(chromeos::SessionManagerClient* session_manager_client,
+  void Start(SessionManagerClient* session_manager_client,
              scoped_refptr<ownership::OwnerKeyUtil> owner_key_util,
              scoped_refptr<ownership::PublicKey> public_key);
 
@@ -90,7 +90,7 @@
   // operation should not perform further processing or trigger callbacks.
   void ReportResult(DeviceSettingsService::Status status);
 
-  chromeos::SessionManagerClient* session_manager_client() {
+  SessionManagerClient* session_manager_client() {
     return session_manager_client_;
   }
 
@@ -124,13 +124,13 @@
 
   // Validates device settings after retrieval from session_manager.
   void ValidateDeviceSettings(
-      chromeos::SessionManagerClient::RetrievePolicyResponseType response_type,
+      SessionManagerClient::RetrievePolicyResponseType response_type,
       const std::string& policy_blob);
 
   // Extracts status and device settings from the validator and reports them.
   void ReportValidatorStatus(policy::DeviceCloudPolicyValidator* validator);
 
-  chromeos::SessionManagerClient* session_manager_client_ = nullptr;
+  SessionManagerClient* session_manager_client_ = nullptr;
   scoped_refptr<ownership::OwnerKeyUtil> owner_key_util_;
 
   Callback callback_;
diff --git a/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn b/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn
index 88e45202..c7ede79 100644
--- a/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn
+++ b/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn
@@ -41,6 +41,7 @@
   deps = [
     ":window_management",
     "//chrome/browser/ash/system_extensions",
+    "//chrome/browser/ash/system_web_apps/test_support",
     "//chrome/browser/web_applications:web_applications_test_support",
     "//chrome/test:test_support",
   ]
diff --git a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc
index 68d15717..4186b196 100644
--- a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc
+++ b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
+#include "ash/shell.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/path_service.h"
@@ -16,12 +17,12 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/ash/system_extensions/system_extensions_install_manager.h"
 #include "chrome/browser/ash/system_extensions/system_extensions_provider.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -34,6 +35,7 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "ui/aura/window.h"
+#include "ui/display/test/display_manager_test_api.h"
 
 namespace ash {
 
@@ -182,7 +184,7 @@
     feature_list_.InitAndEnableFeature(features::kSystemExtensions);
 
     installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
+        TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
   }
   ~CrosWindowBrowserTest() override = default;
 
@@ -197,6 +199,7 @@
         "BlinkExtensionChromeOS,BlinkExtensionChromeOSWindowManagement");
   }
 
+ protected:
   void RunTest(base::StringPiece test_code) {
     // Initialize embedded test server.
     ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
@@ -240,8 +243,7 @@
                      kPostTestStart));
   }
 
- protected:
-  std::unique_ptr<web_app::TestSystemWebAppInstallation> installation_;
+  std::unique_ptr<TestSystemWebAppInstallation> installation_;
 
  private:
   base::test::ScopedFeatureList feature_list_;
@@ -270,6 +272,22 @@
 
 }  // namespace
 
+IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, CrosScreenWidthSampleTest) {
+  display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager())
+      .UpdateDisplay("0+0-1280x720,1280+600-1920x1080");
+
+  const char test_code[] = R"(
+async function cros_test() {
+  let screens = await chromeos.windowManagement.getScreens();
+
+  assert_equals(screens[0].width, 1280);
+  assert_equals(screens[1].width, 1920);
+}
+  )";
+
+  RunTest(test_code);
+}
+
 IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, CrosWindowMoveTo) {
   const char test_code[] = R"(
 async function cros_test() {
@@ -626,6 +644,26 @@
   RunTest(test_code);
 }
 
+IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, CacheGetWindowsReturnsProperty) {
+  const char test_code[] = R"(
+async function cros_test() {
+  let returnedWindows = await chromeos.windowManagement.getWindows();
+  assert_array_equals(chromeos.windowManagement.windows, returnedWindows);
+
+  let windows = chromeos.windowManagement.windows;
+  await chromeos.windowManagement.getWindows();
+
+  // TODO(b/232866765): Change to assert_array_equals() once we update the
+  // cache.
+  windows.forEach((window, index) => {
+    assert_not_equals(window, chromeos.windowManagement.windows[index]);
+  });
+}
+  )";
+
+  RunTest(test_code);
+}
+
 IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, CrosWindowSWACrashTest) {
   // Finish installation of Sample SWA.
   installation_->WaitForAppInstall();
diff --git a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
index 194d52a..b887306 100644
--- a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
+++ b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
@@ -273,4 +273,16 @@
   return widget;
 }
 
+void WindowManagementImpl::GetAllScreens(GetAllScreensCallback callback) {
+  std::vector<blink::mojom::CrosScreenInfoPtr> screens;
+
+  for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) {
+    auto screen = blink::mojom::CrosScreenInfo::New();
+    screen->width = display.bounds().width();
+    screens.push_back(std::move(screen));
+  }
+
+  std::move(callback).Run(std::move(screens));
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h
index 822beed..3d7c2dd 100644
--- a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h
+++ b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h
@@ -57,6 +57,8 @@
 
   void Close(const base::UnguessableToken& id, CloseCallback callback) override;
 
+  void GetAllScreens(GetAllScreensCallback callback) override;
+
  private:
   // Returns profile attached to the render process host id.
   Profile* GetProfile();
diff --git a/chrome/browser/ash/system_logs/reven_log_source.cc b/chrome/browser/ash/system_logs/reven_log_source.cc
index a573885..792eb937 100644
--- a/chrome/browser/ash/system_logs/reven_log_source.cc
+++ b/chrome/browser/ash/system_logs/reven_log_source.cc
@@ -11,9 +11,9 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/thread_pool.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-shared.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-shared.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 
 namespace system_logs {
 
diff --git a/chrome/browser/ash/system_logs/reven_log_source.h b/chrome/browser/ash/system_logs/reven_log_source.h
index 5bf980e..9b5053e4 100644
--- a/chrome/browser/ash/system_logs/reven_log_source.h
+++ b/chrome/browser/ash/system_logs/reven_log_source.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_ASH_SYSTEM_LOGS_REVEN_LOG_SOURCE_H_
 
 #include "base/memory/weak_ptr.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "components/feedback/system_logs/system_logs_source.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
diff --git a/chrome/browser/ash/system_logs/reven_log_source_unittest.cc b/chrome/browser/ash/system_logs/reven_log_source_unittest.cc
index 9482962e..f8c1223 100644
--- a/chrome/browser/ash/system_logs/reven_log_source_unittest.cc
+++ b/chrome/browser/ash/system_logs/reven_log_source_unittest.cc
@@ -8,10 +8,10 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-shared.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-shared.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/system_token_cert_db_initializer.cc b/chrome/browser/ash/system_token_cert_db_initializer.cc
index ba737eb..407c12f 100644
--- a/chrome/browser/ash/system_token_cert_db_initializer.cc
+++ b/chrome/browser/ash/system_token_cert_db_initializer.cc
@@ -25,10 +25,10 @@
 #include "chrome/browser/ash/crosapi/crosapi_ash.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
 #include "chrome/browser/ash/login/startup_utils.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/system_token_cert_db_storage.h"
 #include "content/public/browser/browser_task_traits.h"
diff --git a/chrome/browser/ash/system_token_cert_db_initializer_unittest.cc b/chrome/browser/ash/system_token_cert_db_initializer_unittest.cc
index bb08dfd5..123fba1 100644
--- a/chrome/browser/ash/system_token_cert_db_initializer_unittest.cc
+++ b/chrome/browser/ash/system_token_cert_db_initializer_unittest.cc
@@ -12,10 +12,10 @@
 #include "base/memory/weak_ptr.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/network/system_token_cert_db_storage_test_util.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/network/network_cert_loader.h"
-#include "chromeos/network/system_token_cert_db_storage_test_util.h"
 #include "content/public/test/browser_task_environment.h"
 #include "crypto/nss_util.h"
 #include "crypto/scoped_test_system_nss_key_slot.h"
diff --git a/chrome/browser/ash/system_web_apps/BUILD.gn b/chrome/browser/ash/system_web_apps/BUILD.gn
index d44cd4b..baac04a7 100644
--- a/chrome/browser/ash/system_web_apps/BUILD.gn
+++ b/chrome/browser/ash/system_web_apps/BUILD.gn
@@ -68,6 +68,7 @@
     "//base",
     "//base/test:test_support",
     "//build:chromeos_buildflags",
+    "//chrome/browser/ash/system_web_apps/test_support",
     "//chrome/browser/ash/system_web_apps/types",
     "//chrome/browser/web_applications",
     "//chrome/browser/web_applications:web_applications_test_support",
@@ -94,6 +95,7 @@
     ":system_web_apps",
     "//base",
     "//chrome/app:command_ids",
+    "//chrome/browser/ash/system_web_apps/test_support",
     "//chrome/browser/ash/system_web_apps/test_support:test_support_ui",
     "//chrome/browser/ash/system_web_apps/types",
     "//chrome/browser/web_applications:web_applications_test_support",
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
index 1a8fcd2c..db97876a 100644
--- a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
+++ b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/apps/app_service/browser_app_launcher.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/ash/system_web_apps/types/system_web_app_type.h"
 #include "chrome/browser/file_system_access/file_system_access_permission_request_manager.h"
 #include "chrome/browser/profiles/profile.h"
@@ -34,7 +35,6 @@
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
 #include "chrome/browser/web_applications/proto/web_app.pb.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
@@ -252,7 +252,7 @@
     : public TestProfileTypeMixin<SystemWebAppBrowserTestBase> {
  public:
   using IncludeLaunchDirectory =
-      web_app::TestSystemWebAppInstallation::IncludeLaunchDirectory;
+      TestSystemWebAppInstallation::IncludeLaunchDirectory;
 
   explicit SystemWebAppManagerFileHandlingBrowserTestBase(
       IncludeLaunchDirectory include_launch_directory)
@@ -262,7 +262,7 @@
         {blink::features::kFileHandlingAPI}, {});
 
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppThatReceivesLaunchFiles(
+        TestSystemWebAppInstallation::SetUpAppThatReceivesLaunchFiles(
             include_launch_directory);
   }
 
@@ -828,7 +828,7 @@
   SystemWebAppManagerFileHandlingOriginTrialsBrowserTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppWithEnabledOriginTrials(
+        TestSystemWebAppInstallation::SetUpAppWithEnabledOriginTrials(
             OriginTrialsMap({{GetOrigin(GURL("chrome://test-system-app/")),
                               {"FileHandling"}}}));
   }
@@ -894,7 +894,7 @@
   SystemWebAppManagerNotShownInLauncherTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppNotShownInLauncher();
+        TestSystemWebAppInstallation::SetUpAppNotShownInLauncher();
   }
 };
 
@@ -932,7 +932,7 @@
   SystemWebAppManagerNotShownInSearchTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppNotShownInSearch();
+        TestSystemWebAppInstallation::SetUpAppNotShownInSearch();
   }
 };
 
@@ -959,8 +959,8 @@
  public:
   SystemWebAppManagerHandlesFileOpenIntentsTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
-    maybe_installation_ = web_app::TestSystemWebAppInstallation::
-        SetUpAppThatHandlesFileOpenIntents();
+    maybe_installation_ =
+        TestSystemWebAppInstallation::SetUpAppThatHandlesFileOpenIntents();
   }
 };
 
@@ -987,8 +987,8 @@
  public:
   SystemWebAppManagerAdditionalSearchTermsTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
-    maybe_installation_ = web_app::TestSystemWebAppInstallation::
-        SetUpAppWithAdditionalSearchTerms();
+    maybe_installation_ =
+        TestSystemWebAppInstallation::SetUpAppWithAdditionalSearchTerms();
   }
 };
 
@@ -1017,7 +1017,7 @@
   SystemWebAppManagerHasTabStripTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppWithTabStrip(true);
+        TestSystemWebAppInstallation::SetUpAppWithTabStrip(true);
   }
 };
 
@@ -1037,7 +1037,7 @@
   SystemWebAppManagerHasNoTabStripTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppWithTabStrip(false);
+        TestSystemWebAppInstallation::SetUpAppWithTabStrip(false);
   }
 };
 
@@ -1059,8 +1059,7 @@
   SystemWebAppManagerDefaultBoundsTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppWithDefaultBounds(
-            kDefaultBounds);
+        TestSystemWebAppInstallation::SetUpAppWithDefaultBounds(kDefaultBounds);
   }
 
  protected:
@@ -1086,13 +1085,13 @@
     if (content::IsPreTest()) {
       // Use an app with FileHandling enabled since it will perform extra setup
       // steps.
-      maybe_installation_ = web_app::TestSystemWebAppInstallation::
-          SetUpAppWithEnabledOriginTrials(OriginTrialsMap(
-              {{url::Origin::Create(GURL("chrome://test-system-app/")),
-                {"FileHandling"}}}));
-    } else {
       maybe_installation_ =
-          web_app::TestSystemWebAppInstallation::SetUpWithoutApps();
+          TestSystemWebAppInstallation::SetUpAppWithEnabledOriginTrials(
+              OriginTrialsMap(
+                  {{url::Origin::Create(GURL("chrome://test-system-app/")),
+                    {"FileHandling"}}}));
+    } else {
+      maybe_installation_ = TestSystemWebAppInstallation::SetUpWithoutApps();
     }
   }
   ~SystemWebAppManagerUninstallBrowserTest() override = default;
@@ -1268,7 +1267,7 @@
   SystemWebAppManagerChromeUntrustedTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpChromeUntrustedApp();
+        TestSystemWebAppInstallation::SetUpChromeUntrustedApp();
   }
 };
 
@@ -1306,7 +1305,7 @@
   SystemWebAppManagerOriginTrialsBrowserTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppWithEnabledOriginTrials(
+        TestSystemWebAppInstallation::SetUpAppWithEnabledOriginTrials(
             OriginTrialsMap({{GetOrigin(main_url_), main_url_trials_},
                              {GetOrigin(trial_url_), trial_url_trials_}}));
   }
@@ -1569,8 +1568,7 @@
  public:
   SystemWebAppManagerShortcutTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
-    maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppWithShortcuts();
+    maybe_installation_ = TestSystemWebAppInstallation::SetUpAppWithShortcuts();
   }
 };
 
@@ -1634,7 +1632,7 @@
   SystemWebAppManagerBackgroundTaskTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppWithBackgroundTask();
+        TestSystemWebAppInstallation::SetUpAppWithBackgroundTask();
   }
 
   void WaitForSystemAppsBackgroundTasksStart() {
@@ -1692,7 +1690,7 @@
   SystemWebAppManagerContextMenuBrowserTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppsForContestMenuTest();
+        TestSystemWebAppInstallation::SetUpAppsForContestMenuTest();
   }
   ~SystemWebAppManagerContextMenuBrowserTest() override = default;
 
@@ -1714,7 +1712,7 @@
     return menu;
   }
 
-  // See web_app::TestSystemWebAppInstallation::SetUpAppsForContestMenuTest.
+  // See TestSystemWebAppInstallation::SetUpAppsForContestMenuTest.
   const SystemWebAppType kAppTypeSingleWindow = SystemWebAppType::SETTINGS;
   const SystemWebAppType kAppTypeMultiWindow = SystemWebAppType::FILE_MANAGER;
   const SystemWebAppType kAppTypeSingleWindowTabStrip = SystemWebAppType::MEDIA;
@@ -1831,7 +1829,7 @@
   SystemWebAppAccessibilityTest()
       : SystemWebAppManagerBrowserTest(/*install_mock*/ false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
+        TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
   }
   ~SystemWebAppAccessibilityTest() override = default;
 
@@ -1877,7 +1875,7 @@
   SystemWebAppAbortsLaunchTest()
       : SystemWebAppManagerBrowserTest(/*install_mock*/ false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpAppThatAbortsLaunch();
+        TestSystemWebAppInstallation::SetUpAppThatAbortsLaunch();
   }
   ~SystemWebAppAbortsLaunchTest() override = default;
 };
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager_unittest.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager_unittest.cc
index 84446f79..dbcd0f3 100644
--- a/chrome/browser/ash/system_web_apps/system_web_app_manager_unittest.cc
+++ b/chrome/browser/ash/system_web_apps/system_web_app_manager_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/time/time.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/ash/system_web_apps/system_web_app_background_task.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/ash/system_web_apps/types/system_web_app_delegate.h"
 #include "chrome/browser/ash/system_web_apps/types/system_web_app_delegate_map.h"
 #include "chrome/browser/ash/system_web_apps/types/system_web_app_type.h"
@@ -26,7 +27,6 @@
 #include "chrome/browser/web_applications/externally_installed_web_app_prefs.h"
 #include "chrome/browser/web_applications/externally_managed_app_manager_impl.h"
 #include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_manager.h"
 #include "chrome/browser/web_applications/test/fake_data_retriever.h"
 #include "chrome/browser/web_applications/test/fake_externally_managed_app_manager.h"
@@ -353,11 +353,11 @@
 
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(SystemWebAppType::SETTINGS,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::SETTINGS, kSettingsAppInternalName,
                           AppUrl1(), GetApp1WebAppInfoFactory()));
   system_apps.emplace(SystemWebAppType::CAMERA,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::CAMERA, kCameraAppInternalName,
                           AppUrl2(), GetApp2WebAppInfoFactory()));
 
@@ -382,7 +382,7 @@
 
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(SystemWebAppType::SETTINGS,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::SETTINGS, kSettingsAppInternalName,
                           AppUrl1(), GetApp1WebAppInfoFactory()));
 
@@ -425,7 +425,7 @@
     SystemWebAppDelegateMap system_apps;
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
             GetApp1WebAppInfoFactory()));
     system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -442,11 +442,11 @@
 
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
             GetApp1WebAppInfoFactory()));
     system_apps.emplace(SystemWebAppType::CAMERA,
-                        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                        std::make_unique<UnittestingSystemAppDelegate>(
                             SystemWebAppType::CAMERA, kCameraAppInternalName,
                             AppUrl2(), GetApp2WebAppInfoFactory()));
     system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -469,7 +469,7 @@
     SystemWebAppDelegateMap system_apps;
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
             GetApp1WebAppInfoFactory()));
     system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -485,14 +485,14 @@
     SystemWebAppDelegateMap system_apps;
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
             GetApp1WebAppInfoFactory()));
     // Create another app. The version hasn't changed, but we should immediately
     // install anyway, as if a user flipped a chrome://flag. The first app won't
     // force reinstall.
     system_apps.emplace(SystemWebAppType::CAMERA,
-                        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                        std::make_unique<UnittestingSystemAppDelegate>(
                             SystemWebAppType::CAMERA, kCameraAppInternalName,
                             AppUrl2(), GetApp2WebAppInfoFactory()));
 
@@ -525,12 +525,12 @@
     SystemWebAppDelegateMap system_apps;
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, kAppUrl3,
             base::BindRepeating(&GetWebAppInstallInfo, kAppUrl3)));
 
     system_apps.emplace(SystemWebAppType::CAMERA,
-                        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                        std::make_unique<UnittestingSystemAppDelegate>(
                             SystemWebAppType::CAMERA, kCameraAppInternalName,
                             AppUrl2(), GetApp2WebAppInfoFactory()));
 
@@ -557,7 +557,7 @@
 
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(SystemWebAppType::SETTINGS,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::SETTINGS, kSettingsAppInternalName,
                           AppUrl1(), GetApp1WebAppInfoFactory()));
   system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -605,7 +605,7 @@
     SystemWebAppDelegateMap system_apps;
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
             GetApp1WebAppInfoFactory()));
     system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -648,11 +648,11 @@
     SystemWebAppDelegateMap system_apps;
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
             GetApp1WebAppInfoFactory()));
     system_apps.emplace(SystemWebAppType::CAMERA,
-                        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                        std::make_unique<UnittestingSystemAppDelegate>(
                             SystemWebAppType::CAMERA, kCameraAppInternalName,
                             AppUrl2(), GetApp2WebAppInfoFactory()));
     system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -677,7 +677,7 @@
     SystemWebAppDelegateMap system_apps;
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
             GetApp1WebAppInfoFactory()));
     system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -734,11 +734,11 @@
   InitEmptyRegistrar();
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(SystemWebAppType::SETTINGS,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::SETTINGS, kSettingsAppInternalName,
                           AppUrl1(), GetApp1WebAppInfoFactory()));
   system_apps.emplace(SystemWebAppType::CAMERA,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::CAMERA, kCameraAppInternalName,
                           AppUrl2(), GetApp2WebAppInfoFactory()));
   system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -771,11 +771,11 @@
   InitEmptyRegistrar();
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(SystemWebAppType::SETTINGS,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::SETTINGS, kSettingsAppInternalName,
                           AppUrl1(), GetApp1WebAppInfoFactory()));
   system_apps.emplace(SystemWebAppType::CAMERA,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::CAMERA, kCameraAppInternalName,
                           AppUrl2(), GetApp2WebAppInfoFactory()));
   system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -833,7 +833,7 @@
 
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(SystemWebAppType::SETTINGS,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::SETTINGS, kSettingsAppInternalName,
                           AppUrl1(), GetApp1WebAppInfoFactory()));
   system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -905,7 +905,7 @@
 
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(SystemWebAppType::SETTINGS,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::SETTINGS, kSettingsAppInternalName,
                           AppUrl1(), GetApp1WebAppInfoFactory()));
 
@@ -976,7 +976,7 @@
   // Set up and install a baseline
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(SystemWebAppType::SETTINGS,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::SETTINGS, kSettingsAppInternalName,
                           AppUrl1(), GetApp1WebAppInfoFactory()));
 
@@ -1048,7 +1048,7 @@
   // Register a test system app.
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(SystemWebAppType::SETTINGS,
-                      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+                      std::make_unique<UnittestingSystemAppDelegate>(
                           SystemWebAppType::SETTINGS, kSettingsAppInternalName,
                           AppUrl1(), GetApp1WebAppInfoFactory()));
 
@@ -1087,7 +1087,7 @@
     SystemWebAppDelegateMap system_apps;
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
             GetApp1WebAppInfoFactory()));
     system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
@@ -1107,7 +1107,7 @@
     SystemWebAppDelegateMap system_apps;
     system_apps.emplace(
         SystemWebAppType::SETTINGS,
-        std::make_unique<web_app::UnittestingSystemAppDelegate>(
+        std::make_unique<UnittestingSystemAppDelegate>(
             SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
             GetApp1WebAppInfoFactory()));
     unsynced_system_web_app_manager->SetSystemAppsForTesting(
@@ -1118,7 +1118,7 @@
       web_app::GenerateAppId(/*manifest_id=*/absl::nullopt, AppUrl1())));
 }
 
-class TimerSystemAppDelegate : public web_app::UnittestingSystemAppDelegate {
+class TimerSystemAppDelegate : public UnittestingSystemAppDelegate {
  public:
   TimerSystemAppDelegate(SystemWebAppType type,
                          const std::string& name,
@@ -1126,10 +1126,7 @@
                          web_app::WebAppInstallInfoFactory info_factory,
                          absl::optional<base::TimeDelta> period,
                          bool open_immediately)
-      : web_app::UnittestingSystemAppDelegate(type,
-                                              name,
-                                              url,
-                                              std::move(info_factory)),
+      : UnittestingSystemAppDelegate(type, name, url, std::move(info_factory)),
         period_(period),
         open_immediately_(open_immediately) {}
   absl::optional<SystemWebAppBackgroundTaskInfo> GetTimerInfo() const override;
@@ -1498,7 +1495,7 @@
   SystemWebAppDelegateMap system_apps;
   system_apps.emplace(
       SystemWebAppType::SETTINGS,
-      std::make_unique<web_app::UnittestingSystemAppDelegate>(
+      std::make_unique<UnittestingSystemAppDelegate>(
           SystemWebAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
           base::BindRepeating(&GetWebAppInstallInfo, AppUrl1())));
   system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
diff --git a/chrome/browser/ash/system_web_apps/test_support/BUILD.gn b/chrome/browser/ash/system_web_apps/test_support/BUILD.gn
index 971de445..6e75e7e 100644
--- a/chrome/browser/ash/system_web_apps/test_support/BUILD.gn
+++ b/chrome/browser/ash/system_web_apps/test_support/BUILD.gn
@@ -8,6 +8,47 @@
 # move all the GN dependencies under `if (is_chromeos_ash)` section.
 # assert(is_chromeos_ash)
 
+# This test_support library doesn't use extensions. It must not depend on
+# //chrome/test:test_support_ui as it is depended upon by those targets.
+source_set("test_support") {
+  testonly = true
+
+  sources = [
+    "test_system_web_app_installation.cc",
+    "test_system_web_app_installation.h",
+  ]
+
+  deps = [
+    "//base/test:test_support",
+    "//chrome/app:command_ids",
+    "//chrome/app/theme:chrome_unscaled_resources_grit",
+    "//chrome/browser",
+    "//chrome/browser/ash/system_web_apps",
+    "//chrome/browser/ash/system_web_apps/types",
+    "//chrome/browser/profiles:profile",
+    "//chrome/browser/ui",
+    "//chrome/browser/web_applications",
+    "//chrome/browser/web_applications:web_applications_test_support",
+    "//components/crx_file",
+    "//components/keyed_service/content",
+    "//components/services/app_service/public/cpp:app_types",
+    "//components/services/app_service/public/cpp:app_update",
+    "//components/services/app_service/public/cpp:app_url_handling",
+    "//components/services/app_service/public/cpp:protocol_handling",
+    "//components/services/app_service/public/cpp:types",
+    "//components/sync:test_support_model",
+    "//components/sync_preferences:test_support",
+    "//components/webapps/browser",
+    "//content/test:test_support",
+    "//testing/gtest",
+    "//ui/webui",
+  ]
+
+  if (is_chromeos_ash) {
+    deps += [ "//ash/constants" ]
+  }
+}
+
 # Browsertest base classes that depend on //chrome/test:test_support_ui. Must
 # be separate from :test_support because that is depended upon by
 # //chrome/test:test_support_ui.
@@ -24,6 +65,7 @@
   deps = [
     "//chrome/browser",
     "//chrome/browser/ash/system_web_apps",
+    "//chrome/browser/ash/system_web_apps/test_support",
     "//chrome/browser/profiles:profile",
     "//chrome/browser/ui",
     "//chrome/browser/web_applications",
diff --git a/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.cc b/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.cc
index 87563c7..078ee220 100644
--- a/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.cc
+++ b/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.cc
@@ -171,7 +171,7 @@
     : TestProfileTypeMixin<SystemWebAppBrowserTestBase>(install_mock) {
   if (install_mock) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
+        TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
   }
 }
 
diff --git a/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.h b/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.h
index 9efa734..a0e6464 100644
--- a/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.h
+++ b/chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/test/profile_test_helper.h"
 #include "chrome/browser/web_applications/test/web_app_test_utils.h"
@@ -95,7 +95,7 @@
   size_t GetSystemWebAppBrowserCount(SystemWebAppType type);
 
  protected:
-  std::unique_ptr<web_app::TestSystemWebAppInstallation> maybe_installation_;
+  std::unique_ptr<TestSystemWebAppInstallation> maybe_installation_;
 
  private:
   std::unique_ptr<KeyedService> CreateWebAppProvider(Profile* profile);
diff --git a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc b/chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.cc
similarity index 85%
rename from chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc
rename to chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.cc
index d9d00eb..4d44f1e 100644
--- a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc
+++ b/chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.cc
@@ -13,9 +13,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/ash/system_web_apps/types/system_web_app_type.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_url_data_source.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
@@ -25,7 +25,7 @@
 #include "content/public/common/url_constants.h"
 #include "ui/webui/webui_allowlist.h"
 
-namespace web_app {
+namespace ash {
 
 namespace {
 
@@ -88,11 +88,11 @@
 }  // namespace
 
 UnittestingSystemAppDelegate::UnittestingSystemAppDelegate(
-    ash::SystemWebAppType type,
+    SystemWebAppType type,
     const std::string& name,
     const GURL& url,
-    WebAppInstallInfoFactory info_factory)
-    : ash::SystemWebAppDelegate(type, name, url, nullptr),
+    web_app::WebAppInstallInfoFactory info_factory)
+    : SystemWebAppDelegate(type, name, url, nullptr),
       info_factory_(std::move(info_factory)) {}
 
 UnittestingSystemAppDelegate::~UnittestingSystemAppDelegate() = default;
@@ -156,7 +156,7 @@
 bool UnittestingSystemAppDelegate::ShouldAllowScriptsToCloseWindows() const {
   return allow_scripts_to_close_windows_;
 }
-absl::optional<ash::SystemWebAppBackgroundTaskInfo>
+absl::optional<SystemWebAppBackgroundTaskInfo>
 UnittestingSystemAppDelegate::GetTimerInfo() const {
   return timer_info_;
 }
@@ -169,7 +169,7 @@
 }
 Browser* UnittestingSystemAppDelegate::LaunchAndNavigateSystemWebApp(
     Profile* profile,
-    WebAppProvider* provider,
+    web_app::WebAppProvider* provider,
     const GURL& url,
     const apps::AppLaunchParams& params) const {
   if (launch_and_navigate_system_web_apps_) {
@@ -197,7 +197,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
 void UnittestingSystemAppDelegate::SetAppIdsToUninstallAndReplace(
-    const std::vector<AppId>& ids) {
+    const std::vector<web_app::AppId>& ids) {
   uninstall_and_replace_ = ids;
 }
 void UnittestingSystemAppDelegate::SetMinimumWindowSize(const gfx::Size& size) {
@@ -214,7 +214,7 @@
   include_launch_directory_ = value;
 }
 void UnittestingSystemAppDelegate::SetEnabledOriginTrials(
-    const ash::OriginTrialsMap& map) {
+    const OriginTrialsMap& map) {
   origin_trials_map_ = map;
 }
 void UnittestingSystemAppDelegate::SetAdditionalSearchTerms(
@@ -251,7 +251,7 @@
   allow_scripts_to_close_windows_ = value;
 }
 void UnittestingSystemAppDelegate::SetTimerInfo(
-    const ash::SystemWebAppBackgroundTaskInfo& timer_info) {
+    const SystemWebAppBackgroundTaskInfo& timer_info) {
   timer_info_ = timer_info;
 }
 void UnittestingSystemAppDelegate::SetDefaultBounds(
@@ -290,33 +290,36 @@
   UnittestingSystemAppDelegate* delegate_ptr = delegate.get();
   system_app_delegates_.emplace(type_.value(), std::move(delegate));
 
-  fake_web_app_provider_creator_ = std::make_unique<FakeWebAppProviderCreator>(
-      base::BindRepeating(&TestSystemWebAppInstallation::CreateWebAppProvider,
-                          // base::Unretained is safe here. This callback is
-                          // called at TestingProfile::Init, which is at test
-                          // startup. TestSystemWebAppInstallation is intended
-                          // to have the same lifecycle as the test, it won't be
-                          // destroyed before the test finishes.
-                          base::Unretained(this)));
+  fake_web_app_provider_creator_ =
+      std::make_unique<web_app::FakeWebAppProviderCreator>(base::BindRepeating(
+          &TestSystemWebAppInstallation::CreateWebAppProvider,
+          // base::Unretained is safe here. This callback is
+          // called at TestingProfile::Init, which is at test
+          // startup. TestSystemWebAppInstallation is intended
+          // to have the same lifecycle as the test, it won't be
+          // destroyed before the test finishes.
+          base::Unretained(this)));
 
   test_system_web_app_manager_creator_ =
-      std::make_unique<TestSystemWebAppManagerCreator>(base::BindRepeating(
-          &TestSystemWebAppInstallation::CreateSystemWebAppManager,
-          base::Unretained(this), delegate_ptr));
+      std::make_unique<web_app::TestSystemWebAppManagerCreator>(
+          base::BindRepeating(
+              &TestSystemWebAppInstallation::CreateSystemWebAppManager,
+              base::Unretained(this), delegate_ptr));
 }
 
 TestSystemWebAppInstallation::TestSystemWebAppInstallation() {
-  fake_web_app_provider_creator_ = std::make_unique<FakeWebAppProviderCreator>(
-      base::BindRepeating(&TestSystemWebAppInstallation::CreateWebAppProvider,
-                          // base::Unretained is safe here. This callback is
-                          // called at TestingProfile::Init, which is at test
-                          // startup. TestSystemWebAppInstallation is intended
-                          // to have the same lifecycle as the test, it won't be
-                          // destroyed before the test finishes.
-                          base::Unretained(this)));
+  fake_web_app_provider_creator_ =
+      std::make_unique<web_app::FakeWebAppProviderCreator>(base::BindRepeating(
+          &TestSystemWebAppInstallation::CreateWebAppProvider,
+          // base::Unretained is safe here. This callback is
+          // called at TestingProfile::Init, which is at test
+          // startup. TestSystemWebAppInstallation is intended
+          // to have the same lifecycle as the test, it won't be
+          // destroyed before the test finishes.
+          base::Unretained(this)));
 
   test_system_web_app_manager_creator_ =
-      std::make_unique<TestSystemWebAppManagerCreator>(
+      std::make_unique<web_app::TestSystemWebAppManagerCreator>(
           base::BindRepeating(&TestSystemWebAppInstallation::
                                   CreateSystemWebAppManagerWithNoSystemWebApps,
                               base::Unretained(this)));
@@ -335,7 +338,7 @@
   info->title = u"Test System App";
   info->theme_color = 0xFF00FF00;
   info->display_mode = blink::mojom::DisplayMode::kStandalone;
-  info->user_display_mode = UserDisplayMode::kStandalone;
+  info->user_display_mode = web_app::UserDisplayMode::kStandalone;
   return info;
 }
 
@@ -358,7 +361,7 @@
 TestSystemWebAppInstallation::SetUpTabbedMultiWindowApp() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::TERMINAL, "Terminal",
+          SystemWebAppType::TERMINAL, "Terminal",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldReuseExistingWindow(false);
@@ -373,7 +376,7 @@
 TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::SETTINGS, "OSSettings",
+          SystemWebAppType::SETTINGS, "OSSettings",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetUrlInSystemAppScope(GURL("http://example.com/in-scope"));
@@ -388,7 +391,7 @@
     IncludeLaunchDirectory include_launch_directory) {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Media",
+          SystemWebAppType::MEDIA, "Media",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
 
@@ -408,10 +411,10 @@
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppWithEnabledOriginTrials(
-    const ash::OriginTrialsMap& origin_to_trials) {
+    const OriginTrialsMap& origin_to_trials) {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Media",
+          SystemWebAppType::MEDIA, "Media",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
 
@@ -425,7 +428,7 @@
 TestSystemWebAppInstallation::SetUpAppNotShownInLauncher() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
 
@@ -440,7 +443,7 @@
 TestSystemWebAppInstallation::SetUpAppNotShownInSearch() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldShowInSearch(false);
@@ -454,7 +457,7 @@
 TestSystemWebAppInstallation::SetUpAppThatHandlesFileOpenIntents() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldHandleFileOpenIntents(true);
@@ -468,7 +471,7 @@
 TestSystemWebAppInstallation::SetUpAppWithAdditionalSearchTerms() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetAdditionalSearchTerms({IDS_SETTINGS_SECURITY});
@@ -482,7 +485,7 @@
 TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::HELP, "Test",
+          SystemWebAppType::HELP, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldCaptureNavigations(true);
@@ -492,9 +495,9 @@
   // Add a helper system app to test capturing links from it.
   const GURL kInitiatingAppUrl = GURL("chrome://initiating-app/pwa.html");
   installation->system_app_delegates_.insert_or_assign(
-      ash::SystemWebAppType::SETTINGS,
+      SystemWebAppType::SETTINGS,
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::SETTINGS, "Initiating App", kInitiatingAppUrl,
+          SystemWebAppType::SETTINGS, "Initiating App", kInitiatingAppUrl,
           base::BindLambdaForTesting([]() {
             auto info = std::make_unique<WebAppInstallInfo>();
             // the pwa.html is arguably wrong, but the manifest
@@ -507,7 +510,7 @@
             info->title = u"Test System App";
             info->theme_color = 0xFF00FF00;
             info->display_mode = blink::mojom::DisplayMode::kStandalone;
-            info->user_display_mode = UserDisplayMode::kStandalone;
+            info->user_display_mode = web_app::UserDisplayMode::kStandalone;
             return info;
           })));
   auto factory = std::make_unique<TestSystemWebAppWebUIControllerFactory>(
@@ -522,7 +525,7 @@
 TestSystemWebAppInstallation::SetUpChromeUntrustedApp() {
   return base::WrapUnique(new TestSystemWebAppInstallation(
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::SETTINGS, "Test",
+          SystemWebAppType::SETTINGS, "Test",
           GURL("chrome-untrusted://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestAppUntrusted))));
 }
@@ -532,7 +535,7 @@
 TestSystemWebAppInstallation::SetUpNonResizeableAndNonMaximizableApp() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldAllowResize(false);
@@ -547,11 +550,11 @@
 TestSystemWebAppInstallation::SetUpAppWithBackgroundTask() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
 
-  ash::SystemWebAppBackgroundTaskInfo background_task(
+  SystemWebAppBackgroundTaskInfo background_task(
       base::Days(1), GURL("chrome://test-system-app/page2.html"), true);
   delegate->SetTimerInfo(background_task);
 
@@ -565,7 +568,7 @@
     bool value) {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   /* The default value of allow_scripts_to_close_windows is false. */
@@ -581,7 +584,7 @@
 TestSystemWebAppInstallation::SetUpAppWithTabStrip(bool has_tab_strip) {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldHaveTabStrip(has_tab_strip);
@@ -596,7 +599,7 @@
     const gfx::Rect& default_bounds) {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetDefaultBounds(
@@ -611,7 +614,7 @@
 TestSystemWebAppInstallation::SetUpAppWithNewWindowMenuItem() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::FILE_MANAGER, "Test",
+          SystemWebAppType::FILE_MANAGER, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldShowNewWindowMenuOption(true);
@@ -626,7 +629,7 @@
 TestSystemWebAppInstallation::SetUpAppWithShortcuts() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::SHORTCUT_CUSTOMIZATION, "Shortcuts",
+          SystemWebAppType::SHORTCUT_CUSTOMIZATION, "Shortcuts",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindLambdaForTesting([]() {
             std::unique_ptr<WebAppInstallInfo> info =
@@ -656,11 +659,11 @@
 TestSystemWebAppInstallation::SetUpAppThatAbortsLaunch() {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::OS_FEEDBACK, "Test",
+          SystemWebAppType::OS_FEEDBACK, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetLaunchAndNavigateSystemWebApp(base::BindRepeating(
-      [](Profile*, WebAppProvider*, const GURL&,
+      [](Profile*, web_app::WebAppProvider*, const GURL&,
          const apps::AppLaunchParams&) -> Browser* { return nullptr; }));
 
   return base::WrapUnique(
@@ -677,7 +680,7 @@
 
 std::unique_ptr<UnittestingSystemAppDelegate>
 CreateSystemAppDelegateWithWindowConfig(
-    const ash::SystemWebAppType type,
+    const SystemWebAppType type,
     const GURL& app_url,
     SystemWebAppWindowConfig window_config) {
   auto* delegate = new UnittestingSystemAppDelegate(
@@ -688,7 +691,7 @@
         info->title = u"Test System App";
         info->theme_color = 0xFF00FF00;
         info->display_mode = blink::mojom::DisplayMode::kStandalone;
-        info->user_display_mode = UserDisplayMode::kStandalone;
+        info->user_display_mode = web_app::UserDisplayMode::kStandalone;
         return info;
       }));
 
@@ -721,22 +724,20 @@
 TestSystemWebAppInstallation::SetUpAppsForContestMenuTest() {
   std::vector<std::unique_ptr<UnittestingSystemAppDelegate>> delegates;
   delegates.push_back(CreateSystemAppDelegateWithWindowConfig(
-      ash::SystemWebAppType::SETTINGS, GURL("chrome://single-window/pwa.html"),
+      SystemWebAppType::SETTINGS, GURL("chrome://single-window/pwa.html"),
       SystemWebAppWindowConfig::SINGLE_WINDOW));
 
   delegates.push_back(CreateSystemAppDelegateWithWindowConfig(
-      ash::SystemWebAppType::FILE_MANAGER,
-      GURL("chrome://multi-window/pwa.html"),
+      SystemWebAppType::FILE_MANAGER, GURL("chrome://multi-window/pwa.html"),
       SystemWebAppWindowConfig::MULTI_WINDOW));
 
   delegates.push_back(CreateSystemAppDelegateWithWindowConfig(
-      ash::SystemWebAppType::MEDIA,
+      SystemWebAppType::MEDIA,
       GURL("chrome://single-window-tab-strip/pwa.html"),
       SystemWebAppWindowConfig::SINGLE_WINDOW_TAB_STRIP));
 
   delegates.push_back(CreateSystemAppDelegateWithWindowConfig(
-      ash::SystemWebAppType::HELP,
-      GURL("chrome://multi-window-tab-strip/pwa.html"),
+      SystemWebAppType::HELP, GURL("chrome://multi-window-tab-strip/pwa.html"),
       SystemWebAppWindowConfig::MULTI_WINDOW_TAB_STRIP));
   auto* installation =
       new TestSystemWebAppInstallation(std::move(delegates[0]));
@@ -764,7 +765,7 @@
     absl::optional<SkColor> dark_mode_background_color) {
   std::unique_ptr<UnittestingSystemAppDelegate> delegate =
       std::make_unique<UnittestingSystemAppDelegate>(
-          ash::SystemWebAppType::MEDIA, "Test",
+          SystemWebAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindLambdaForTesting([=]() {
             auto info = GenerateWebAppInstallInfoForTestApp();
@@ -782,7 +783,7 @@
 TestSystemWebAppInstallation::CreateWebAppProvider(Profile* profile) {
   profile_ = profile;
 
-  auto provider = std::make_unique<FakeWebAppProvider>(profile);
+  auto provider = std::make_unique<web_app::FakeWebAppProvider>(profile);
   provider->Start();
 
   return provider;
@@ -796,16 +797,17 @@
   DCHECK_EQ(profile_, profile);
 
   if (GetWebUIType(delegate->GetInstallUrl()) == WebUIType::kChromeUntrusted) {
-    AddTestURLDataSource(GetChromeUntrustedDataSourceNameFromInstallUrl(
-                             delegate->GetInstallUrl()),
-                         profile);
+    web_app::AddTestURLDataSource(
+        GetChromeUntrustedDataSourceNameFromInstallUrl(
+            delegate->GetInstallUrl()),
+        profile);
   }
 
-  WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(profile);
+  web_app::WebAppProvider* provider =
+      web_app::WebAppProvider::GetForLocalAppsUnchecked(profile);
   DCHECK(provider);
 
-  auto system_web_app_manager =
-      std::make_unique<ash::SystemWebAppManager>(profile);
+  auto system_web_app_manager = std::make_unique<SystemWebAppManager>(profile);
 
   system_web_app_manager->SetSystemAppsForTesting(
       std::move(system_app_delegates_));
@@ -828,11 +830,11 @@
   // `CreateWebAppProvider` gets called first and assigns `profile_`.
   DCHECK_EQ(profile_, profile);
 
-  WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(profile);
+  web_app::WebAppProvider* provider =
+      web_app::WebAppProvider::GetForLocalAppsUnchecked(profile);
   DCHECK(provider);
 
-  auto system_web_app_manager =
-      std::make_unique<ash::SystemWebAppManager>(profile);
+  auto system_web_app_manager = std::make_unique<SystemWebAppManager>(profile);
 
   system_web_app_manager->SetSystemAppsForTesting({});
   system_web_app_manager->SetUpdatePolicyForTesting(update_policy_);
@@ -845,7 +847,7 @@
 
 void TestSystemWebAppInstallation::WaitForAppInstall() {
   base::RunLoop run_loop;
-  ash::SystemWebAppManager::GetForTest(profile_)->on_apps_synchronized().Post(
+  SystemWebAppManager::GetForTest(profile_)->on_apps_synchronized().Post(
       FROM_HERE, base::BindLambdaForTesting([&]() {
         // Wait one execution loop for on_apps_synchronized() to be
         // called on all listeners.
@@ -855,23 +857,24 @@
   run_loop.Run();
 }
 
-AppId TestSystemWebAppInstallation::GetAppId() {
-  return ash::SystemWebAppManager::GetForTest(profile_)
+web_app::AppId TestSystemWebAppInstallation::GetAppId() {
+  return SystemWebAppManager::GetForTest(profile_)
       ->GetAppIdForSystemApp(type_.value())
       .value();
 }
 
 const GURL& TestSystemWebAppInstallation::GetAppUrl() {
-  return WebAppProvider::GetForTest(profile_)->registrar().GetAppStartUrl(
-      GetAppId());
+  return web_app::WebAppProvider::GetForTest(profile_)
+      ->registrar()
+      .GetAppStartUrl(GetAppId());
 }
 
-ash::SystemWebAppDelegate* TestSystemWebAppInstallation::GetDelegate() {
+SystemWebAppDelegate* TestSystemWebAppInstallation::GetDelegate() {
   auto it = system_app_delegates_.find(GetType());
   return it != system_app_delegates_.end() ? it->second.get() : nullptr;
 }
 
-ash::SystemWebAppType TestSystemWebAppInstallation::GetType() {
+SystemWebAppType TestSystemWebAppInstallation::GetType() {
   return type_.value();
 }
 
@@ -880,4 +883,4 @@
   auto_granted_permissions_.insert(permission);
 }
 
-}  // namespace web_app
+}  // namespace ash
diff --git a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h b/chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h
similarity index 82%
rename from chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h
rename to chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h
index 5d0b304..a935387 100644
--- a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h
+++ b/chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_WEB_APPLICATIONS_SYSTEM_WEB_APPS_TEST_TEST_SYSTEM_WEB_APP_INSTALLATION_H_
-#define CHROME_BROWSER_WEB_APPLICATIONS_SYSTEM_WEB_APPS_TEST_TEST_SYSTEM_WEB_APP_INSTALLATION_H_
+#ifndef CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_TEST_SUPPORT_TEST_SYSTEM_WEB_APP_INSTALLATION_H_
+#define CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_TEST_SUPPORT_TEST_SYSTEM_WEB_APP_INSTALLATION_H_
 
 #include <memory>
 
@@ -17,14 +17,14 @@
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-namespace web_app {
+namespace ash {
 
-class UnittestingSystemAppDelegate : public ash::SystemWebAppDelegate {
+class UnittestingSystemAppDelegate : public SystemWebAppDelegate {
  public:
-  UnittestingSystemAppDelegate(ash::SystemWebAppType type,
+  UnittestingSystemAppDelegate(SystemWebAppType type,
                                const std::string& name,
                                const GURL& url,
-                               WebAppInstallInfoFactory info_factory);
+                               web_app::WebAppInstallInfoFactory info_factory);
   UnittestingSystemAppDelegate(const UnittestingSystemAppDelegate&) = delete;
   UnittestingSystemAppDelegate& operator=(const UnittestingSystemAppDelegate&) =
       delete;
@@ -32,7 +32,7 @@
 
   using LaunchAndNavigateSystemWebAppCallback =
       base::RepeatingCallback<Browser*(Profile*,
-                                       WebAppProvider*,
+                                       web_app::WebAppProvider*,
                                        const GURL&,
                                        const apps::AppLaunchParams&)>;
 
@@ -54,12 +54,11 @@
   bool ShouldHaveTabStrip() const override;
   bool ShouldHaveReloadButtonInMinimalUi() const override;
   bool ShouldAllowScriptsToCloseWindows() const override;
-  absl::optional<ash::SystemWebAppBackgroundTaskInfo> GetTimerInfo()
-      const override;
+  absl::optional<SystemWebAppBackgroundTaskInfo> GetTimerInfo() const override;
   gfx::Rect GetDefaultBounds(Browser* browser) const override;
   Browser* LaunchAndNavigateSystemWebApp(
       Profile* profile,
-      WebAppProvider* provider,
+      web_app::WebAppProvider* provider,
       const GURL& url,
       const apps::AppLaunchParams& params) const override;
   bool IsAppEnabled() const override;
@@ -69,12 +68,12 @@
   bool ShouldAnimateThemeChanges() const override;
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
-  void SetAppIdsToUninstallAndReplace(const std::vector<AppId>&);
+  void SetAppIdsToUninstallAndReplace(const std::vector<web_app::AppId>&);
   void SetMinimumWindowSize(const gfx::Size&);
   void SetShouldReuseExistingWindow(bool);
   void SetShouldShowNewWindowMenuOption(bool);
   void SetShouldIncludeLaunchDirectory(bool);
-  void SetEnabledOriginTrials(const ash::OriginTrialsMap&);
+  void SetEnabledOriginTrials(const OriginTrialsMap&);
   void SetAdditionalSearchTerms(const std::vector<int>&);
   void SetShouldShowInLauncher(bool);
   void SetShouldShowInSearch(bool);
@@ -85,7 +84,7 @@
   void SetShouldHaveTabStrip(bool);
   void SetShouldHaveReloadButtonInMinimalUi(bool);
   void SetShouldAllowScriptsToCloseWindows(bool);
-  void SetTimerInfo(const ash::SystemWebAppBackgroundTaskInfo&);
+  void SetTimerInfo(const SystemWebAppBackgroundTaskInfo&);
   void SetDefaultBounds(base::RepeatingCallback<gfx::Rect(Browser*)>);
   void SetLaunchAndNavigateSystemWebApp(LaunchAndNavigateSystemWebAppCallback);
   void SetIsAppEnabled(bool);
@@ -96,9 +95,9 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
  private:
-  WebAppInstallInfoFactory info_factory_;
+  web_app::WebAppInstallInfoFactory info_factory_;
 
-  std::vector<AppId> uninstall_and_replace_;
+  std::vector<web_app::AppId> uninstall_and_replace_;
   gfx::Size minimum_window_size_;
   bool single_window_ = true;
   bool show_new_window_menu_option_ = false;
@@ -126,7 +125,7 @@
   LaunchAndNavigateSystemWebAppCallback launch_and_navigate_system_web_apps_ =
       base::NullCallback();
 
-  absl::optional<ash::SystemWebAppBackgroundTaskInfo> timer_info_;
+  absl::optional<SystemWebAppBackgroundTaskInfo> timer_info_;
 };
 
 // Class to setup the installation of a test System Web App.
@@ -154,7 +153,7 @@
       IncludeLaunchDirectory include_launch_directory);
 
   static std::unique_ptr<TestSystemWebAppInstallation>
-  SetUpAppWithEnabledOriginTrials(const ash::OriginTrialsMap& origin_to_trials);
+  SetUpAppWithEnabledOriginTrials(const OriginTrialsMap& origin_to_trials);
 
   static std::unique_ptr<TestSystemWebAppInstallation>
   SetUpAppNotShownInLauncher();
@@ -168,7 +167,7 @@
   static std::unique_ptr<TestSystemWebAppInstallation>
   SetUpAppWithAdditionalSearchTerms();
 
-  // This method additionally sets up a helper ash::SystemWebAppType::SETTING
+  // This method additionally sets up a helper SystemWebAppType::SETTING
   // system app for testing capturing links from a different SWA.
   static std::unique_ptr<TestSystemWebAppInstallation>
   SetUpAppThatCapturesNavigation();
@@ -219,12 +218,12 @@
 
   void WaitForAppInstall();
 
-  AppId GetAppId();
+  web_app::AppId GetAppId();
   const GURL& GetAppUrl();
-  ash::SystemWebAppDelegate* GetDelegate();
-  ash::SystemWebAppType GetType();
+  SystemWebAppDelegate* GetDelegate();
+  SystemWebAppType GetType();
 
-  void set_update_policy(ash::SystemWebAppManager::UpdatePolicy update_policy) {
+  void set_update_policy(SystemWebAppManager::UpdatePolicy update_policy) {
     update_policy_ = update_policy;
   }
 
@@ -245,23 +244,23 @@
   void RegisterAutoGrantedPermissions(ContentSettingsType permission);
 
   raw_ptr<Profile> profile_;
-  ash::SystemWebAppManager::UpdatePolicy update_policy_ =
-      ash::SystemWebAppManager::UpdatePolicy::kAlwaysUpdate;
+  SystemWebAppManager::UpdatePolicy update_policy_ =
+      SystemWebAppManager::UpdatePolicy::kAlwaysUpdate;
 
-  std::unique_ptr<FakeWebAppProviderCreator> fake_web_app_provider_creator_;
-  std::unique_ptr<TestSystemWebAppManagerCreator>
+  std::unique_ptr<web_app::FakeWebAppProviderCreator>
+      fake_web_app_provider_creator_;
+  std::unique_ptr<web_app::TestSystemWebAppManagerCreator>
       test_system_web_app_manager_creator_;
 
   // nullopt if SetUpWithoutApps() was used.
-  const absl::optional<ash::SystemWebAppType> type_;
+  const absl::optional<SystemWebAppType> type_;
   std::vector<std::unique_ptr<TestSystemWebAppWebUIControllerFactory>>
       web_ui_controller_factories_;
   std::set<ContentSettingsType> auto_granted_permissions_;
-  base::flat_map<ash::SystemWebAppType,
-                 std::unique_ptr<ash::SystemWebAppDelegate>>
+  base::flat_map<SystemWebAppType, std::unique_ptr<SystemWebAppDelegate>>
       system_app_delegates_;
 };
 
-}  // namespace web_app
+}  // namespace ash
 
-#endif  // CHROME_BROWSER_WEB_APPLICATIONS_SYSTEM_WEB_APPS_TEST_TEST_SYSTEM_WEB_APP_INSTALLATION_H_
+#endif  // CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_TEST_SUPPORT_TEST_SYSTEM_WEB_APP_INSTALLATION_H_
diff --git a/chrome/browser/ash/tether/tether_service_unittest.cc b/chrome/browser/ash/tether/tether_service_unittest.cc
index c098c2d9..7b3b717 100644
--- a/chrome/browser/ash/tether/tether_service_unittest.cc
+++ b/chrome/browser/ash/tether/tether_service_unittest.cc
@@ -41,6 +41,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
@@ -49,7 +50,6 @@
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_type_pattern.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
index 17030007..0497ca25 100644
--- a/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
+++ b/chrome/browser/ash/web_applications/media_app/media_app_integration_browsertest.cc
@@ -870,7 +870,7 @@
     const auto& descriptor = task.task_descriptor;
 
     EXPECT_EQ("Gallery", task.task_title);
-    EXPECT_EQ(extensions::api::file_manager_private::Verb::VERB_OPEN_WITH,
+    EXPECT_EQ(extensions::api::file_manager_private::Verb::VERB_NONE,
               task.task_verb);
     EXPECT_EQ(descriptor.app_id,
               *GetManager().GetAppIdForSystemApp(ash::SystemWebAppType::MEDIA));
diff --git a/chrome/browser/ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.cc b/chrome/browser/ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.cc
new file mode 100644
index 0000000..70c16a1
--- /dev/null
+++ b/chrome/browser/ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.cc
@@ -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.
+
+#include "chrome/browser/ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.h"
+
+#include "ash/constants/ash_features.h"
+#include "ash/constants/ash_pref_names.h"
+#include "ash/rgb_keyboard/rgb_keyboard_manager.h"
+#include "ash/shell.h"
+#include "ash/webui/personalization_app/mojom/personalization_app.mojom-shared.h"
+#include "base/metrics/histogram_functions.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "components/prefs/pref_service.h"
+
+KeyboardBacklightColorMetricsProvider::KeyboardBacklightColorMetricsProvider() =
+    default;
+KeyboardBacklightColorMetricsProvider::
+    ~KeyboardBacklightColorMetricsProvider() = default;
+
+void KeyboardBacklightColorMetricsProvider::ProvideCurrentSessionData(
+    metrics::ChromeUserMetricsExtension* uma_proto_unused) {
+  if (!ash::features::IsRgbKeyboardEnabled() ||
+      !ash::Shell::Get()->rgb_keyboard_manager()->IsRgbKeyboardSupported()) {
+    return;
+  }
+
+  PrefService* pref_service =
+      ProfileManager::GetActiveUserProfile()->GetPrefs();
+  DCHECK(pref_service);
+  auto backlight_color =
+      static_cast<ash::personalization_app::mojom::BacklightColor>(
+          pref_service->GetInteger(
+              ash::prefs::kPersonalizationKeyboardBacklightColor));
+  base::UmaHistogramEnumeration(
+      "Ash.Personalization.KeyboardBacklight.Color.Settled", backlight_color);
+}
diff --git a/chrome/browser/ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.h b/chrome/browser/ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.h
new file mode 100644
index 0000000..9034ee3
--- /dev/null
+++ b/chrome/browser/ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.h
@@ -0,0 +1,26 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_COLOR_METRICS_PROVIDER_H_
+#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_COLOR_METRICS_PROVIDER_H_
+
+#include "components/metrics/metrics_provider.h"
+
+class KeyboardBacklightColorMetricsProvider : public metrics::MetricsProvider {
+ public:
+  KeyboardBacklightColorMetricsProvider();
+
+  KeyboardBacklightColorMetricsProvider(
+      const KeyboardBacklightColorMetricsProvider&) = delete;
+  KeyboardBacklightColorMetricsProvider& operator=(
+      const KeyboardBacklightColorMetricsProvider&) = delete;
+
+  ~KeyboardBacklightColorMetricsProvider() override;
+
+  // metrics::MetricsProvider:
+  void ProvideCurrentSessionData(
+      metrics::ChromeUserMetricsExtension* uma_proto_unused) override;
+};
+
+#endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_PERSONALIZATION_APP_KEYBOARD_BACKLIGHT_COLOR_METRICS_PROVIDER_H_
diff --git a/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_bridge.cc b/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_bridge.cc
index 056e167..9ac0190 100644
--- a/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_bridge.cc
+++ b/chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_bridge.cc
@@ -20,8 +20,8 @@
 #include "chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_network_context.h"
 #include "chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_notification_controller.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 9b1e75f..3f9de16 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -746,7 +746,7 @@
 // 9. document.getElementById('id').value = "bar";
 //
 // Then `ListenForValueChange("id", "unblock", rfh).Wait(base::Seconds(5)) ==
-// "bar"` the ListenForValueChange() call happens any point before Event 9 and
+// "bar"`. The ListenForValueChange() call happens any point before Event 9, and
 // Event 9 happens no later than 5 seconds after that.
 [[nodiscard]] ValueWaiter ListenForValueChange(
     const std::string& id,
@@ -892,7 +892,7 @@
 
   void SetUp() override {
     ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
-    InProcessBrowserTest::SetUp();
+    AutofillUiTest::SetUp();
   }
 
   void SetUpOnMainThread() override {
@@ -926,6 +926,9 @@
     cert_verifier_.SetUpCommandLine(command_line);
     // Needed to allow input before commit on various builders.
     command_line->AppendSwitch(blink::switches::kAllowPreCommitInput);
+    // HTTPS server only serves a valid cert for localhost, so this is needed to
+    // load pages from "a.com" without an interstitial.
+    command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
     // TODO(crbug.com/1258185): Migrate to a better mechanism for testing around
     // language detection.
     command_line->AppendSwitch(switches::kOverrideLanguageDetection);
@@ -941,6 +944,16 @@
     AutofillUiTest::TearDownInProcessBrowserTestFixture();
   }
 
+  // Skips AutofillUiTest::TearDownOnMainThread() and instead calls the
+  // grandparent's TearDownOnMainThread(). The reason is:
+  // After autofilling a credit card, there is a delayed task of recording its
+  // use on the db. If we reenable the services, the config would be deleted and
+  // we won't be able to encrypt the cc number. There will be a crash while
+  // encrypting the cc number.
+  void TearDownOnMainThread() override {
+    InProcessBrowserTest::TearDownOnMainThread();
+  }
+
   std::unique_ptr<net::test_server::HttpResponse> HandleTestURL(
       const net::test_server::HttpRequest& request) {
     if (request.relative_url != kTestUrlPath)
@@ -1143,6 +1156,8 @@
 
   static const char kTestUrlPath[];
 
+  base::HistogramTester& histogram_tester() { return histogram_tester_; }
+
  private:
   net::EmbeddedTestServer https_server_;
 
@@ -1165,6 +1180,8 @@
   std::string test_url_content_;
 
   base::test::ScopedFeatureList feature_list_;
+
+  base::HistogramTester histogram_tester_;
 };
 
 const char AutofillInteractiveTestBase::kTestUrlPath[] =
@@ -1216,10 +1233,7 @@
     command_line->AppendSwitch(switches::kNoProxyServer);
   }
 
-  base::HistogramTester& histogram_tester() { return histogram_tester_; }
-
  private:
-  base::HistogramTester histogram_tester_;
   std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor_;
 };
 
@@ -2772,38 +2786,8 @@
   EXPECT_EQ("15125551234", GetFieldValueById("phone"));
 }
 
-class AutofillInteractiveTestCreditCard : public AutofillInteractiveTestBase {
- public:
-  AutofillInteractiveTestCreditCard() = default;
-  AutofillInteractiveTestCreditCard(const AutofillInteractiveTestCreditCard&) =
-      delete;
-  AutofillInteractiveTestCreditCard& operator=(
-      const AutofillInteractiveTestCreditCard&) = delete;
-  ~AutofillInteractiveTestCreditCard() override = default;
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    AutofillInteractiveTestBase::SetUpCommandLine(command_line);
-    // HTTPS server only serves a valid cert for localhost, so this is needed to
-    // load pages from "a.com" without an interstitial.
-    command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
-  }
-
-  // After autofilling the credit card, there is a delayed task of recording its
-  // use on the db. If we reenable the services, the config would be deleted and
-  // we won't be able to encrypt the cc number. There will be a crash while
-  // encrypting the cc number.
-  void TearDownOnMainThread() override {}
-
-  const base::HistogramTester& histogram_tester() const {
-    return histogram_tester_;
-  }
-
- private:
-  base::HistogramTester histogram_tester_;
-};
-
 // Test that credit card autofill works.
-IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestCreditCard, FillLocalCreditCard) {
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestBase, FillLocalCreditCard) {
   CreateTestCreditCart();
   GURL url = https_server()->GetURL("a.com",
                                     "/autofill/autofill_creditcard_form.html");
@@ -2819,7 +2803,6 @@
 // Test that we do not fill formless non-checkout forms when we enable the
 // formless form restrictions.
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestBase, NoAutocomplete) {
-  base::HistogramTester histogram;
   CreateTestProfile();
   GURL url =
       embedded_test_server()->GetURL("/autofill/formless_no_autocomplete.html");
@@ -2832,7 +2815,8 @@
   // If only some form fields are tagged with autocomplete types, then the
   // number of input elements will not match the number of fields when autofill
   // triees to preview or fill.
-  histogram.ExpectUniqueSample("Autofill.NumElementsMatchesNumFields", true, 2);
+  histogram_tester().ExpectUniqueSample("Autofill.NumElementsMatchesNumFields",
+                                        true, 2);
 
   EXPECT_EQ("Milton", GetFieldValueById("firstname"));
   EXPECT_EQ("4120 Freidrich Lane", GetFieldValueById("address"));
@@ -2850,7 +2834,6 @@
 // of the form.
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestBase, SomeAutocomplete) {
   CreateTestProfile();
-  base::HistogramTester histogram;
   GURL url = embedded_test_server()->GetURL(
       "/autofill/formless_some_autocomplete.html");
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
@@ -2862,7 +2845,8 @@
   // If only some form fields are tagged with autocomplete types, then the
   // number of input elements will not match the number of fields when autofill
   // triees to preview or fill.
-  histogram.ExpectUniqueSample("Autofill.NumElementsMatchesNumFields", true, 2);
+  histogram_tester().ExpectUniqueSample("Autofill.NumElementsMatchesNumFields",
+                                        true, 2);
 
   EXPECT_EQ("Milton", GetFieldValueById("firstname"));
   EXPECT_EQ("4120 Freidrich Lane", GetFieldValueById("address"));
@@ -2878,7 +2862,6 @@
 // TODO(https://crbug.com/1297560): Check back if flakiness is fixed now.
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestBase, AllAutocomplete) {
   CreateTestProfile();
-  base::HistogramTester histogram;
   GURL url = embedded_test_server()->GetURL(
       "/autofill/formless_all_autocomplete.html");
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
@@ -2889,7 +2872,8 @@
 
   // If all form fields are tagged with autocomplete types, we make them all
   // available to be filled.
-  histogram.ExpectUniqueSample("Autofill.NumElementsMatchesNumFields", true, 2);
+  histogram_tester().ExpectUniqueSample("Autofill.NumElementsMatchesNumFields",
+                                        true, 2);
 
   EXPECT_EQ("Milton", GetFieldValueById("firstname"));
   EXPECT_EQ("4120 Freidrich Lane", GetFieldValueById("address"));
@@ -2900,67 +2884,6 @@
   EXPECT_EQ("15125551234", GetFieldValueById("phone"));
 }
 
-// Some websites have JavaScript handlers that mess with the input of the user
-// and autofill. A common problem is that the date "09/2999" gets reformatted
-// into "09 / 20" instead of "09 / 99".
-// In these tests, the following steps will happen:
-// 1) Autofill recognizes an expiration date field with maxlength=7, will infer
-//    that it is supposed to fill 09/2999 and will fill that value.
-// 2) The website sees the content 09/2999 and reformats it to 09 / 29 because
-//    this is what websites do sometimes.
-// 3) The AutofillAgent recognizes that it failed to fill 09/2999 and fills
-//    09 / 99 instead.
-// 4) The promise waits to see 09 / 99 and resolved.
-// Flaky on Win https://crbug.com/1337757.
-#if BUILDFLAG(IS_WIN)
-#define MAYBE_FillCardOnReformatingForm DISABLED_FillCardOnReformatingForm
-#else
-#define MAYBE_FillCardOnReformatingForm FillCardOnReformatingForm
-#endif
-IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestCreditCard,
-                       MAYBE_FillCardOnReformatingForm) {
-  CreateTestCreditCart();
-  GURL url = https_server()->GetURL(
-      "a.com", "/autofill/autofill_creditcard_form_with_date_formatter.html");
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
-
-  ASSERT_TRUE(AutofillFlow(GetElementById("CREDIT_CARD_NAME_FULL"), this));
-
-  std::string script = R"(
-    new Promise(function (resolve) {
-      (function waitForCorrectExpirationDate(){
-        const e = document.getElementById('CREDIT_CARD_EXP_DATE');
-        if (e && e.value === '09 / 99') {
-          return resolve(e.value);
-        }
-        setTimeout(waitForCorrectExpirationDate, 30);
-      })();  // <-- This defines and calls waitForCorrectExpirationDate().
-    });
-  )";
-  EXPECT_EQ("09 / 99", content::EvalJs(GetWebContents(), script));
-  content::LoadStopObserver load_stop_observer(GetWebContents());
-  ASSERT_TRUE(content::ExecuteScript(
-      GetWebContents(), "document.getElementById('testform').submit();"));
-  load_stop_observer.Wait();
-
-  // Short hand for ExpectbucketCount:
-  auto expect_count = [&](base::StringPiece name,
-                          base::HistogramBase::Sample sample,
-                          base::HistogramBase::Count expected_count) {
-    histogram_tester().ExpectBucketCount(name, sample, expected_count);
-  };
-  expect_count("Autofill.KeyMetrics.FillingReadiness.CreditCard", 1, 1);
-  expect_count("Autofill.KeyMetrics.FillingAcceptance.CreditCard", 1, 1);
-  expect_count("Autofill.KeyMetrics.FillingCorrectness.CreditCard", 1, 1);
-  expect_count("Autofill.KeyMetrics.FillingAssistance.CreditCard", 1, 1);
-  // Ensure that refills don't count as edits.
-  expect_count("Autofill.NumberOfEditedAutofilledFieldsAtSubmission", 0, 1);
-  expect_count("Autofill.PerfectFilling.CreditCards", 1, 1);
-  // Bucket 0 = edited, 1 = accepted; 3 samples for 3 fields.
-  expect_count("Autofill.EditedAutofilledFieldAtSubmission.Aggregate", 0, 0);
-  expect_count("Autofill.EditedAutofilledFieldAtSubmission.Aggregate", 1, 3);
-}
-
 // An extension of the test fixture for tests with site isolation.
 class AutofillInteractiveIsolationTest : public AutofillInteractiveTestBase {
  protected:
@@ -3199,13 +3122,6 @@
       const MAYBE_AutofillInteractiveTestDynamicForm&) = delete;
   ~MAYBE_AutofillInteractiveTestDynamicForm() override = default;
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    AutofillInteractiveTestBase::SetUpCommandLine(command_line);
-    // HTTPS server only serves a valid cert for localhost, so this is needed to
-    // load pages from "a.com" without an interstitial.
-    command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
-  }
-
   ValueWaiter ListenForRefill(
       const std::string& id,
       absl::optional<std::string> unblock_variable = "refill") {
@@ -3214,8 +3130,10 @@
 
   // Refills only happen within `kLimitBeforeRefill` second of the initial fill.
   // Slow bots may exceed this limit and thus cause flakiness.
-  void AdvanceClockBetweenFillAndRefill(
-      base::TimeDelta delta = kLimitBeforeRefill / 10) {
+  static constexpr base::TimeDelta kLessThanLimitBeforeRefill =
+      kLimitBeforeRefill / 10;
+
+  void AdvanceClock(base::TimeDelta delta) {
     clock_.Advance(delta);
     tick_clock_.Advance(delta);
   }
@@ -3227,6 +3145,10 @@
   TestAutofillTickClock tick_clock_{AutofillTickClock::NowTicks()};
 };
 
+INSTANTIATE_TEST_SUITE_P(AutofillInteractiveTest,
+                         MAYBE_AutofillInteractiveTestDynamicForm,
+                         testing::Bool());
+
 // Test that we can Autofill dynamically generated forms.
 // TODO(https://crbug.com/1297560): Check back if flakiness is fixed now.
 IN_PROC_BROWSER_TEST_P(MAYBE_AutofillInteractiveTestDynamicForm,
@@ -3238,7 +3160,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname_form1");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3261,7 +3183,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname_form1");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname_form1"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3275,7 +3197,7 @@
 
   refill = ListenForRefill("firstname_form2");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname_form2"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3298,7 +3220,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname_form2");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_FALSE(std::move(refill).Wait());
 
   // Make sure the new form was not filled.
@@ -3321,7 +3243,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname_form1");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill(kLimitBeforeRefill + base::Milliseconds(1));
+  AdvanceClock(kLimitBeforeRefill + base::Milliseconds(1));
   ASSERT_FALSE(std::move(refill).Wait());
 
   // Make sure that the new form was not filled.
@@ -3345,7 +3267,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname_form1");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // The fields present in the initial fill should be filled.
@@ -3376,7 +3298,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3401,7 +3323,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3427,7 +3349,7 @@
 
   ValueWaiter refill = ListenForRefill("address1");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3452,7 +3374,7 @@
 
   ValueWaiter refill = ListenForRefill("address1");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3478,7 +3400,7 @@
 
   ValueWaiter refill = ListenForRefill("address1_7");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname_5"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the second form was filled correctly, and the first form was left
@@ -3504,7 +3426,7 @@
 
   ValueWaiter refill = ListenForRefill("address1_7");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname_5"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the second form was filled correctly, and the first form was left
@@ -3532,7 +3454,7 @@
 
   ValueWaiter refill = ListenForRefill("address1_7");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname_5"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the second form was filled correctly, and the first form was left
@@ -3557,7 +3479,7 @@
 
   ValueWaiter refill = ListenForRefill("address1");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3580,7 +3502,7 @@
   ValueWaiter refill = ListenForRefill("cc-name");
   ASSERT_TRUE(AutofillFlow(GetElementById("cc-name"), this,
                            {.show_method = ShowMethod::ByChar('M')}));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   EXPECT_EQ("Milton Waddams", GetFieldValueById("cc-name"));
@@ -3601,7 +3523,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3626,7 +3548,7 @@
   ValueWaiter refill1 = ListenForRefill("address1", "refill1");
   ValueWaiter refill2 = ListenForRefill("firstname", "refill2");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill1).Wait());
   ASSERT_FALSE(std::move(refill2).Wait());
 
@@ -3653,7 +3575,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname_form1");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3680,7 +3602,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3705,7 +3627,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname_syntheticform1");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3731,7 +3653,7 @@
 
   ValueWaiter refill = ListenForRefill("firstname");
   ASSERT_TRUE(AutofillFlow(GetElementById("firstname"), this));
-  AdvanceClockBetweenFillAndRefill();
+  AdvanceClock(kLessThanLimitBeforeRefill);
   ASSERT_TRUE(std::move(refill).Wait());
 
   // Make sure the new form was filled correctly.
@@ -3744,6 +3666,60 @@
   EXPECT_EQ("15125551234", GetFieldValueById("phone"));
 }
 
+// Some websites have JavaScript handlers that mess with the input of the user
+// and autofill. A common problem is that the date "09/2999" gets reformatted
+// into "09 / 20" instead of "09 / 99".
+// In these tests, the following steps will happen:
+// 1) Autofill recognizes an expiration date field with maxlength=7, will infer
+//    that it is supposed to fill 09/2999 and will fill that value.
+// 2) The website sees the content 09/2999 and reformats it to 09 / 29 because
+//    this is what websites do sometimes.
+// 3) The AutofillAgent recognizes that it failed to fill 09/2999 and fills
+//    09 / 99 instead.
+// 4) The promise waits to see 09 / 99 and resolved.
+// Flaky on Win https://crbug.com/1337757.
+IN_PROC_BROWSER_TEST_P(MAYBE_AutofillInteractiveTestDynamicForm,
+                       FillCardOnReformattingForm) {
+  CreateTestCreditCart();
+  GURL url = https_server()->GetURL(
+      "a.com", "/autofill/autofill_creditcard_form_with_date_formatter.html");
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+
+  ValueWaiter reformat_waiter =
+      ListenForValueChange("CREDIT_CARD_EXP_DATE", "unblock", GetWebContents());
+  ASSERT_TRUE(AutofillFlow(GetElementById("CREDIT_CARD_NAME_FULL"), this));
+  AdvanceClock(kLessThanLimitBeforeRefill);
+  ASSERT_TRUE(std::move(reformat_waiter).Wait());
+  EXPECT_EQ("09 / 99", GetFieldValue(GetElementById("CREDIT_CARD_EXP_DATE")));
+
+  // The timestamp from BrowserAutofillManager::OnDidFillAutofillFormData()
+  // comes from the renderer process and thus from an actual clock. Since this
+  // interaction timestamp must be before the submission timestamp, we advance
+  // the browser by a lot.
+  AdvanceClock(base::Minutes(10));
+  content::LoadStopObserver load_stop_observer(GetWebContents());
+  ASSERT_TRUE(content::ExecuteScript(
+      GetWebContents(), "document.getElementById('testform').submit();"));
+  load_stop_observer.Wait();
+
+  // Short hand for ExpectbucketCount:
+  auto expect_count = [&](base::StringPiece name,
+                          base::HistogramBase::Sample sample,
+                          base::HistogramBase::Count expected_count) {
+    histogram_tester().ExpectBucketCount(name, sample, expected_count);
+  };
+  expect_count("Autofill.KeyMetrics.FillingReadiness.CreditCard", 1, 1);
+  expect_count("Autofill.KeyMetrics.FillingAcceptance.CreditCard", 1, 1);
+  expect_count("Autofill.KeyMetrics.FillingCorrectness.CreditCard", 1, 1);
+  expect_count("Autofill.KeyMetrics.FillingAssistance.CreditCard", 1, 1);
+  // Ensure that refills don't count as edits.
+  expect_count("Autofill.NumberOfEditedAutofilledFieldsAtSubmission", 0, 1);
+  expect_count("Autofill.PerfectFilling.CreditCards", 1, 1);
+  // Bucket 0 = edited, 1 = accepted; 3 samples for 3 fields.
+  expect_count("Autofill.EditedAutofilledFieldAtSubmission.Aggregate", 0, 0);
+  expect_count("Autofill.EditedAutofilledFieldAtSubmission.Aggregate", 1, 3);
+}
+
 IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ShadowDOM) {
   CreateTestProfile();
   GURL url =
@@ -3763,10 +3739,6 @@
   EXPECT_EQ("78744", Js("getZip()"));
 }
 
-INSTANTIATE_TEST_SUITE_P(AutofillInteractiveTest,
-                         MAYBE_AutofillInteractiveTestDynamicForm,
-                         testing::Bool());
-
 // ChromeVox is only available on ChromeOS.
 #if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(ENABLE_EXTENSIONS)
 
@@ -3780,6 +3752,7 @@
     // in-flight requests during test shutdown. https://crbug.com/923090
     ash::AccessibilityManager::Get()->EnableSpokenFeedback(false);
     AutomationManagerAura::GetInstance()->Disable();
+    AutofillInteractiveTestBase::TearDownOnMainThread();
   }
 
   void EnableChromeVox() {
diff --git a/chrome/browser/autofill/autofill_uitest.cc b/chrome/browser/autofill/autofill_uitest.cc
index 165fa8e..803177b 100644
--- a/chrome/browser/autofill/autofill_uitest.cc
+++ b/chrome/browser/autofill/autofill_uitest.cc
@@ -157,6 +157,7 @@
   BrowserAutofillManager* autofill_manager = GetBrowserAutofillManager();
   if (autofill_manager)
     autofill_manager->client()->HideAutofillPopup(PopupHidingReason::kTabGone);
+  InProcessBrowserTest::TearDownOnMainThread();
 }
 
 bool AutofillUiTest::SendKeyToPageAndWait(
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManagerTest.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManagerTest.java
index b7cd217..b2b863d 100644
--- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManagerTest.java
+++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManagerTest.java
@@ -9,17 +9,14 @@
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.metrics.HistogramTestRule;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
 import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
-import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
@@ -28,9 +25,6 @@
 @RunWith(BaseJUnit4ClassRunner.class)
 @Batch(Batch.UNIT_TESTS)
 public class BackPressManagerTest {
-    @Rule
-    public HistogramTestRule mHistogramTester = new HistogramTestRule();
-
     private class EmptyBackPressHandler implements BackPressHandler {
         private ObservableSupplierImpl<Boolean> mSupplier = new ObservableSupplierImpl<>();
 
@@ -45,7 +39,6 @@
 
     @BeforeClass
     public static void setUpClass() {
-        NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
         ObservableSupplierImpl.setIgnoreThreadChecksForTesting(true);
     }
 
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandlerUnitTest.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandlerUnitTest.java
index 5fb8e0c..b64b405b 100644
--- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandlerUnitTest.java
+++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandlerUnitTest.java
@@ -28,7 +28,6 @@
 import org.chromium.base.UserDataHost;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.metrics.HistogramTestRule;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
 import org.chromium.chrome.browser.back_press.MinimizeAppAndCloseTabBackPressHandler.MinimizeAppAndCloseTabType;
@@ -37,7 +36,6 @@
 import org.chromium.chrome.browser.tab.TabAssociatedApp;
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
@@ -49,9 +47,6 @@
     @Rule
     public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
-    @Rule
-    public HistogramTestRule mHistogramTester = new HistogramTestRule();
-
     @Mock
     private TabModelSelector mTabModelSelector;
 
@@ -66,7 +61,6 @@
 
     @BeforeClass
     public static void setUpClass() {
-        NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
         ObservableSupplierImpl.setIgnoreThreadChecksForTesting(true);
     }
 
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc
index 77d5a8a8..9803fd1 100644
--- a/chrome/browser/browser_features.cc
+++ b/chrome/browser/browser_features.cc
@@ -27,7 +27,7 @@
 
 // Destroy profiles when their last browser window is closed, instead of when
 // the browser exits.
-const base::Feature kDestroyProfileOnBrowserClose{
+const base::Feature kDestroyProfileOnBrowserClose {
   "DestroyProfileOnBrowserClose",
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
       base::FEATURE_ENABLED_BY_DEFAULT
@@ -164,4 +164,10 @@
     "RestartNetworkServiceUnsandboxedForFailedLaunch",
     base::FEATURE_ENABLED_BY_DEFAULT};
 
+#if BUILDFLAG(IS_WIN)
+// When this feature is enabled, metrics are gathered regarding the performance
+// and reliability of app-bound encryption primitives on a background thread.
+const base::Feature kAppBoundEncryptionMetrics{
+    "AppBoundEncryptionMetrics", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
 }  // namespace features
diff --git a/chrome/browser/browser_features.h b/chrome/browser/browser_features.h
index 4f70115..f860c19 100644
--- a/chrome/browser/browser_features.h
+++ b/chrome/browser/browser_features.h
@@ -68,6 +68,10 @@
 
 extern const base::Feature kKeyPinningComponentUpdater;
 
+#if BUILDFLAG(IS_WIN)
+extern const base::Feature kAppBoundEncryptionMetrics;
+#endif
+
 }  // namespace features
 
 #endif  // CHROME_BROWSER_BROWSER_FEATURES_H_
diff --git a/chrome/browser/browser_keyevents_browsertest.cc b/chrome/browser/browser_keyevents_browsertest.cc
index a000c60..65b882d 100644
--- a/chrome/browser/browser_keyevents_browsertest.cc
+++ b/chrome/browser/browser_keyevents_browsertest.cc
@@ -289,7 +289,8 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, NormalKeyEvents) {
+// TODO(crbug.com/1338416): Re-enable this test
+IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_NormalKeyEvents) {
   static const KeyEventTestData kTestNoInput[] = {
     // a
     { ui::VKEY_A, false, false, false, false,
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 7bfdf77e..e22604a 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -39,7 +39,7 @@
         <include name="IDR_ABOUT_SYS_JS" file="resources\about_sys\about_sys.js" preprocess="true" type="BINDATA" />
       </if>
       <include name="IDR_AD_NETWORK_HASHES" file="resources\ad_networks.dat" type="BINDATA" />
-      <if expr="use_nss_certs and use_aura">
+      <if expr="enable_webui_certificate_viewer">
         <include name="IDR_CERTIFICATE_VIEWER_HTML" file="resources\certificate_viewer\certificate_viewer.html" type="BINDATA" />
         <include name="IDR_CERTIFICATE_VIEWER_JS" file="${root_gen_dir}\chrome\browser\resources\certificate_viewer\tsc\certificate_viewer.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_CERTIFICATE_VIEWER_CSS" file="resources\certificate_viewer\certificate_viewer.css" type="BINDATA" />
diff --git a/chrome/browser/certificate_provider/certificate_provider_service_factory.cc b/chrome/browser/certificate_provider/certificate_provider_service_factory.cc
index cce0016..6e94c23 100644
--- a/chrome/browser/certificate_provider/certificate_provider_service_factory.cc
+++ b/chrome/browser/certificate_provider/certificate_provider_service_factory.cc
@@ -86,8 +86,8 @@
     int request_id) {
   api_cp::CertificatesUpdateRequest certificates_update_request;
   certificates_update_request.certificates_request_id = request_id;
-  std::vector<base::Value> event_args;
-  event_args.push_back(
+  base::Value::List event_args;
+  event_args.Append(
       base::Value::FromUniquePtrValue(certificates_update_request.ToValue()));
   return std::make_unique<extensions::Event>(
       extensions::events::CERTIFICATEPROVIDER_ON_CERTIFICATES_UPDATE_REQUESTED,
@@ -97,8 +97,8 @@
 // Constructs the legacy "onCertificatesRequested" event.
 std::unique_ptr<extensions::Event> BuildOnCertificatesRequestedEvent(
     int request_id) {
-  std::vector<base::Value> event_args;
-  event_args.push_back(base::Value(request_id));
+  base::Value::List event_args;
+  event_args.Append(request_id);
   return std::make_unique<extensions::Event>(
       extensions::events::CERTIFICATEPROVIDER_ON_CERTIFICATES_REQUESTED,
       api_cp::OnCertificatesRequested::kEventName, std::move(event_args));
@@ -146,8 +146,8 @@
       net::x509_util::CryptoBufferAsStringPiece(certificate.cert_buffer());
   request.certificate.assign(cert_der.begin(), cert_der.end());
 
-  std::vector<base::Value> event_args;
-  event_args.push_back(base::Value::FromUniquePtrValue(request.ToValue()));
+  base::Value::List event_args;
+  event_args.Append(base::Value::FromUniquePtrValue(request.ToValue()));
 
   return std::make_unique<extensions::Event>(
       extensions::events::CERTIFICATEPROVIDER_ON_SIGNATURE_REQUESTED,
@@ -197,9 +197,9 @@
   }
   request.digest.resize(digest_len);
 
-  std::vector<base::Value> event_args;
-  event_args.push_back(base::Value(request_id));
-  event_args.push_back(base::Value::FromUniquePtrValue(request.ToValue()));
+  base::Value::List event_args;
+  event_args.Append(request_id);
+  event_args.Append(base::Value::FromUniquePtrValue(request.ToValue()));
 
   return std::make_unique<extensions::Event>(
       extensions::events::CERTIFICATEPROVIDER_ON_SIGN_DIGEST_REQUESTED,
diff --git a/chrome/browser/certificate_provider/test_certificate_provider_extension.cc b/chrome/browser/certificate_provider/test_certificate_provider_extension.cc
index 9e43711..105d8b76 100644
--- a/chrome/browser/certificate_provider/test_certificate_provider_extension.cc
+++ b/chrome/browser/certificate_provider/test_certificate_provider_extension.cc
@@ -216,12 +216,12 @@
     cert_info_values.Append(MakeClientCertificateInfoValue(*certificate_));
   message_data.SetKey("certificateInfoList", std::move(cert_info_values));
 
-  auto message = std::make_unique<base::Value>(base::Value::Type::LIST);
-  message->Append(std::move(message_data));
+  base::Value::List message;
+  message.Append(std::move(message_data));
   auto event = std::make_unique<extensions::Event>(
       extensions::events::FOR_TEST,
-      extensions::api::test::OnMessage::kEventName,
-      std::move(*message).TakeListDeprecated(), browser_context_);
+      extensions::api::test::OnMessage::kEventName, std::move(message),
+      browser_context_);
   extensions::EventRouter::Get(browser_context_)
       ->DispatchEventToExtension(extension_id(), std::move(event));
 }
diff --git a/chrome/browser/certificate_viewer.h b/chrome/browser/certificate_viewer.h
index 617a534..a6ba6abb 100644
--- a/chrome/browser/certificate_viewer.h
+++ b/chrome/browser/certificate_viewer.h
@@ -19,6 +19,14 @@
                            gfx::NativeWindow parent,
                            net::X509Certificate* cert);
 
+// Opens a certificate viewer for client authentication under |parent| to
+// display |cert|.
+// TODO(https://crbug.com/1336065): remove this and use the internal cert
+// viewer for client auth as well.
+void ShowCertificateViewerForClientAuth(content::WebContents* web_contents,
+                                        gfx::NativeWindow parent,
+                                        net::X509Certificate* cert);
+
 // Go through the motions but do not invoke the native API showing a modal
 // interactive dialog on platforms where that results in hanging tests.
 void MockCertificateViewerForTesting();
diff --git a/chrome/browser/chrome_back_forward_cache_browsertest.cc b/chrome/browser/chrome_back_forward_cache_browsertest.cc
index 96b82acb..70227f1 100644
--- a/chrome/browser/chrome_back_forward_cache_browsertest.cc
+++ b/chrome/browser/chrome_back_forward_cache_browsertest.cc
@@ -12,6 +12,7 @@
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/content_settings/mixed_content_settings_tab_helper.h"
+#include "chrome/browser/pdf/pdf_extension_test_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/task_manager/task_manager_tester.h"
 #include "chrome/browser/ui/browser.h"
@@ -24,6 +25,7 @@
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
+#include "components/metrics/content/subprocess_metrics_provider.h"
 #include "components/network_session_configurator/common/network_switches.h"
 #include "components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h"
 #include "components/permissions/permission_manager.h"
@@ -31,7 +33,6 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -39,6 +40,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/blink/public/common/permissions/permission_utils.h"
+#include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
 #include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -661,3 +663,255 @@
               ::testing::ElementsAre(expected_url_b_active_title,
                                      expected_url_a_cached_title));
 }
+
+class ChromeBackForwardCacheBrowserWithEmbedTest
+    : public ChromeBackForwardCacheBrowserTest,
+      public ::testing::WithParamInterface<std::string> {
+ public:
+  ChromeBackForwardCacheBrowserWithEmbedTest() = default;
+  ~ChromeBackForwardCacheBrowserWithEmbedTest() override = default;
+
+  static std::string GetSrcAttributeForTag(const std::string& tag) {
+    return tag == "embed" ? "src" : "data";
+  }
+
+  void SetUpOnMainThread() override {
+    ChromeBackForwardCacheBrowserTest::SetUpOnMainThread();
+    ASSERT_TRUE(embedded_test_server()->Start());
+  }
+
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // Allow BackForwardCache for non-plugin embedded elements.
+    EnableFeatureAndSetParams(
+        blink::features::kBackForwardCacheEnabledForNonPluginEmbed, "", "");
+    ChromeBackForwardCacheBrowserTest::SetUpCommandLine(command_line);
+  }
+
+  void ExpectBlocklistedFeature(
+      blink::scheduler::WebSchedulerTrackedFeature feature,
+      base::Location location) {
+    content::FetchHistogramsFromChildProcesses();
+    base::HistogramBase::Sample sample = base::HistogramBase::Sample(feature);
+    base::Bucket expected_blocklisted(sample, 1);
+
+    EXPECT_THAT(histogram_tester_->GetAllSamples(
+                    "BackForwardCache.HistoryNavigationOutcome."
+                    "BlocklistedFeature"),
+                testing::Contains(expected_blocklisted))
+        << location.ToString();
+
+    EXPECT_THAT(histogram_tester_->GetAllSamples(
+                    "BackForwardCache.AllSites.HistoryNavigationOutcome."
+                    "BlocklistedFeature"),
+                testing::Contains(expected_blocklisted))
+        << location.ToString();
+  }
+
+  void ExpectNotRestoredReasonHaveInnerContents(base::Location location) {
+    // BackForwardCacheMetrics::NotRestoredReason::kHaveInnerContents
+    uint8_t reason = 32;
+    content::FetchHistogramsFromChildProcesses();
+    base::HistogramBase::Sample sample = base::HistogramBase::Sample(reason);
+    base::Bucket expected_not_restored(sample, 1);
+
+    EXPECT_THAT(histogram_tester_->GetAllSamples(
+                    "BackForwardCache.HistoryNavigationOutcome."
+                    "NotRestoredReason"),
+                testing::Contains(expected_not_restored))
+        << location.ToString();
+
+    EXPECT_THAT(histogram_tester_->GetAllSamples(
+                    "BackForwardCache.AllSites.HistoryNavigationOutcome."
+                    "NotRestoredReason"),
+                testing::Contains(expected_not_restored))
+        << location.ToString();
+  }
+};
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    ChromeBackForwardCacheBrowserWithEmbedTest,
+    testing::ValuesIn<std::vector<std::string>>({"embed", "object"}));
+
+IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedTest,
+                       DoesNotCachePageWithEmbeddedPlugin) {
+  const auto tag = GetParam();
+  const auto page_with_plugin = base::StringPrintf(
+      "/back_forward_cache/page_with_%s_plugin.html", tag.c_str());
+
+  // Navigate to A, a page with embedded Pepper plugin.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(),
+      embedded_test_server()->GetURL("a.com", page_with_plugin)));
+  content::RenderFrameHostWrapper rfh_a(current_frame_host());
+
+  // Navigate to B.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", "/title2.html")));
+
+  // Verify A is NOT stored in the BackForwardCache.
+  EXPECT_NE(rfh_a->GetLifecycleState(),
+            content::RenderFrameHost::LifecycleState::kInBackForwardCache);
+
+  // Navigate back to A.
+  ASSERT_TRUE(content::HistoryGoBack(web_contents()));
+  // Verify A is not restored from BackForwardCache due to |kContainsPlugins|.
+  ExpectBlocklistedFeature(
+      blink::scheduler::WebSchedulerTrackedFeature::kContainsPlugins,
+      FROM_HERE);
+}
+
+IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedTest,
+                       DoesNotCachePageWithEmbeddedPdf) {
+  const auto tag = GetParam();
+  const auto page_with_pdf = base::StringPrintf(
+      "/back_forward_cache/page_with_%s_pdf.html", tag.c_str());
+
+  // Navigate to A, a page with embedded PDF.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", page_with_pdf)));
+  ASSERT_TRUE(pdf_extension_test_util::EnsurePDFHasLoaded(
+      web_contents(), /*wait_for_hit_test_data=*/true, tag));
+  content::RenderFrameHostWrapper rfh_a(current_frame_host());
+
+  // Navigate to B.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", "/title2.html")));
+
+  // Verify A is NOT stored in the BackForwardCache.
+  EXPECT_NE(rfh_a->GetLifecycleState(),
+            content::RenderFrameHost::LifecycleState::kInBackForwardCache);
+
+  // Navigate back to A.
+  ASSERT_TRUE(content::HistoryGoBack(web_contents()));
+  // Verify A is not restored from BackForwardCache. Loading PDF plugins
+  // in chrome actually creates a nested WebContents which takes precedent over
+  // the blocklisted feature kContainsPlugins.
+  ExpectNotRestoredReasonHaveInnerContents(FROM_HERE);
+}
+
+IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedTest,
+                       DoesNotCachePageWithEmbeddedPdfAppendedOnPageLoaded) {
+  const auto tag = GetParam();
+
+  // Navigate to A.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", "/title1.html")));
+  content::RenderFrameHostWrapper rfh_a(current_frame_host());
+  //  Embed a PDF into A, and wait until PDF is loaded.
+  ASSERT_TRUE(content::ExecJs(
+      rfh_a.get(), content::JsReplace(R"(
+    new Promise(async resolve => {
+      let el = document.createElement($1);
+      el.type = 'application/pdf';
+      el[$2] = '/pdf/test.pdf';
+      el.onload = e => resolve();
+      document.body.append(el);
+    });
+  )",
+                                      tag, GetSrcAttributeForTag(tag))));
+
+  // Navigate to B.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", "/title2.html")));
+
+  // Verify A is NOT stored in the BackForwardCache.
+  EXPECT_NE(rfh_a->GetLifecycleState(),
+            content::RenderFrameHost::LifecycleState::kInBackForwardCache);
+
+  //  Navigate back to A.
+  ASSERT_TRUE(content::HistoryGoBack(web_contents()));
+  // Verify A is not restored from BackForwardCache. Loading PDF plugins
+  // in chrome actually creates a nested WebContents which takes precedent over
+  // the blocklisted feature kContainsPlugins.
+  ExpectNotRestoredReasonHaveInnerContents(FROM_HERE);
+}
+
+IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedTest,
+                       DoesCachePageWithEmbeddedHtml) {
+  const auto tag = GetParam();
+  const auto page_with_html = base::StringPrintf(
+      "/back_forward_cache/page_with_%s_html.html", tag.c_str());
+
+  // Navigate to A, a page with embedded HTML.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", page_with_html)));
+  content::RenderFrameHostWrapper rfh_a(current_frame_host());
+
+  // Navigate to B.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", "/title2.html")));
+
+  // Verify A is stored in the BackForwardCache.
+  EXPECT_EQ(rfh_a->GetLifecycleState(),
+            content::RenderFrameHost::LifecycleState::kInBackForwardCache);
+}
+
+IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedTest,
+                       DoesNotCachePageWithEmbeddedHtmlMutatedIntoPdf) {
+  const auto tag = GetParam();
+  const auto page_with_html = base::StringPrintf(
+      "/back_forward_cache/page_with_%s_html.html", tag.c_str());
+
+  // Navigate to A, a page with embedded HTML.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", page_with_html)));
+  content::RenderFrameHostWrapper rfh_a(current_frame_host());
+  //  Mutate the embed into PDF, and wait until PDF is loaded.
+  ASSERT_TRUE(content::ExecJs(
+      rfh_a.get(), content::JsReplace(R"(
+    new Promise(async resolve => {
+      let el = document.getElementById($1);
+      el.type = 'application/pdf';
+      el[$2] = '/pdf/test.pdf';
+      el.onload = e => resolve();
+    });
+  )",
+                                      tag, GetSrcAttributeForTag(tag))));
+
+  // Navigate to B.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", "/title2.html")));
+
+  // Verify A is NOT stored in the BackForwardCache.
+  EXPECT_NE(rfh_a->GetLifecycleState(),
+            content::RenderFrameHost::LifecycleState::kInBackForwardCache);
+
+  // Navigate back to A.
+  ASSERT_TRUE(content::HistoryGoBack(web_contents()));
+  // Verify A is not restored from BackForwardCache. Loading PDF plugins
+  // in chrome actually creates a nested WebContents which takes precedent over
+  // the blocklisted feature kContainsPlugins.
+  ExpectNotRestoredReasonHaveInnerContents(FROM_HERE);
+}
+
+IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedTest,
+                       DoesCachePageWithEmbeddedPdfMutatedIntoHtml) {
+  const auto tag = GetParam();
+  const auto page_with_pdf = base::StringPrintf(
+      "/back_forward_cache/page_with_%s_pdf.html", tag.c_str());
+
+  // Navigate to A, a page with embedded PDF.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", page_with_pdf)));
+  content::RenderFrameHostWrapper rfh_a(current_frame_host());
+  //  Mutate the embed into HTML, and wait until HTML is loaded.
+  ASSERT_TRUE(content::ExecJs(
+      rfh_a.get(), content::JsReplace(R"(
+    new Promise(async resolve => {
+      let el = document.getElementById($1);
+      el.type = 'text/html';
+      el[$2] = '/title1.html';
+      el.onload = e => resolve();
+    });
+  )",
+                                      tag, GetSrcAttributeForTag(tag))));
+
+  // Navigate to B.
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents(), embedded_test_server()->GetURL("a.com", "/title2.html")));
+
+  // Verify A is stored in the BackForwardCache.
+  EXPECT_EQ(rfh_a->GetLifecycleState(),
+            content::RenderFrameHost::LifecycleState::kInBackForwardCache);
+}
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc
index 9f15dccc..d924bb5 100644
--- a/chrome/browser/chrome_browser_main_win.cc
+++ b/chrome/browser/chrome_browser_main_win.cc
@@ -47,10 +47,12 @@
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
 #include "chrome/browser/about_flags.h"
+#include "chrome/browser/browser_features.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/enterprise/browser_management/management_service_factory.h"
 #include "chrome/browser/enterprise/util/critical_policy_section_metrics_win.h"
 #include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/os_crypt/app_bound_encryption_metrics_win.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_shortcut_manager.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.h"
@@ -651,6 +653,12 @@
   content::GetUIThreadTaskRunner({})->PostDelayedTask(
       FROM_HERE, base::BindOnce(&DetectFaultTolerantHeap), base::Minutes(1));
 
+  // Query feature first, to include full population in field trial.
+  if (base::FeatureList::IsEnabled(features::kAppBoundEncryptionMetrics) &&
+      install_static::IsSystemInstall()) {
+    os_crypt::MeasureAppBoundEncryptionStatus(g_browser_process->local_state());
+  }
+
   // Record Processor Metrics. This is very low priority, hence posting as
   // BEST_EFFORT to start after Chrome startup has completed. This metric is
   // only available starting Windows 10.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 9ead8957..f61d18f 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2571,13 +2571,6 @@
       command_line);
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
-  // TODO(https://crbug.com/1316129): Re-enable for Lacros.
-  // Processes may only query perf_event_open with the BPF sandbox disabled.
-  if (browser_command_line.HasSwitch(switches::kEnableThreadInstructionCount) &&
-      command_line->HasSwitch(sandbox::policy::switches::kNoSandbox)) {
-    command_line->AppendSwitch(switches::kEnableThreadInstructionCount);
-  }
-
   // Opt into a hardened stack canary mitigation if it hasn't already been
   // force-disabled.
   if (!browser_command_line.HasSwitch(switches::kChangeStackGuardOnFork)) {
@@ -5979,8 +5972,7 @@
   switch (user_agent_reduction) {
     case embedder_support::UserAgentReductionEnterprisePolicyState::
         kForceDisabled:
-      return embedder_support::GetFullUserAgent(force_major_version_to_minor,
-                                                user_agent_reduction);
+      return embedder_support::GetFullUserAgent(force_major_version_to_minor);
     case embedder_support::UserAgentReductionEnterprisePolicyState::
         kForceEnabled:
       return embedder_support::GetReducedUserAgent(
diff --git a/chrome/browser/chrome_worker_browsertest.cc b/chrome/browser/chrome_worker_browsertest.cc
index 8aed6bf..20121f3 100644
--- a/chrome/browser/chrome_worker_browsertest.cc
+++ b/chrome/browser/chrome_worker_browsertest.cc
@@ -249,6 +249,17 @@
     expected_request_urls_ = expected_request_urls;
   }
 
+  // Return |true| in the two conditions: 1) if the user agent minor version
+  // matches "0.0.0" and we expect the user agent to be reduced in UAReduction
+  // origin trial. 2) if the user agent minor version doesn't match "0.0.0" and
+  // we don't expect the user agent to be reduced in UAReduction origin trial.
+  // Otherwise, return false. We should not always expect reduced UA when
+  // kReduceUserAgentMinorVersion feature turns on, it would give false positive
+  // test results when the feature turns on as default. For example, if we
+  // expect full UA in the UADeprecation origin trial with
+  // kReduceUserAgentMinorVersion turned on, the actual value gives reduced UA,
+  // and the validation will succeed in this case which causes us to ignore
+  // actual bugs in code.
   void CheckUserAgentString(const std::string& user_agent_value,
                             const bool expected_user_agent_reduced) {
     // A regular expression that matches Chrome/{major_version}.{minor_version}
@@ -257,13 +268,6 @@
         "Chrome/[0-9]+\\.([0-9]+\\.[0-9]+\\.[0-9]+)";
     // The minor version in the reduced UA string is always "0.0.0".
     static constexpr char kReducedMinorVersion[] = "0.0.0";
-    // The minor version in the ReduceUserAgentMinorVersion experiment is always
-    // "0.X.0", where X is the frozen build version.
-    const std::string kReduceUserAgentMinorVersion =
-        "0." +
-        std::string(
-            blink::features::kUserAgentFrozenBuildVersion.Get().data()) +
-        ".0";
 
     std::string minor_version;
     EXPECT_TRUE(re2::RE2::PartialMatch(user_agent_value, kChromeVersionRegex,
@@ -271,9 +275,6 @@
 
     if (expected_user_agent_reduced) {
       EXPECT_EQ(minor_version, kReducedMinorVersion);
-    } else if (base::FeatureList::IsEnabled(
-                   blink::features::kReduceUserAgentMinorVersion)) {
-      EXPECT_EQ(minor_version, kReduceUserAgentMinorVersion);
     } else {
       EXPECT_NE(minor_version, kReducedMinorVersion);
     }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 70cf391f..8d67506 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -274,6 +274,8 @@
     "//chromeos/ash/components/dbus/system_proxy:system_proxy_proto",
     "//chromeos/ash/components/dbus/typecd",
     "//chromeos/ash/components/dbus/upstart",
+    "//chromeos/ash/components/dbus/userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/ash/components/hibernate:buildflags",
     "//chromeos/ash/components/memory",
     "//chromeos/ash/components/network/portal_detector",
@@ -281,6 +283,9 @@
     "//chromeos/ash/components/scanning",
     "//chromeos/ash/services/assistant:lib",
     "//chromeos/ash/services/assistant/public/cpp",
+    "//chromeos/ash/services/cros_healthd/private/cpp",
+    "//chromeos/ash/services/cros_healthd/public/cpp",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_browser",
     "//chromeos/components/disks:prefs",
     "//chromeos/components/feature_usage",
@@ -340,8 +345,6 @@
     "//chromeos/dbus/u2f:u2f_proto",
     "//chromeos/dbus/update_engine",
     "//chromeos/dbus/update_engine:proto",
-    "//chromeos/dbus/userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus/util",
     "//chromeos/dbus/virtual_file_provider",
     "//chromeos/dbus/vm_plugin_dispatcher",
@@ -353,9 +356,6 @@
     "//chromeos/network",
     "//chromeos/printing",
     "//chromeos/services/bluetooth_config:in_process_bluetooth_config",
-    "//chromeos/services/cros_healthd/private/cpp",
-    "//chromeos/services/cros_healthd/public/cpp",
-    "//chromeos/services/cros_healthd/public/mojom",
     "//chromeos/services/machine_learning/public/cpp",
     "//chromeos/services/machine_learning/public/mojom",
     "//chromeos/services/network_config:in_process_instance",
@@ -1545,6 +1545,8 @@
     "../ash/web_applications/os_url_handler_system_web_app_info.h",
     "../ash/web_applications/personalization_app/enterprise_policy_delegate_impl.cc",
     "../ash/web_applications/personalization_app/enterprise_policy_delegate_impl.h",
+    "../ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.cc",
+    "../ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.h",
     "../ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc",
     "../ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.h",
     "../ash/web_applications/personalization_app/personalization_app_keyboard_backlight_provider_impl.cc",
@@ -1937,6 +1939,7 @@
       "../ash/chromebox_for_meetings/service_adaptor.h",
     ]
     deps += [
+      "//ash/components/hid_detection:hid_detection",
       "//ash/services/chromebox_for_meetings/public/cpp",
       "//ash/services/chromebox_for_meetings/public/mojom",
       "//chromeos/ash/components/chromebox_for_meetings",
@@ -2189,14 +2192,14 @@
     "//chromeos/ash/components/dbus/concierge",
     "//chromeos/ash/components/dbus/seneschal",
     "//chromeos/ash/components/dbus/session_manager",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/chunneld",
     "//chromeos/dbus/cros_disks",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
     "//chromeos/dbus/dlcservice",
-    "//chromeos/dbus/userdataauth:userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//chromeos/printing",
     "//chromeos/system",
     "//components/crx_file",
@@ -2331,6 +2334,7 @@
     "../ash/arc/privacy_items/arc_privacy_items_bridge_unittest.cc",
     "../ash/arc/process/arc_process_unittest.cc",
     "../ash/arc/session/arc_demo_mode_preference_handler_unittest.cc",
+    "../ash/arc/session/arc_disk_space_monitor_unittest.cc",
     "../ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc",
     "../ash/arc/session/arc_provisioning_result_unittest.cc",
     "../ash/arc/session/arc_session_manager_unittest.cc",
@@ -2469,10 +2473,12 @@
     "../ash/file_manager/copy_or_move_io_task_unittest.cc",
     "../ash/file_manager/delete_io_task_unittest.cc",
     "../ash/file_manager/documents_provider_root_manager_unittest.cc",
+    "../ash/file_manager/empty_trash_io_task_unittest.cc",
     "../ash/file_manager/file_tasks_notifier_unittest.cc",
     "../ash/file_manager/file_tasks_unittest.cc",
     "../ash/file_manager/file_watcher_unittest.cc",
     "../ash/file_manager/fileapi_util_unittest.cc",
+    "../ash/file_manager/fusebox_moniker_unittest.cc",
     "../ash/file_manager/guest_os_file_tasks_unittest.cc",
     "../ash/file_manager/io_task_controller_unittest.cc",
     "../ash/file_manager/path_util_unittest.cc",
@@ -2529,6 +2535,7 @@
     "../ash/guest_os/guest_id_unittest.cc",
     "../ash/guest_os/guest_os_diagnostics_builder_unittest.cc",
     "../ash/guest_os/guest_os_external_protocol_handler_unittest.cc",
+    "../ash/guest_os/guest_os_file_watcher_unittest.cc",
     "../ash/guest_os/guest_os_mime_types_service_unittest.cc",
     "../ash/guest_os/guest_os_registry_service_unittest.cc",
     "../ash/guest_os/guest_os_share_path_unittest.cc",
@@ -3157,6 +3164,7 @@
     "//chromeos/ash/components/dbus/session_manager",
     "//chromeos/ash/components/dbus/system_clock",
     "//chromeos/ash/components/dbus/upstart",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/ash/components/network/portal_detector:test_support",
     "//chromeos/ash/components/scanning",
     "//chromeos/components/sensors:test_support",
@@ -3183,7 +3191,6 @@
     "//chromeos/login/login_state",
     "//chromeos/login/login_state:test_support",
     "//chromeos/network",
-    "//chromeos/network:test_support",
     "//chromeos/services/machine_learning/public/cpp:stub",
     "//chromeos/system",
     "//chromeos/ui/frame:test_support",
diff --git a/chrome/browser/chromeos/app_mode/chrome_kiosk_app_launcher_unittest.cc b/chrome/browser/chromeos/app_mode/chrome_kiosk_app_launcher_unittest.cc
index 51bad11..e12bb4c 100644
--- a/chrome/browser/chromeos/app_mode/chrome_kiosk_app_launcher_unittest.cc
+++ b/chrome/browser/chromeos/app_mode/chrome_kiosk_app_launcher_unittest.cc
@@ -58,10 +58,9 @@
                                   const extensions::Event& event) override {
     ASSERT_EQ(event.event_name,
               extensions::api::app_runtime::OnLaunched::kEventName);
-    ASSERT_TRUE(event.event_args);
-    ASSERT_EQ(1u, event.event_args->GetListDeprecated().size());
+    ASSERT_EQ(1u, event.event_args.size());
 
-    const base::Value& launch_data = event.event_args->GetListDeprecated()[0];
+    const base::Value& launch_data = event.event_args[0];
     const base::Value* is_kiosk_session =
         launch_data.FindKeyOfType("isKioskSession", base::Value::Type::BOOLEAN);
     ASSERT_TRUE(is_kiosk_session);
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc
index c46ff0d8..f5ef28dc 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc
@@ -26,11 +26,11 @@
 #include "chrome/browser/ash/arc/tracing/arc_app_performance_tracing_session.h"
 #include "chrome/browser/ash/arc/tracing/arc_app_performance_tracing_test_helper.h"
 #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_prefs.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "components/feature_engagement/public/feature_constants.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
@@ -396,12 +396,12 @@
  public:
   AutotestPrivateSystemWebAppsTest() {
     installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
+        ash::TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
   }
   ~AutotestPrivateSystemWebAppsTest() override = default;
 
  private:
-  std::unique_ptr<web_app::TestSystemWebAppInstallation> installation_;
+  std::unique_ptr<ash::TestSystemWebAppInstallation> installation_;
 };
 
 // TODO(crbug.com/1201545): Fix flakiness.
diff --git a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.h b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.h
index 43fe68a..b1acb09 100644
--- a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router.h
@@ -96,7 +96,7 @@
   virtual void BroadcastEvent(
       extensions::events::HistogramValue histogram_value,
       const std::string& event_name,
-      std::vector<base::Value> event_args) = 0;
+      base::Value::List event_args) = 0;
 
   static extensions::api::file_manager_private::FileTransferStatus
   CreateFileTransferStatus(
diff --git a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router_unittest.cc
index 5e6bd82..6404455 100644
--- a/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router_unittest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/drivefs_event_router_unittest.cc
@@ -83,7 +83,7 @@
 
   void BroadcastEvent(extensions::events::HistogramValue histogram_value,
                       const std::string& event_name,
-                      std::vector<base::Value> event_args) override {
+                      base::Value::List event_args) override {
     BroadcastEventImpl(event_name, base::Value(std::move(event_args)));
   }
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index ba96eb99..86f446dd 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -125,7 +125,7 @@
 void BroadcastEvent(Profile* profile,
                     extensions::events::HistogramValue histogram_value,
                     const std::string& event_name,
-                    std::vector<base::Value> event_args) {
+                    base::Value::List event_args) {
   extensions::EventRouter::Get(profile)->BroadcastEvent(
       std::make_unique<extensions::Event>(histogram_value, event_name,
                                           std::move(event_args)));
@@ -138,7 +138,7 @@
     const std::string& extension_id,
     extensions::events::HistogramValue histogram_value,
     const std::string& event_name,
-    std::vector<base::Value> event_args) {
+    base::Value::List event_args) {
   extensions::EventRouter::Get(profile)->DispatchEventToExtension(
       extension_id, std::make_unique<extensions::Event>(
                         histogram_value, event_name, std::move(event_args)));
@@ -419,7 +419,7 @@
 
   void BroadcastEvent(extensions::events::HistogramValue histogram_value,
                       const std::string& event_name,
-                      std::vector<base::Value> event_args) override {
+                      base::Value::List event_args) override {
     std::unique_ptr<extensions::Event> event =
         std::make_unique<extensions::Event>(histogram_value, event_name,
                                             std::move(event_args));
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/event_router_unittest.cc
index 83105c8..7e292f65 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router_unittest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router_unittest.cc
@@ -173,16 +173,15 @@
 // extract the "outputs" key. It then looks at the output at `index` and matches
 // the `field` against the `expected_value`.
 MATCHER_P3(ExpectEventArgString, index, field, expected_value, "") {
-  EXPECT_EQ((*arg).type(), base::Value::Type::LIST)
-      << "Supplied value must be of type LIST";
-  EXPECT_GE((*arg).GetList().size(), 1);
-  base::Value* outputs =
-      (*arg).GetList()[0].FindKeyOfType("outputs", base::Value::Type::LIST);
+  EXPECT_GE(arg.size(), 1);
+  const base::Value* outputs =
+      arg[0].FindKeyOfType("outputs", base::Value::Type::LIST);
   EXPECT_TRUE(outputs) << "The outputs field is not available on the event";
   EXPECT_GT((*outputs).GetList().size(), index)
       << "The supplied index on outputs is not available, size: "
       << (*outputs).GetList().size() << ", index: " << index;
-  std::string* actual_value = (*outputs).GetList()[index].FindStringKey(field);
+  const std::string* actual_value =
+      (*outputs).GetList()[index].FindStringKey(field);
   EXPECT_TRUE(actual_value) << "Could not find the string with key: " << field;
   return testing::ExplainMatchResult(expected_value, *actual_value,
                                      result_listener);
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 2197db6..5da9af8d 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
@@ -36,11 +36,13 @@
 #include "chrome/browser/ash/drive/file_system_util.h"
 #include "chrome/browser/ash/file_manager/copy_or_move_io_task.h"
 #include "chrome/browser/ash/file_manager/delete_io_task.h"
+#include "chrome/browser/ash/file_manager/empty_trash_io_task.h"
 #include "chrome/browser/ash/file_manager/extract_io_task.h"
 #include "chrome/browser/ash/file_manager/file_manager_copy_or_move_hook_delegate.h"
 #include "chrome/browser/ash/file_manager/fileapi_util.h"
 #include "chrome/browser/ash/file_manager/io_task.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
+#include "chrome/browser/ash/file_manager/restore_io_task.h"
 #include "chrome/browser/ash/file_manager/trash_io_task.h"
 #include "chrome/browser/ash/file_manager/volume_manager.h"
 #include "chrome/browser/ash/file_manager/zip_io_task.h"
@@ -402,10 +404,14 @@
       return file_manager::io_task::OperationType::kCopy;
     case api::file_manager_private::IO_TASK_TYPE_DELETE:
       return file_manager::io_task::OperationType::kDelete;
+    case api::file_manager_private::IO_TASK_TYPE_EMPTY_TRASH:
+      return file_manager::io_task::OperationType::kEmptyTrash;
     case api::file_manager_private::IO_TASK_TYPE_EXTRACT:
       return file_manager::io_task::OperationType::kExtract;
     case api::file_manager_private::IO_TASK_TYPE_MOVE:
       return file_manager::io_task::OperationType::kMove;
+    case api::file_manager_private::IO_TASK_TYPE_RESTORE:
+      return file_manager::io_task::OperationType::kRestore;
     case api::file_manager_private::IO_TASK_TYPE_TRASH:
       return file_manager::io_task::OperationType::kTrash;
     case api::file_manager_private::IO_TASK_TYPE_ZIP:
@@ -1619,6 +1625,14 @@
     }
   }
 
+  std::vector<std::string> restore_paths;
+  if (base::FeatureList::IsEnabled(chromeos::features::kFilesTrash) &&
+      params->params.restore_paths) {
+    for (const auto& path : *params->params.restore_paths) {
+      restore_paths.emplace_back(path);
+    }
+  }
+
   std::unique_ptr<file_manager::io_task::IOTask> task;
   switch (type.value()) {
     case file_manager::io_task::OperationType::kCopy:
@@ -1636,6 +1650,29 @@
       task = std::make_unique<file_manager::io_task::DeleteIOTask>(
           std::move(source_urls), file_system_context);
       break;
+    case file_manager::io_task::OperationType::kEmptyTrash:
+      if (base::FeatureList::IsEnabled(chromeos::features::kFilesTrash)) {
+        task = std::make_unique<file_manager::io_task::EmptyTrashIOTask>(
+            blink::StorageKey(render_frame_host()->GetLastCommittedOrigin()),
+            profile, file_system_context,
+            /*base_path=*/base::FilePath());
+        break;
+      } else {
+        return RespondNow(Error("Invalid operation type"));
+      }
+    case file_manager::io_task::OperationType::kRestore:
+      if (base::FeatureList::IsEnabled(chromeos::features::kFilesTrash)) {
+        if (source_urls.size() != restore_paths.size()) {
+          return RespondNow(Error("Invalid number of restore paths"));
+        }
+        task = std::make_unique<file_manager::io_task::RestoreIOTask>(
+            std::move(source_urls), std::move(restore_paths), profile,
+            file_system_context,
+            /*base_path=*/base::FilePath());
+        break;
+      } else {
+        return RespondNow(Error("Invalid operation type"));
+      }
     case file_manager::io_task::OperationType::kTrash:
       if (base::FeatureList::IsEnabled(chromeos::features::kFilesTrash)) {
         task = std::make_unique<file_manager::io_task::TrashIOTask>(
diff --git a/chrome/browser/chromeos/extensions/file_manager/system_notification_manager.cc b/chrome/browser/chromeos/extensions/file_manager/system_notification_manager.cc
index 9a52d87..a8f16ef89 100644
--- a/chrome/browser/chromeos/extensions/file_manager/system_notification_manager.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/system_notification_manager.cc
@@ -367,7 +367,7 @@
 std::unique_ptr<message_center::Notification>
 SystemNotificationManager::MakeDriveSyncErrorNotification(
     const extensions::Event& event,
-    base::Value::ListView& event_arguments) {
+    const base::Value::List& event_arguments) {
   std::unique_ptr<message_center::Notification> notification;
   file_manager_private::DriveSyncErrorEvent sync_error;
   const char* id;
@@ -440,7 +440,7 @@
 std::unique_ptr<message_center::Notification>
 SystemNotificationManager::MakeDriveConfirmDialogNotification(
     const extensions::Event& event,
-    base::Value::ListView& event_arguments) {
+    const base::Value::List& event_arguments) {
   std::unique_ptr<message_center::Notification> notification;
   file_manager_private::DriveConfirmDialogEvent dialog_event;
   std::u16string title =
@@ -473,7 +473,7 @@
 std::unique_ptr<message_center::Notification>
 SystemNotificationManager::UpdateDriveSyncNotification(
     const extensions::Event& event,
-    base::Value::ListView& event_arguments) {
+    const base::Value::List& event_arguments) {
   std::unique_ptr<message_center::Notification> notification;
   file_manager_private::FileTransferStatus transfer_status;
   if (!file_manager_private::FileTransferStatus::Populate(event_arguments[0],
@@ -529,9 +529,7 @@
   if (!swa_enabled_) {
     return;
   }
-  base::Value::ListView event_arguments;
-
-  event_arguments = event.event_args->GetListDeprecated();
+  const base::Value::List& event_arguments = event.event_args;
   if (event_arguments.size() < 1) {
     return;
   }
diff --git a/chrome/browser/chromeos/extensions/file_manager/system_notification_manager.h b/chrome/browser/chromeos/extensions/file_manager/system_notification_manager.h
index 42e5fa90..564e6560 100644
--- a/chrome/browser/chromeos/extensions/file_manager/system_notification_manager.h
+++ b/chrome/browser/chromeos/extensions/file_manager/system_notification_manager.h
@@ -235,7 +235,7 @@
    */
   std::unique_ptr<message_center::Notification> MakeDriveSyncErrorNotification(
       const extensions::Event& event,
-      base::Value::ListView& event_arguments);
+      const base::Value::List& event_arguments);
 
   /**
    * Click handler for the Drive offline confirmation dialog notification.
@@ -247,7 +247,7 @@
    */
   std::unique_ptr<message_center::Notification>
   MakeDriveConfirmDialogNotification(const extensions::Event& event,
-                                     base::Value::ListView& event_arguments);
+                                     const base::Value::List& event_arguments);
 
   /**
    * Update/remove Drive sync progress notification.
@@ -257,7 +257,7 @@
    */
   std::unique_ptr<message_center::Notification> UpdateDriveSyncNotification(
       const extensions::Event& event,
-      base::Value::ListView& event_arguments);
+      const base::Value::List& event_arguments);
 
   /**
    * Click handler for the removable device notification.
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_apitest.cc b/chrome/browser/chromeos/extensions/login_screen/login/login_apitest.cc
index 1a78c51..fef0a14 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/login_apitest.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/login_apitest.cc
@@ -25,8 +25,8 @@
 #include "chrome/browser/policy/extension_force_install_mixin.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/test/policy_builder.h"
 #include "components/policy/core/common/policy_service.h"
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_ash_unittest.cc b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_ash_unittest.cc
index 41ca741..aea14ff 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_ash_unittest.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_ash_unittest.cc
@@ -62,10 +62,8 @@
   }
 
   const extensions::Event& event = *iter->second;
-  CHECK(event.event_args);
-  CHECK_EQ(1u, event.event_args->GetListDeprecated().size());
-  std::string session_state =
-      (event.event_args->GetListDeprecated())[0].GetString();
+  CHECK_EQ(1u, event.event_args.size());
+  std::string session_state = event.event_args[0].GetString();
   return extensions::api::login_state::ParseSessionState(session_state) ==
          expected_state;
 }
diff --git a/chrome/browser/chromeos/extensions/printing_metrics/print_job_finished_event_dispatcher_unittest.cc b/chrome/browser/chromeos/extensions/printing_metrics/print_job_finished_event_dispatcher_unittest.cc
index 7b25c01..095d9e9 100644
--- a/chrome/browser/chromeos/extensions/printing_metrics/print_job_finished_event_dispatcher_unittest.cc
+++ b/chrome/browser/chromeos/extensions/printing_metrics/print_job_finished_event_dispatcher_unittest.cc
@@ -35,14 +35,13 @@
     return nullptr;
 
   const extensions::Event& event = *iter->second;
-  if (!event.event_args || !event.event_args->is_list() ||
-      event.event_args->GetList().size() != 1u) {
+  if (event.event_args.size() != 1u) {
     ADD_FAILURE() << "Invalid event args";
     return nullptr;
   }
 
   return extensions::api::printing_metrics::PrintJobInfo::FromValue(
-      event.event_args->GetList()[0]);
+      event.event_args[0]);
 }
 
 // Creates a new MockPrintJobHistoryService for the given |context|.
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/BUILD.gn b/chrome/browser/chromeos/extensions/telemetry/api/BUILD.gn
index 52bbac4..b3f9644 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/BUILD.gn
+++ b/chrome/browser/chromeos/extensions/telemetry/api/BUILD.gn
@@ -77,14 +77,15 @@
   deps = [
     ":api",
     ":fake_hardware_info_delegate",
+    "//ash/webui/telemetry_extension_ui/services:telemetry_services",
     "//base",
     "//chrome/browser/ash/wilco_dtc_supportd:mojo_utils",
     "//chrome/common/chromeos/extensions",
     "//chrome/test:test_support",
+    "//chromeos/ash/services/cros_healthd/public/cpp",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//chromeos/dbus",
     "//chromeos/dbus/debug_daemon",
-    "//chromeos/services/cros_healthd/public/cpp",
-    "//chromeos/services/cros_healthd/public/mojom",
     "//components/user_manager",
     "//extensions:test_support",
     "//extensions/browser",
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/diagnostics_api_browsertest.cc b/chrome/browser/chromeos/extensions/telemetry/api/diagnostics_api_browsertest.cc
index 07e043f..ac5eb1e 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/diagnostics_api_browsertest.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/diagnostics_api_browsertest.cc
@@ -4,8 +4,8 @@
 
 #include "chrome/browser/ash/wilco_dtc_supportd/mojo_utils.h"
 #include "chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/hardware_info_delegate.cc b/chrome/browser/chromeos/extensions/telemetry/api/hardware_info_delegate.cc
index e241412..0463aa02 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/hardware_info_delegate.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/hardware_info_delegate.cc
@@ -81,7 +81,8 @@
 HardwareInfoDelegate::Factory::~Factory() = default;
 
 HardwareInfoDelegate::HardwareInfoDelegate()
-    : probe_service_(remote_probe_service_.BindNewPipeAndPassReceiver()) {}
+    : probe_service_(ash::ProbeService::Factory::Create(
+          remote_probe_service_.BindNewPipeAndPassReceiver())) {}
 
 HardwareInfoDelegate::~HardwareInfoDelegate() {
   remote_probe_service_.reset();
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/hardware_info_delegate.h b/chrome/browser/chromeos/extensions/telemetry/api/hardware_info_delegate.h
index 8931465..80bf985 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/hardware_info_delegate.h
+++ b/chrome/browser/chromeos/extensions/telemetry/api/hardware_info_delegate.h
@@ -49,7 +49,7 @@
                        std::string probe_service_result);
 
   mojo::Remote<ash::health::mojom::ProbeService> remote_probe_service_;
-  ash::ProbeService probe_service_;
+  std::unique_ptr<ash::health::mojom::ProbeService> probe_service_;
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc
index 407f853..4cc7690 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc
@@ -10,6 +10,7 @@
 #include <string>
 #include <utility>
 
+#include "ash/webui/telemetry_extension_ui/services/probe_service.h"
 #include "base/bind.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.h"
@@ -18,8 +19,12 @@
 
 namespace chromeos {
 
+// TelemetryApiFunctionBase ----------------------------------------------------
+
 TelemetryApiFunctionBase::TelemetryApiFunctionBase()
-    : probe_service_(remote_probe_service_.BindNewPipeAndPassReceiver()) {}
+    : probe_service_(ash::ProbeService::Factory::Create(
+          remote_probe_service_.BindNewPipeAndPassReceiver())) {}
+
 TelemetryApiFunctionBase::~TelemetryApiFunctionBase() = default;
 
 // OsTelemetryGetBatteryInfoFunction -------------------------------------------
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h
index c1c09f3..99be601b 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h
+++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h
@@ -5,8 +5,9 @@
 #ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_TELEMETRY_API_TELEMETRY_API_H_
 #define CHROME_BROWSER_CHROMEOS_EXTENSIONS_TELEMETRY_API_TELEMETRY_API_H_
 
+#include <memory>
+
 #include "ash/webui/telemetry_extension_ui/mojom/probe_service.mojom.h"
-#include "ash/webui/telemetry_extension_ui/services/probe_service.h"
 #include "chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_api_guard_function.h"
 #include "extensions/browser/extension_function.h"
 #include "extensions/browser/extension_function_histogram_value.h"
@@ -27,7 +28,7 @@
   mojo::Remote<ash::health::mojom::ProbeService> remote_probe_service_;
 
  private:
-  ash::ProbeService probe_service_;
+  std::unique_ptr<ash::health::mojom::ProbeService> probe_service_;
 };
 
 class OsTelemetryGetBatteryInfoFunction : public TelemetryApiFunctionBase {
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc
index c8557a6..6e4e903 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc
@@ -5,18 +5,34 @@
 #include <string>
 #include <utility>
 
+#include "ash/webui/telemetry_extension_ui/services/fake_probe_service.h"
+#include "ash/webui/telemetry_extension_ui/services/probe_service.h"
 #include "chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
 
-using TelemetryExtensionTelemetryApiBrowserTest =
-    BaseTelemetryExtensionBrowserTest;
+class TelemetryExtensionTelemetryApiBrowserTest
+    : public BaseTelemetryExtensionBrowserTest {
+ public:
+  TelemetryExtensionTelemetryApiBrowserTest() {
+    ash::ProbeService::Factory::SetForTesting(&fake_probe_factory_);
+  }
+  ~TelemetryExtensionTelemetryApiBrowserTest() override = default;
+
+  TelemetryExtensionTelemetryApiBrowserTest(
+      const TelemetryExtensionTelemetryApiBrowserTest&) = delete;
+  TelemetryExtensionTelemetryApiBrowserTest& operator=(
+      const TelemetryExtensionTelemetryApiBrowserTest&) = delete;
+
+ protected:
+  ash::FakeProbeService::Factory fake_probe_factory_;
+};
 
 namespace {
 
@@ -47,39 +63,49 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(
+      fake_probe_factory_.GetAndClearRequestedCategories(),
+      testing::ElementsAre(ash::health::mojom::ProbeCategoryEnum::kBattery));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
                        GetBatteryInfo_Success) {
   // Configure fake cros_healthd response.
   {
-    auto telemetry_info = chromeos::cros_healthd::mojom::TelemetryInfo::New();
+    auto telemetry_info = ash::health::mojom::TelemetryInfo::New();
     {
-      auto battery_info = chromeos::cros_healthd::mojom::BatteryInfo::New();
-      battery_info->cycle_count = 100000000000000;
-      battery_info->voltage_now = 1234567890.123456;
+      auto battery_info = ash::health::mojom::BatteryInfo::New();
+      battery_info->cycle_count =
+          ash::health::mojom::Int64Value::New(100000000000000);
+      battery_info->voltage_now =
+          ash::health::mojom::DoubleValue::New(1234567890.123456);
       battery_info->vendor = "Google";
       battery_info->serial_number = "abcdef";
-      battery_info->charge_full_design = 3000000000000000;
-      battery_info->charge_full = 9000000000000000;
-      battery_info->voltage_min_design = 1000000000.1001;
+      battery_info->charge_full_design =
+          ash::health::mojom::DoubleValue::New(3000000000000000);
+      battery_info->charge_full =
+          ash::health::mojom::DoubleValue::New(9000000000000000);
+      battery_info->voltage_min_design =
+          ash::health::mojom::DoubleValue::New(1000000000.1001);
       battery_info->model_name = "Google Battery";
-      battery_info->charge_now = 7777777777.777;
-      battery_info->current_now = 0.9999999999999;
+      battery_info->charge_now =
+          ash::health::mojom::DoubleValue::New(7777777777.777);
+      battery_info->current_now =
+          ash::health::mojom::DoubleValue::New(0.9999999999999);
       battery_info->technology = "Li-ion";
       battery_info->status = "Charging";
       battery_info->manufacture_date = "2020-07-30";
       battery_info->temperature =
-          chromeos::cros_healthd::mojom::NullableUint64::New(7777777777777777);
+          ash::health::mojom::UInt64Value::New(7777777777777777);
 
       telemetry_info->battery_result =
-          chromeos::cros_healthd::mojom::BatteryResult::NewBatteryInfo(
+          ash::health::mojom::BatteryResult::NewBatteryInfo(
               std::move(battery_info));
     }
 
-    ASSERT_TRUE(cros_healthd::FakeCrosHealthd::Get());
-    cros_healthd::FakeCrosHealthd::Get()
-        ->SetProbeTelemetryInfoResponseForTesting(telemetry_info);
+    fake_probe_factory_.SetProbeTelemetryInfoResponseForTesting(
+        std::move(telemetry_info));
   }
 
   CreateExtensionAndRunServiceWorker(R"(
@@ -109,6 +135,10 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(
+      fake_probe_factory_.GetAndClearRequestedCategories(),
+      testing::ElementsAre(ash::health::mojom::ProbeCategoryEnum::kBattery));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
@@ -124,76 +154,86 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(
+      fake_probe_factory_.GetAndClearRequestedCategories(),
+      testing::ElementsAre(ash::health::mojom::ProbeCategoryEnum::kCpu));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
                        GetCpuInfo_Success) {
   // Configure fake cros_healthd response.
   {
-    auto telemetry_info = cros_healthd::mojom::TelemetryInfo::New();
+    auto telemetry_info = ash::health::mojom::TelemetryInfo::New();
 
     {
-      auto c_state1 = chromeos::cros_healthd::mojom::CpuCStateInfo::New();
+      auto c_state1 = ash::health::mojom::CpuCStateInfo::New();
       c_state1->name = "C1";
-      c_state1->time_in_state_since_last_boot_us = 1125899906875957;
+      c_state1->time_in_state_since_last_boot_us =
+          ash::health::mojom::UInt64Value::New(1125899906875957);
 
-      auto c_state2 = chromeos::cros_healthd::mojom::CpuCStateInfo::New();
+      auto c_state2 = ash::health::mojom::CpuCStateInfo::New();
       c_state2->name = "C2";
-      c_state2->time_in_state_since_last_boot_us = 1125899906877777;
+      c_state2->time_in_state_since_last_boot_us =
+          ash::health::mojom::UInt64Value::New(1125899906877777);
 
-      auto logical_info1 = chromeos::cros_healthd::mojom::LogicalCpuInfo::New();
-      logical_info1->max_clock_speed_khz = 2147473647;
-      logical_info1->scaling_max_frequency_khz = 1073764046;
-      logical_info1->scaling_current_frequency_khz = 536904245;
+      auto logical_info1 = ash::health::mojom::LogicalCpuInfo::New();
+      logical_info1->max_clock_speed_khz =
+          ash::health::mojom::UInt32Value::New(2147473647);
+      logical_info1->scaling_max_frequency_khz =
+          ash::health::mojom::UInt32Value::New(1073764046);
+      logical_info1->scaling_current_frequency_khz =
+          ash::health::mojom::UInt32Value::New(536904245);
       // Idle time cannot be tested in browser test, because it requires USER_HZ
       // system constant to convert idle_time_user_hz to milliseconds.
-      logical_info1->idle_time_user_hz = 0;
+      logical_info1->idle_time_ms = ash::health::mojom::UInt64Value::New(0);
       logical_info1->c_states.push_back(std::move(c_state1));
       logical_info1->c_states.push_back(std::move(c_state2));
 
-      auto logical_info2 = chromeos::cros_healthd::mojom::LogicalCpuInfo::New();
-      logical_info2->max_clock_speed_khz = 1147494759;
-      logical_info2->scaling_max_frequency_khz = 1063764046;
-      logical_info2->scaling_current_frequency_khz = 936904246;
+      auto logical_info2 = ash::health::mojom::LogicalCpuInfo::New();
+      logical_info2->max_clock_speed_khz =
+          ash::health::mojom::UInt32Value::New(1147494759);
+      logical_info2->scaling_max_frequency_khz =
+          ash::health::mojom::UInt32Value::New(1063764046);
+      logical_info2->scaling_current_frequency_khz =
+          ash::health::mojom::UInt32Value::New(936904246);
       // Idle time cannot be tested in browser test, because it requires USER_HZ
       // system constant to convert idle_time_user_hz to milliseconds.
-      logical_info2->idle_time_user_hz = 0;
+      logical_info2->idle_time_ms = ash::health::mojom::UInt64Value::New(0);
 
-      auto physical_info1 =
-          chromeos::cros_healthd::mojom::PhysicalCpuInfo::New();
+      auto physical_info1 = ash::health::mojom::PhysicalCpuInfo::New();
       physical_info1->model_name = "i9";
       physical_info1->logical_cpus.push_back(std::move(logical_info1));
       physical_info1->logical_cpus.push_back(std::move(logical_info2));
 
-      auto logical_info3 = chromeos::cros_healthd::mojom::LogicalCpuInfo::New();
-      logical_info3->max_clock_speed_khz = 1247494759;
-      logical_info3->scaling_max_frequency_khz = 1263764046;
-      logical_info3->scaling_current_frequency_khz = 946904246;
+      auto logical_info3 = ash::health::mojom::LogicalCpuInfo::New();
+      logical_info3->max_clock_speed_khz =
+          ash::health::mojom::UInt32Value::New(1247494759);
+      logical_info3->scaling_max_frequency_khz =
+          ash::health::mojom::UInt32Value::New(1263764046);
+      logical_info3->scaling_current_frequency_khz =
+          ash::health::mojom::UInt32Value::New(946904246);
       // Idle time cannot be tested in browser test, because it requires USER_HZ
       // system constant to convert idle_time_user_hz to milliseconds.
-      logical_info3->idle_time_user_hz = 0;
+      logical_info3->idle_time_ms = ash::health::mojom::UInt64Value::New(0);
 
-      auto physical_info2 =
-          chromeos::cros_healthd::mojom::PhysicalCpuInfo::New();
+      auto physical_info2 = ash::health::mojom::PhysicalCpuInfo::New();
       physical_info2->model_name = "i9-low-powered";
       physical_info2->logical_cpus.push_back(std::move(logical_info3));
 
-      auto cpu_info = chromeos::cros_healthd::mojom::CpuInfo::New();
-      cpu_info->num_total_threads = 2147483647;
-      cpu_info->architecture =
-          chromeos::cros_healthd::mojom::CpuArchitectureEnum::kArmv7l;
+      auto cpu_info = ash::health::mojom::CpuInfo::New();
+      cpu_info->num_total_threads =
+          ash::health::mojom::UInt32Value::New(2147483647);
+      cpu_info->architecture = ash::health::mojom::CpuArchitectureEnum::kArmv7l;
       cpu_info->physical_cpus.push_back(std::move(physical_info1));
       cpu_info->physical_cpus.push_back(std::move(physical_info2));
 
       telemetry_info->cpu_result =
-          chromeos::cros_healthd::mojom::CpuResult::NewCpuInfo(
-              std::move(cpu_info));
+          ash::health::mojom::CpuResult::NewCpuInfo(std::move(cpu_info));
     }
 
-    ASSERT_TRUE(cros_healthd::FakeCrosHealthd::Get());
-
-    cros_healthd::FakeCrosHealthd::Get()
-        ->SetProbeTelemetryInfoResponseForTesting(telemetry_info);
+    fake_probe_factory_.SetProbeTelemetryInfoResponseForTesting(
+        std::move(telemetry_info));
   }
 
   CreateExtensionAndRunServiceWorker(R"(
@@ -245,6 +285,10 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(
+      fake_probe_factory_.GetAndClearRequestedCategories(),
+      testing::ElementsAre(ash::health::mojom::ProbeCategoryEnum::kCpu));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
@@ -260,30 +304,36 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(
+      fake_probe_factory_.GetAndClearRequestedCategories(),
+      testing::ElementsAre(ash::health::mojom::ProbeCategoryEnum::kMemory));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
                        GetMemoryInfo_Success) {
   // Configure fake cros_healthd response.
   {
-    auto telemetry_info = cros_healthd::mojom::TelemetryInfo::New();
+    auto telemetry_info = ash::health::mojom::TelemetryInfo::New();
 
     {
-      auto memory_info = chromeos::cros_healthd::mojom::MemoryInfo::New();
-      memory_info->total_memory_kib = 2147483647;
-      memory_info->free_memory_kib = 2147483646;
-      memory_info->available_memory_kib = 2147483645;
-      memory_info->page_faults_since_last_boot = 4611686018427388000;
+      auto memory_info = ash::health::mojom::MemoryInfo::New();
+      memory_info->total_memory_kib =
+          ash::health::mojom::UInt32Value::New(2147483647);
+      memory_info->free_memory_kib =
+          ash::health::mojom::UInt32Value::New(2147483646);
+      memory_info->available_memory_kib =
+          ash::health::mojom::UInt32Value::New(2147483645);
+      memory_info->page_faults_since_last_boot =
+          ash::health::mojom::UInt64Value::New(4611686018427388000);
 
       telemetry_info->memory_result =
-          chromeos::cros_healthd::mojom::MemoryResult::NewMemoryInfo(
+          ash::health::mojom::MemoryResult::NewMemoryInfo(
               std::move(memory_info));
     }
 
-    ASSERT_TRUE(cros_healthd::FakeCrosHealthd::Get());
-
-    cros_healthd::FakeCrosHealthd::Get()
-        ->SetProbeTelemetryInfoResponseForTesting(telemetry_info);
+    fake_probe_factory_.SetProbeTelemetryInfoResponseForTesting(
+        std::move(telemetry_info));
   }
 
   CreateExtensionAndRunServiceWorker(R"(
@@ -299,6 +349,10 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(
+      fake_probe_factory_.GetAndClearRequestedCategories(),
+      testing::ElementsAre(ash::health::mojom::ProbeCategoryEnum::kMemory));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
@@ -321,12 +375,18 @@
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
                        GetOemDataWithSerialNumberPermission_Success) {
+  {
+    auto oem_data = ash::health::mojom::OemData::New();
+    oem_data->oem_data = "123456789";
+    fake_probe_factory_.SetOemDataResponseForTesting(std::move(oem_data));
+  }
+
   CreateExtensionAndRunServiceWorker(R"(
     chrome.test.runTests([
       async function getOemData() {
         const result = await chrome.os.telemetry.getOemData();
         chrome.test.assertEq(
-          "oemdata: response from GetLog", result.oemData);
+          "123456789", result.oemData);
         chrome.test.succeed();
       }
     ]);
@@ -346,34 +406,37 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(
+      fake_probe_factory_.GetAndClearRequestedCategories(),
+      testing::ElementsAre(ash::health::mojom::ProbeCategoryEnum::kSystem));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
                        GetOsVersionInfo_Success) {
   // Configure fake cros_healthd response.
   {
-    auto telemetry_info = chromeos::cros_healthd::mojom::TelemetryInfo::New();
+    auto telemetry_info = ash::health::mojom::TelemetryInfo::New();
     {
-      auto os_version_info = cros_healthd::mojom::OsVersion::New();
+      auto os_version_info = ash::health::mojom::OsVersion::New();
       os_version_info->release_milestone = "87";
       os_version_info->build_number = "13544";
       os_version_info->patch_number = "59.0";
       os_version_info->release_channel = "stable-channel";
 
-      auto os_info = cros_healthd::mojom::OsInfo::New();
+      auto os_info = ash::health::mojom::OsInfo::New();
       os_info->os_version = std::move(os_version_info);
 
-      auto system_info_v2 = cros_healthd::mojom::SystemInfoV2::New();
-      system_info_v2->os_info = std::move(os_info);
+      auto system_info = ash::health::mojom::SystemInfo::New();
+      system_info->os_info = std::move(os_info);
 
-      telemetry_info->system_result_v2 =
-          chromeos::cros_healthd::mojom::SystemResultV2::NewSystemInfoV2(
-              std::move(system_info_v2));
+      telemetry_info->system_result =
+          ash::health::mojom::SystemResult::NewSystemInfo(
+              std::move(system_info));
     }
 
-    ASSERT_TRUE(cros_healthd::FakeCrosHealthd::Get());
-    cros_healthd::FakeCrosHealthd::Get()
-        ->SetProbeTelemetryInfoResponseForTesting(telemetry_info);
+    fake_probe_factory_.SetProbeTelemetryInfoResponseForTesting(
+        std::move(telemetry_info));
   }
 
   CreateExtensionAndRunServiceWorker(R"(
@@ -391,6 +454,10 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(
+      fake_probe_factory_.GetAndClearRequestedCategories(),
+      testing::ElementsAre(ash::health::mojom::ProbeCategoryEnum::kSystem));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
@@ -406,33 +473,31 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(fake_probe_factory_.GetAndClearRequestedCategories(),
+              std::vector<ash::health::mojom::ProbeCategoryEnum>(
+                  {ash::health::mojom::ProbeCategoryEnum::kCachedVpdData}));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
                        GetVpdInfoWithSerialNumberPermission) {
   // Configure fake cros_healthd response.
   {
-    auto telemetry_info = cros_healthd::mojom::TelemetryInfo::New();
+    auto telemetry_info = ash::health::mojom::TelemetryInfo::New();
 
     {
-      auto os_version = cros_healthd::mojom::OsVersion::New();
+      auto vpd_info = ash::health::mojom::CachedVpdInfo::New();
+      vpd_info->first_power_date = "2021-50";
+      vpd_info->model_name = "COOL-LAPTOP-CHROME";
+      vpd_info->serial_number = "5CD9132880";
+      vpd_info->sku_number = "sku15";
 
-      auto system_info = cros_healthd::mojom::SystemInfo::New();
-      system_info->first_power_date = "2021-50";
-      system_info->product_model_name = "COOL-LAPTOP-CHROME";
-      system_info->product_serial_number = "5CD9132880";
-      system_info->product_sku_number = "sku15";
-      system_info->os_version = std::move(os_version);
-
-      telemetry_info->system_result =
-          cros_healthd::mojom::SystemResult::NewSystemInfo(
-              std::move(system_info));
+      telemetry_info->vpd_result =
+          ash::health::mojom::CachedVpdResult::NewVpdInfo(std::move(vpd_info));
     }
 
-    ASSERT_TRUE(cros_healthd::FakeCrosHealthd::Get());
-
-    cros_healthd::FakeCrosHealthd::Get()
-        ->SetProbeTelemetryInfoResponseForTesting(telemetry_info);
+    fake_probe_factory_.SetProbeTelemetryInfoResponseForTesting(
+        std::move(telemetry_info));
   }
 
   CreateExtensionAndRunServiceWorker(R"(
@@ -447,6 +512,10 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(fake_probe_factory_.GetAndClearRequestedCategories(),
+              testing::ElementsAre(
+                  ash::health::mojom::ProbeCategoryEnum::kCachedVpdData));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
@@ -462,49 +531,53 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(fake_probe_factory_.GetAndClearRequestedCategories(),
+              testing::ElementsAre(
+                  ash::health::mojom::ProbeCategoryEnum::kStatefulPartition));
 }
 
 IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
                        GetStatefulPartitionInfo_Success) {
   // Configure fake cros_healthd response.
   {
-    auto telemetry_info = chromeos::cros_healthd::mojom::TelemetryInfo::New();
+    auto telemetry_info = ash::health::mojom::TelemetryInfo::New();
     {
       auto stateful_part_info =
-          chromeos::cros_healthd::mojom::StatefulPartitionInfo::New();
-      stateful_part_info->available_space = 3000000000000000;
-      stateful_part_info->total_space = 9000000000000000;
+          ash::health::mojom::StatefulPartitionInfo::New();
+      stateful_part_info->available_space =
+          ash::health::mojom::UInt64Value::New(3000000000000000);
+      stateful_part_info->total_space =
+          ash::health::mojom::UInt64Value::New(9000000000000000);
 
       telemetry_info->stateful_partition_result =
-          chromeos::cros_healthd::mojom::StatefulPartitionResult::
-              NewPartitionInfo(std::move(stateful_part_info));
+          ash::health::mojom::StatefulPartitionResult::NewPartitionInfo(
+              std::move(stateful_part_info));
     }
 
-    ASSERT_TRUE(cros_healthd::FakeCrosHealthd::Get());
-    cros_healthd::FakeCrosHealthd::Get()
-        ->SetProbeTelemetryInfoResponseForTesting(telemetry_info);
+    fake_probe_factory_.SetProbeTelemetryInfoResponseForTesting(
+        std::move(telemetry_info));
   }
 
   CreateExtensionAndRunServiceWorker(R"(
     chrome.test.runTests([
       async function getStatefulPartitionInfo() {
         const result = await chrome.os.telemetry.getStatefulPartitionInfo();
-
-        // The available space is rounded down to the next 50MB.
-        const k100 = 100 * 1024 * 1024;
-        const availableSpace = Math.floor(3000000000000000 / k100) * k100;
-
         chrome.test.assertEq(
           // The dictionary members are ordered lexicographically by the Unicode
           // codepoints that comprise their identifiers.
           {
-            availableSpace: availableSpace,
+            availableSpace: 3000000000000000,
             totalSpace: 9000000000000000,
           }, result);
         chrome.test.succeed();
       }
     ]);
   )");
+
+  EXPECT_THAT(fake_probe_factory_.GetAndClearRequestedCategories(),
+              testing::ElementsAre(
+                  ash::health::mojom::ProbeCategoryEnum::kStatefulPartition));
 }
 
 class TelemetryExtensionTelemetryApiWithoutSerialNumberBrowserTest
@@ -550,33 +623,39 @@
     GetBatteryInfoWithoutSerialNumberPermission) {
   // Configure fake cros_healthd response.
   {
-    auto telemetry_info = chromeos::cros_healthd::mojom::TelemetryInfo::New();
+    auto telemetry_info = ash::health::mojom::TelemetryInfo::New();
     {
-      auto battery_info = chromeos::cros_healthd::mojom::BatteryInfo::New();
-      battery_info->cycle_count = 100000000000000;
-      battery_info->voltage_now = 1234567890.123456;
+      auto battery_info = ash::health::mojom::BatteryInfo::New();
+      battery_info->cycle_count =
+          ash::health::mojom::Int64Value::New(100000000000000);
+      battery_info->voltage_now =
+          ash::health::mojom::DoubleValue::New(1234567890.123456);
       battery_info->vendor = "Google";
       battery_info->serial_number = "abcdef";
-      battery_info->charge_full_design = 3000000000000000;
-      battery_info->charge_full = 9000000000000000;
-      battery_info->voltage_min_design = 1000000000.1001;
+      battery_info->charge_full_design =
+          ash::health::mojom::DoubleValue::New(3000000000000000);
+      battery_info->charge_full =
+          ash::health::mojom::DoubleValue::New(9000000000000000);
+      battery_info->voltage_min_design =
+          ash::health::mojom::DoubleValue::New(1000000000.1001);
       battery_info->model_name = "Google Battery";
-      battery_info->charge_now = 7777777777.777;
-      battery_info->current_now = 0.9999999999999;
+      battery_info->charge_now =
+          ash::health::mojom::DoubleValue::New(7777777777.777);
+      battery_info->current_now =
+          ash::health::mojom::DoubleValue::New(0.9999999999999);
       battery_info->technology = "Li-ion";
       battery_info->status = "Charging";
       battery_info->manufacture_date = "2020-07-30";
       battery_info->temperature =
-          chromeos::cros_healthd::mojom::NullableUint64::New(7777777777777777);
+          ash::health::mojom::UInt64Value::New(7777777777777777);
 
       telemetry_info->battery_result =
-          chromeos::cros_healthd::mojom::BatteryResult::NewBatteryInfo(
+          ash::health::mojom::BatteryResult::NewBatteryInfo(
               std::move(battery_info));
     }
 
-    ASSERT_TRUE(cros_healthd::FakeCrosHealthd::Get());
-    cros_healthd::FakeCrosHealthd::Get()
-        ->SetProbeTelemetryInfoResponseForTesting(telemetry_info);
+    fake_probe_factory_.SetProbeTelemetryInfoResponseForTesting(
+        std::move(telemetry_info));
   }
 
   CreateExtensionAndRunServiceWorker(R"(
@@ -606,6 +685,10 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(
+      fake_probe_factory_.GetAndClearRequestedCategories(),
+      testing::ElementsAre(ash::health::mojom::ProbeCategoryEnum::kBattery));
 }
 
 IN_PROC_BROWSER_TEST_F(
@@ -630,27 +713,21 @@
     GetVpdInfoWithoutSerialNumberPermission) {
   // Configure fake cros_healthd response.
   {
-    auto telemetry_info = cros_healthd::mojom::TelemetryInfo::New();
+    auto telemetry_info = ash::health::mojom::TelemetryInfo::New();
 
     {
-      auto os_version = cros_healthd::mojom::OsVersion::New();
+      auto vpd_info = ash::health::mojom::CachedVpdInfo::New();
+      vpd_info->first_power_date = "2021-50";
+      vpd_info->model_name = "COOL-LAPTOP-CHROME";
+      vpd_info->serial_number = "5CD9132880";
+      vpd_info->sku_number = "sku15";
 
-      auto system_info = cros_healthd::mojom::SystemInfo::New();
-      system_info->first_power_date = "2021-50";
-      system_info->product_model_name = "COOL-LAPTOP-CHROME";
-      system_info->product_serial_number = "5CD9132880";
-      system_info->product_sku_number = "sku15";
-      system_info->os_version = std::move(os_version);
-
-      telemetry_info->system_result =
-          cros_healthd::mojom::SystemResult::NewSystemInfo(
-              std::move(system_info));
+      telemetry_info->vpd_result =
+          ash::health::mojom::CachedVpdResult::NewVpdInfo(std::move(vpd_info));
     }
 
-    ASSERT_TRUE(cros_healthd::FakeCrosHealthd::Get());
-
-    cros_healthd::FakeCrosHealthd::Get()
-        ->SetProbeTelemetryInfoResponseForTesting(telemetry_info);
+    fake_probe_factory_.SetProbeTelemetryInfoResponseForTesting(
+        std::move(telemetry_info));
   }
 
   CreateExtensionAndRunServiceWorker(R"(
@@ -665,6 +742,10 @@
       }
     ]);
   )");
+
+  EXPECT_THAT(fake_probe_factory_.GetAndClearRequestedCategories(),
+              testing::ElementsAre(
+                  ash::health::mojom::ProbeCategoryEnum::kCachedVpdData));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index afe649f..2e3dad0 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -235,8 +235,20 @@
     run_loop->Quit();
 }
 
-void CheckUserAgentMinorVersion(const std::string& user_agent_value,
-                                const bool expected_user_agent_reduced) {
+// Return |true| in the following conditions: If we expect reduced user agent,
+// user agent minor version matches "0.0.0" if reduced UA through UAReduction
+// origin trial. or user agent minor version matches "0.X.0" if reduced UA
+// through kReduceUserAgentMinorVersion experiment. Otherwise, return |false|.
+// We should not always expect reduced UA when kReduceUserAgentMinorVersion
+// feature turns on, it would give false positive test results when the feature
+// turns on as default. For example, if we expect full UA in the UADeprecation
+// origin trial with kReduceUserAgentMinorVersion turned on, the actual value
+// gives reduced UA, and the validation will succeed in this case which causes
+// us to ignore actual bugs in code.
+void CheckUserAgentMinorVersion(
+    const std::string& user_agent_value,
+    const bool expected_user_agent_reduced,
+    const bool expected_reduced_ua_through_experiment) {
   // A regular expression that matches Chrome/{major_version}.{minor_version}
   // in the User-Agent string, where the {minor_version} is captured.
   static constexpr char kChromeVersionRegex[] =
@@ -255,10 +267,9 @@
                                      &minor_version));
 
   if (expected_user_agent_reduced) {
-    EXPECT_EQ(minor_version, kReducedMinorVersion);
-  } else if (base::FeatureList::IsEnabled(
-                 blink::features::kReduceUserAgentMinorVersion)) {
-    EXPECT_EQ(minor_version, kReduceUserAgentMinorVersion);
+    EXPECT_EQ(minor_version, expected_reduced_ua_through_experiment
+                                 ? kReduceUserAgentMinorVersion
+                                 : kReducedMinorVersion);
   } else {
     EXPECT_NE(minor_version, kReducedMinorVersion);
   }
@@ -3598,12 +3609,15 @@
                 Optional(expected_ua_header_value));
   }
 
-  void CheckUserAgentReduced(const bool expected_user_agent_reduced) {
+  void CheckUserAgentReduced(
+      const bool expected_user_agent_reduced,
+      const bool expected_reduced_ua_through_experiment) {
     const absl::optional<std::string>& user_agent_header_value =
         GetLastUserAgentHeaderValue();
     EXPECT_TRUE(user_agent_header_value.has_value());
     CheckUserAgentMinorVersion(*user_agent_header_value,
-                               expected_user_agent_reduced);
+                               expected_user_agent_reduced,
+                               expected_reduced_ua_through_experiment);
   }
 
   // |ch_ua_reduced_expected| indicates whether expects a reduce UA string.
@@ -3615,7 +3629,19 @@
     ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
 
     CheckUaOriginTrialClientHint(ch_ua_exist_expected);
-    CheckUserAgentReduced(ch_ua_reduced_expected);
+
+    // If we expect reduced user agent, but there is no valid origin trial
+    // header, it means reduced UA depends on feature
+    // kReduceUserAgentMinorVersion experiment.
+    const bool expected_reduced_ua_through_experiment =
+        ch_ua_reduced_expected && !ch_ua_exist_expected;
+    CheckUserAgentReduced(ch_ua_reduced_expected,
+                          expected_reduced_ua_through_experiment);
+  }
+
+  bool UAReductionEnabled() {
+    return base::FeatureList::IsEnabled(
+        blink::features::kReduceUserAgentMinorVersion);
   }
 
  protected:
@@ -3815,11 +3841,20 @@
     // If Critical-CH is set, we expect Sec-CH-UA-Reduced in the first
     // navigation request header.  If Critical-CH is not set, we don't expect
     // Sec-CH-UA-Reduced in the first navigation request.
-    const bool first_navigation_reduced_ua =
+    // If Sec-CH-UA-Reduced in the first request, UA string should reduced,
+    // otherwise UA string depends on whether kReduceUserAgentMinorVersion has
+    // turns up.
+    const bool first_navigation_has_sec_reduced_ua =
         critical_ch_ua_reduced_expected && ch_ua_reduced_expected;
-    NavigateAndCheckHeaders(url, first_navigation_reduced_ua,
-                            first_navigation_reduced_ua);
-    if (first_navigation_reduced_ua) {
+    bool first_navigation_expected_reduced_ua = true;
+    if (first_navigation_has_sec_reduced_ua) {
+      first_navigation_expected_reduced_ua = true;
+    } else {
+      first_navigation_expected_reduced_ua = UAReductionEnabled();
+    }
+    NavigateAndCheckHeaders(url, first_navigation_expected_reduced_ua,
+                            first_navigation_has_sec_reduced_ua);
+    if (first_navigation_has_sec_reduced_ua) {
       ++reduced_count;
       if (critical_ch_ua_reduced_expected) {
         // If Critical-CH was set, there will also be the initial navigation
@@ -3841,8 +3876,18 @@
     // Regardless of the Critical-CH setting, we expect the Sec-CH-UA-Reduced
     // client hint sent on the second request, if Sec-CH-UA-Reduced is set and
     // the Origin Trial token is valid.
-    NavigateAndCheckHeaders(url, ch_ua_reduced_expected,
-                            ch_ua_reduced_expected);
+    // If Sec-CH-UA-Reduced in the second request, UA string should reduced,
+    // otherwise UA string depends on whether kReduceUserAgentMinorVersion has
+    // turns up.
+    bool second_navigation_has_sec_reduced_ua = ch_ua_reduced_expected;
+    bool second_navigation_expected_reduced_ua = true;
+    if (second_navigation_has_sec_reduced_ua) {
+      second_navigation_expected_reduced_ua = true;
+    } else {
+      second_navigation_expected_reduced_ua = UAReductionEnabled();
+    }
+    NavigateAndCheckHeaders(url, second_navigation_expected_reduced_ua,
+                            second_navigation_has_sec_reduced_ua);
     // Make sure non-default client hints are not added to the request headers
     // of subresource requests. Here, we just use Sec-CH-UA-Bitness as a high
     // entropy hint to check against.
@@ -3870,10 +3915,19 @@
     // If Critical-CH is set, we expect Sec-CH-UA-Full in the first
     // navigation request header.  If Critical-CH is not set, we don't expect
     // Sec-CH-UA-Full in the first navigation request.
-    const bool first_navigation_full_ua =
+    const bool first_navigation_has_sec_full_ua =
         critical_ch_ua_full_expected && ch_ua_full_expected;
-    // For full user agent, we never expect the ua reduced.
-    NavigateAndCheckHeaders(url, false, first_navigation_full_ua);
+    // If Sec-CH-UA-Full in the first request, UA string should not reduced,
+    // otherwise UA string depends on whether kReduceUserAgentMinorVersion has
+    // turns up.
+    bool first_navigation_expected_reduced_ua = false;
+    if (first_navigation_has_sec_full_ua) {
+      first_navigation_expected_reduced_ua = false;
+    } else {
+      first_navigation_expected_reduced_ua = UAReductionEnabled();
+    }
+    NavigateAndCheckHeaders(url, first_navigation_expected_reduced_ua,
+                            first_navigation_has_sec_full_ua);
 
     // TODO: Currently no matter whether it's a first navigation request or not,
     // we always sent the full user agent string. We need to update the count
@@ -3895,7 +3949,18 @@
     // Regardless of the Critical-CH setting, we expect the Sec-CH-UA-Full
     // client hint sent on the second request, if Sec-CH-UA-Full is set and
     // the Origin Trial token is valid.
-    NavigateAndCheckHeaders(url, false, ch_ua_full_expected);
+    // If Sec-CH-UA-Full in the second request, UA string should not reduced,
+    // otherwise UA string depends on whether kReduceUserAgentMinorVersion has
+    // turns up.
+    bool second_navigation_has_sec_full_ua = ch_ua_full_expected;
+    bool second_navigation_expected_reduced_ua = false;
+    if (second_navigation_has_sec_full_ua) {
+      second_navigation_expected_reduced_ua = false;
+    } else {
+      second_navigation_expected_reduced_ua = UAReductionEnabled();
+    }
+    NavigateAndCheckHeaders(url, second_navigation_expected_reduced_ua,
+                            ch_ua_full_expected);
     // Make sure non-default client hints are not added to the request headers
     // of subresource requests. Here, we just use Sec-CH-UA-Bitness as a high
     // entropy hint to check against.
@@ -4064,11 +4129,13 @@
   CheckUserAgentMinorVersion(
       content::EvalJs(web_contents, "navigator.userAgent").ExtractString(),
       /*expected_user_agent_reduced=*/GetParam() ==
-          UserAgentOriginTrialTestType::UAReduction);
+          UserAgentOriginTrialTestType::UAReduction,
+      false);
   CheckUserAgentMinorVersion(
       content::EvalJs(web_contents, "navigator.appVersion").ExtractString(),
       /*expected_user_agent_reduced=*/GetParam() ==
-          UserAgentOriginTrialTestType::UAReduction);
+          UserAgentOriginTrialTestType::UAReduction,
+      false);
   // Instead of checking all platform types, just check one that has a
   // difference between the full and reduced versions.
 #if BUILDFLAG(IS_ANDROID)
@@ -4092,16 +4159,16 @@
                               /*ch_ua_exist_expected=*/false,
                               /*critical_ch_ua_exist_expected=*/false);
 
-  // The Origin Trial token is invalid, so we expect the full UA values in
-  // the Javascript getters.
+  // The Origin Trial token is invalid, so we expect the UA values depends on
+  // the feature kReduceUserAgentMinorVersion in the Javascript getters.
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   CheckUserAgentMinorVersion(
       content::EvalJs(web_contents, "navigator.userAgent").ExtractString(),
-      /*expected_user_agent_reduced=*/false);
+      /*expected_user_agent_reduced=*/UAReductionEnabled(), true);
   CheckUserAgentMinorVersion(
       content::EvalJs(web_contents, "navigator.appVersion").ExtractString(),
-      /*expected_user_agent_reduced=*/false);
+      /*expected_user_agent_reduced=*/UAReductionEnabled(), true);
   // Instead of checking all platform types, just check one that has a
   // difference between the full and reduced versions.
 #if BUILDFLAG(IS_ANDROID)
@@ -4376,7 +4443,7 @@
   // The first navigation sets Sec-CH-UA-Reduced/Sec-CH-UA-Full in the client
   // hints storage for the origin.
   NavigateAndCheckHeaders(ua_with_valid_origin_trial_token_url(),
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
   // The second navigation doesn't contain an Accept-CH header in the
   // response, so Sec-CH-UA-Reduced/Sec-CH-UA-Full is removed from the storage.
@@ -4388,7 +4455,7 @@
   // in the request header because the second navigation caused it to get
   // removed.
   NavigateAndCheckHeaders(ua_with_valid_origin_trial_token_url(),
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
 }
 
@@ -4651,7 +4718,7 @@
           CONTENT_SETTING_BLOCK);
   // Headers should not be sent in third party iframe.
   NavigateAndCheckHeaders(url,
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
 
   // Make sure the last intercepted URL was the request for the embedded
@@ -4711,7 +4778,7 @@
   SetValidOTToken(false);       // Origin Trial Token is invalid.
 
   NavigateAndCheckHeaders(accept_ch_ua_cross_origin_iframe_request_url(),
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
 
   // Make sure the last intercepted URL was the request for the embedded
@@ -4725,7 +4792,7 @@
   SetValidOTToken(false);       // Origin Trial Token is invalid.
 
   NavigateAndCheckHeaders(accept_ch_ua_cross_origin_subresource_request_url(),
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
 
   // Make sure the last intercepted URL was the request for the embedded
@@ -4865,7 +4932,7 @@
           GetParam() == UserAgentOriginTrialTestType::UAReduction;
       const bool ch_ua_exist_expected = true;
       CheckUaOriginTrialClientHint(ch_ua_exist_expected);
-      CheckUserAgentReduced(ch_ua_reduced_expected);
+      CheckUserAgentReduced(ch_ua_reduced_expected, false);
     }
 
     std::string resource_path = "chrome/test/data/client_hints";
@@ -4933,10 +5000,11 @@
 
   // Called by `https_server_`.
   void MonitorRequest(const net::test_server::HttpRequest& request) {
-    // All first party requests will have the full UA string, not the reduced
-    // one, since they don't respond with a valid Origin Trial token.
-    CheckUserAgentMinorVersion(request.headers.at("user-agent"),
-                               /*expected_user_agent_reduced=*/false);
+    // All first party requests don't respond with a valid Origin Trial token,
+    // Reduced UA string or not is controlled by kReduceUserAgentMinorVersion.
+    CheckUserAgentMinorVersion(
+        request.headers.at("user-agent"),
+        /*expected_user_agent_reduced=*/UAReductionEnabled(), true);
     std::string sec_ua_ch_name =
         base::StrCat({GetParam() == UserAgentOriginTrialTestType::UAReduction
                           ? "sec-ch-ua-reduced"
@@ -4993,7 +5061,7 @@
       accept_ch_ua_cross_origin_iframe_request_url();
   // The first navigation is to opt-into the OT.
   NavigateAndCheckHeaders(top_level_frame_url,
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
   NavigateAndCheckHeaders(top_level_frame_url,
                           /*ch_ua_reduced_expected=*/GetParam() ==
@@ -5021,10 +5089,10 @@
   // embed, which shouldn't happen for this test because third-party cookies
   // are blocked.
   NavigateAndCheckHeaders(top_level_frame_url,
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
   NavigateAndCheckHeaders(top_level_frame_url,
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
   // Make sure the last intercepted URL was the request for the embedded
   // iframe.
@@ -5042,10 +5110,10 @@
   // The first navigation is to attempt to opt-into the OT for the third-party
   // embed, which shouldn't happen for this test because cookies are blocked.
   NavigateAndCheckHeaders(accept_ch_ua_cross_origin_iframe_request_url(),
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
   NavigateAndCheckHeaders(accept_ch_ua_cross_origin_iframe_request_url(),
-                          /*ch_ua_reduced_expected=*/false,
+                          /*ch_ua_reduced_expected=*/UAReductionEnabled(),
                           /*ch_ua_exist_expected=*/false);
   // Make sure the last intercepted URL was the request for the embedded
   // iframe.
@@ -5389,13 +5457,16 @@
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), redirect_url()));
   EXPECT_EQ(last_url(), redirect_url());
   CheckUserAgentMinorVersion(last_user_agent(),
-                             /*expected_user_agent_reduced=*/true);
+                             /*expected_user_agent_reduced=*/true, false);
   EXPECT_THAT(last_ua_reduced_ch(), Optional(Eq("?1")));
 
   // The next request to the origin should not send Sec-CH-UA-Reduced.
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), accept_ch_url()));
   EXPECT_EQ(last_url(), accept_ch_url());
   CheckUserAgentMinorVersion(last_user_agent(),
-                             /*expected_user_agent_reduced=*/false);
+                             /*expected_user_agent_reduced=*/
+                             base::FeatureList::IsEnabled(
+                                 blink::features::kReduceUserAgentMinorVersion),
+                             true);
   EXPECT_THAT(last_ua_reduced_ch(), Eq(absl::nullopt));
 }
diff --git a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustBottomSheetContent.java b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustBottomSheetContent.java
index 91aa1f4..6238c5a8 100644
--- a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustBottomSheetContent.java
+++ b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustBottomSheetContent.java
@@ -6,6 +6,7 @@
 
 import android.view.View;
 
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
@@ -22,17 +23,20 @@
     private final View mToolbarView;
     private final View mContentView;
     private final Supplier<Integer> mVerticalScrollOffset;
-    private final Supplier<Boolean> mBackPressHandler;
+    private final Runnable mBackPressCallback;
+    private final ObservableSupplierImpl<Boolean> mBackPressStateChangedSupplier =
+            new ObservableSupplierImpl<>();
 
     /**
      * Creates a new instance.
      */
     public MerchantTrustBottomSheetContent(View toolbarView, View contentView,
-            Supplier<Integer> verticalScrollOffset, Supplier<Boolean> backPressHandler) {
+            Supplier<Integer> verticalScrollOffset, Runnable backPressHandler) {
         mToolbarView = toolbarView;
         mContentView = contentView;
         mVerticalScrollOffset = verticalScrollOffset;
-        mBackPressHandler = backPressHandler;
+        mBackPressCallback = backPressHandler;
+        mBackPressStateChangedSupplier.set(true);
     }
 
     @Override
@@ -80,7 +84,18 @@
 
     @Override
     public boolean handleBackPress() {
-        return mBackPressHandler.get();
+        mBackPressCallback.run();
+        return true;
+    }
+
+    @Override
+    public ObservableSupplierImpl<Boolean> getBackPressStateChangedSupplier() {
+        return mBackPressStateChangedSupplier;
+    }
+
+    @Override
+    public void onBackPressed() {
+        mBackPressCallback.run();
     }
 
     @Override
diff --git a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustBottomSheetCoordinator.java b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustBottomSheetCoordinator.java
index eaafad6..a0e922b 100644
--- a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustBottomSheetCoordinator.java
+++ b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustBottomSheetCoordinator.java
@@ -93,11 +93,9 @@
         createToolbarView();
         createThinWebView();
         mMediator.setupSheetWebContents(mThinWebView, mToolbarModel);
-        mSheetContent = new MerchantTrustBottomSheetContent(mToolbarView.getView(),
-                mThinWebView.getView(), () -> mMediator.getVerticalScrollOffset(), () -> {
-                    closeSheet();
-                    return true;
-                });
+        mSheetContent =
+                new MerchantTrustBottomSheetContent(mToolbarView.getView(), mThinWebView.getView(),
+                        () -> mMediator.getVerticalScrollOffset(), this::closeSheet);
 
         mBottomSheetObserver = new EmptyBottomSheetObserver() {
             private int mCloseReason;
diff --git a/chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc b/chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc
index d10b558..75d5a62 100644
--- a/chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc
+++ b/chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc
@@ -18,7 +18,7 @@
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "components/ownership/mock_owner_key_util.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_utils.h"
@@ -116,7 +116,7 @@
   ash::ScopedTestDeviceSettingsService scoped_device_settings_service_;
   ash::ScopedTestCrosSettings scoped_test_cros_settings_{
       scoped_testing_local_state_.Get()};
-  chromeos::FakeSessionManagerClient session_manager_client_;
+  ash::FakeSessionManagerClient session_manager_client_;
   policy::DevicePolicyBuilder device_policy_;
 };
 
diff --git a/chrome/browser/devtools/devtools_eye_dropper.cc b/chrome/browser/devtools/devtools_eye_dropper.cc
index fb80dae..e8cfb0d7 100644
--- a/chrome/browser/devtools/devtools_eye_dropper.cc
+++ b/chrome/browser/devtools/devtools_eye_dropper.cc
@@ -357,6 +357,8 @@
   UpdateCursor();
 }
 
+void DevToolsEyeDropper::OnNewCropVersion(uint32_t crop_version) {}
+
 void DevToolsEyeDropper::OnFrameWithEmptyRegionCapture() {}
 
 void DevToolsEyeDropper::OnStopped() {}
diff --git a/chrome/browser/devtools/devtools_eye_dropper.h b/chrome/browser/devtools/devtools_eye_dropper.h
index 9e22032..40b132fb 100644
--- a/chrome/browser/devtools/devtools_eye_dropper.h
+++ b/chrome/browser/devtools/devtools_eye_dropper.h
@@ -53,6 +53,7 @@
       const gfx::Rect& content_rect,
       mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
           callbacks) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnStopped() override;
   void OnLog(const std::string& /*message*/) override {}
diff --git a/chrome/browser/download/android/BUILD.gn b/chrome/browser/download/android/BUILD.gn
index b7a7a10..4f16b89 100644
--- a/chrome/browser/download/android/BUILD.gn
+++ b/chrome/browser/download/android/BUILD.gn
@@ -219,6 +219,7 @@
 
 android_resources("java_resources") {
   sources = [
+    "java/res/drawable/ic_incognito_download_message.xml",
     "java/res/drawable/infobar_download_complete.xml",
     "java/res/layout/confirm_oma_download.xml",
     "java/res/layout/download_later_dialog.xml",
diff --git a/chrome/browser/download/android/dangerous_download_dialog_bridge.cc b/chrome/browser/download/android/dangerous_download_dialog_bridge.cc
index 7e7f0e1..4a7d9e2 100644
--- a/chrome/browser/download/android/dangerous_download_dialog_bridge.cc
+++ b/chrome/browser/download/android/dangerous_download_dialog_bridge.cc
@@ -14,9 +14,7 @@
 #include "chrome/browser/android/resource_mapper.h"
 #include "chrome/browser/download/android/download_dialog_utils.h"
 #include "chrome/browser/download/android/jni_headers/DangerousDownloadDialogBridge_jni.h"
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/grit/generated_resources.h"
-#include "content/public/browser/download_item_utils.h"
 #include "ui/android/window_android.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -52,11 +50,6 @@
 
   JNIEnv* env = base::android::AttachCurrentThread();
 
-  content::BrowserContext* browser_context =
-      content::DownloadItemUtils::GetBrowserContext(download_item);
-  bool isOffTheRecord =
-      Profile::FromBrowserContext(browser_context)->IsOffTheRecord();
-
   Java_DangerousDownloadDialogBridge_showDialog(
       env, java_object_, window_android->GetJavaObject(),
       base::android::ConvertUTF8ToJavaString(env, download_item->GetGuid()),
@@ -64,8 +57,7 @@
           env,
           base::UTF8ToUTF16(download_item->GetFileNameToReportUser().value())),
       download_item->GetTotalBytes(),
-      ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_INFOBAR_WARNING),
-      isOffTheRecord);
+      ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_INFOBAR_WARNING));
 }
 
 void DangerousDownloadDialogBridge::OnDownloadDestroyed(
diff --git a/chrome/browser/download/android/download_controller.cc b/chrome/browser/download/android/download_controller.cc
index 72641be..056d970 100644
--- a/chrome/browser/download/android/download_controller.cc
+++ b/chrome/browser/download/android/download_controller.cc
@@ -185,6 +185,12 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(callback_id);
 
+  if (!DownloadController::GetInstance()
+           ->validator()
+           ->ValidateAndClearJavaCallback(callback_id)) {
+    return;
+  }
+
   std::string permission_to_update;
   if (jpermission_to_update) {
     permission_to_update =
@@ -316,7 +322,7 @@
   // Make copy on the heap so we can pass the pointer through JNI.
   intptr_t callback_id = reinterpret_cast<intptr_t>(
       new AcquirePermissionCallback(std::move(callback)));
-
+  validator_.AddJavaCallback(callback_id);
   Java_DownloadController_requestFileAccess(env, callback_id, jwindow_android);
 }
 
diff --git a/chrome/browser/download/android/download_controller.h b/chrome/browser/download/android/download_controller.h
index 1203160..7d9137a 100644
--- a/chrome/browser/download/android/download_controller.h
+++ b/chrome/browser/download/android/download_controller.h
@@ -26,6 +26,7 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/memory/singleton.h"
 #include "chrome/browser/download/android/dangerous_download_dialog_bridge.h"
+#include "chrome/browser/download/android/download_callback_validator.h"
 #include "chrome/browser/download/android/download_controller_base.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_key.h"
@@ -68,6 +69,8 @@
   using AcquirePermissionCallback =
       base::OnceCallback<void(bool, const std::string&)>;
 
+  DownloadCallbackValidator* validator() { return &validator_; }
+
  private:
   friend struct base::DefaultSingletonTraits<DownloadController>;
   DownloadController();
@@ -109,6 +112,8 @@
   // from the beginning and all downloaded data will be lost.
   StrongValidatorsMap strong_validators_map_;
 
+  DownloadCallbackValidator validator_;
+
   std::unique_ptr<DangerousDownloadDialogBridge> dangerous_download_bridge_;
 };
 
diff --git a/chrome/browser/download/android/download_dialog_bridge.cc b/chrome/browser/download/android/download_dialog_bridge.cc
index a60ebf0c..9e28442 100644
--- a/chrome/browser/download/android/download_dialog_bridge.cc
+++ b/chrome/browser/download/android/download_dialog_bridge.cc
@@ -49,8 +49,6 @@
     net::NetworkChangeNotifier::ConnectionType connection_type,
     DownloadLocationDialogType dialog_type,
     const base::FilePath& suggested_path,
-    bool supports_later_dialog,
-    bool show_date_time_picker,
     bool is_incognito,
     DialogCallback dialog_callback) {
   if (!native_window)
@@ -88,7 +86,7 @@
       static_cast<int>(dialog_type),
       base::android::ConvertUTF8ToJavaString(env,
                                              suggested_path.AsUTF8Unsafe()),
-      supports_later_dialog, is_incognito);
+      false /*supports_later_dialog*/, is_incognito);
 }
 
 void DownloadDialogBridge::OnComplete(
diff --git a/chrome/browser/download/android/download_dialog_bridge.h b/chrome/browser/download/android/download_dialog_bridge.h
index f3867f9..75dde77 100644
--- a/chrome/browser/download/android/download_dialog_bridge.h
+++ b/chrome/browser/download/android/download_dialog_bridge.h
@@ -53,8 +53,6 @@
       net::NetworkChangeNotifier::ConnectionType connection_type,
       DownloadLocationDialogType dialog_type,
       const base::FilePath& suggested_path,
-      bool supports_later_dialog,
-      bool show_date_time_picker,
       bool is_incognito,
       DialogCallback dialog_callback);
 
diff --git a/chrome/browser/download/android/download_manager_service.cc b/chrome/browser/download/android/download_manager_service.cc
index 1b6ac49..ab24ddf 100644
--- a/chrome/browser/download/android/download_manager_service.cc
+++ b/chrome/browser/download/android/download_manager_service.cc
@@ -855,8 +855,7 @@
           download::DOWNLOAD_INTERRUPT_REASON_CRASH, false, false, false,
           base::Time(), false,
           std::vector<download::DownloadItem::ReceivedSlice>(),
-          download::DownloadItemRerouteInfo(),
-          absl::nullopt /*download_schedule*/, download::kInvalidRange,
+          download::DownloadItemRerouteInfo(), download::kInvalidRange,
           download::kInvalidRange, nullptr));
 }
 
diff --git a/chrome/browser/download/android/java/res/drawable/ic_incognito_download_message.xml b/chrome/browser/download/android/java/res/drawable/ic_incognito_download_message.xml
new file mode 100644
index 0000000..6908049b
--- /dev/null
+++ b/chrome/browser/download/android/java/res/drawable/ic_incognito_download_message.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="14dp"
+    android:height="17dp"
+    android:viewportWidth="14"
+    android:viewportHeight="17">
+  <path
+      android:pathData="M14,6H10V0H4V6H0L7,13L14,6V6ZM0,15V17H14V15H0V15Z"
+      android:fillColor="@color/baseline_primary_200"
+      android:fillType="evenOdd"/>
+</vector>
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DangerousDownloadDialogBridge.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DangerousDownloadDialogBridge.java
index 555d009..8b3b4bd 100644
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DangerousDownloadDialogBridge.java
+++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DangerousDownloadDialogBridge.java
@@ -42,7 +42,7 @@
      */
     @CalledByNative
     public void showDialog(WindowAndroid windowAndroid, String guid, String fileName,
-            long totalBytes, int iconId, boolean isOffTheRecord) {
+            long totalBytes, int iconId) {
         Activity activity = windowAndroid.getActivity().get();
         if (activity == null) {
             onCancel(guid);
@@ -51,7 +51,7 @@
 
         new DangerousDownloadDialog().show(activity,
                 ((ModalDialogManagerHolder) activity).getModalDialogManager(), fileName, totalBytes,
-                iconId, isOffTheRecord, (accepted) -> {
+                iconId, (accepted) -> {
                     if (accepted) {
                         onAccepted(guid);
                     } else {
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DangerousDownloadDialog.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DangerousDownloadDialog.java
index b7be3bf..2aca420 100644
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DangerousDownloadDialog.java
+++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DangerousDownloadDialog.java
@@ -54,7 +54,7 @@
      *         false otherwise.
      */
     public void show(Context context, ModalDialogManager modalDialogManager, String fileName,
-            long totalBytes, int iconId, boolean isOffTheRecord, Callback<Boolean> callback) {
+            long totalBytes, int iconId, Callback<Boolean> callback) {
         String message = totalBytes > 0
                 ? context.getResources().getString(
                         R.string.dangerous_download_dialog_text, fileName)
@@ -116,11 +116,6 @@
                                 ModalDialogProperties.ButtonStyles.PRIMARY_OUTLINE_NEGATIVE_OUTLINE)
                         .build();
 
-        if (DownloadDialogUtils.shouldShowIncognitoWarning(isOffTheRecord)) {
-            propertyModel.set(ModalDialogProperties.MESSAGE_PARAGRAPH_2,
-                    context.getResources().getString(R.string.download_location_incognito_warning));
-        }
-
         modalDialogManager.showDialog(propertyModel, ModalDialogManager.ModalDialogType.TAB);
         recordDangerousDownloadDialogEvent(
                 DangerousDownloadDialogEvent.DANGEROUS_DOWNLOAD_DIALOG_SHOW);
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index a9065a87..65e6bbd 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -308,8 +308,7 @@
       target_info->target_path, target_info->target_disposition,
       target_info->danger_type, target_info->mixed_content_status,
       target_info->intermediate_path, target_info->display_name,
-      target_info->mime_type, std::move(target_info->download_schedule),
-      target_info->result);
+      target_info->mime_type, target_info->result);
 }
 
 #if BUILDFLAG(IS_ANDROID)
@@ -322,13 +321,13 @@
     bool should_download) {
   // If the download should be blocked, we can call the callback directly.
   if (!should_download) {
-    std::move(callback).Run(
-        target_info->target_path, target_info->target_disposition,
-        download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-        DownloadItem::MixedContentStatus::SILENT_BLOCK,
-        target_info->intermediate_path, target_info->display_name,
-        target_info->mime_type, std::move(target_info->download_schedule),
-        download::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED);
+    std::move(callback).Run(target_info->target_path,
+                            target_info->target_disposition,
+                            download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+                            DownloadItem::MixedContentStatus::SILENT_BLOCK,
+                            target_info->intermediate_path,
+                            target_info->display_name, target_info->mime_type,
+                            download::DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED);
     return;
   }
   target_info->mixed_content_status =
@@ -455,21 +454,14 @@
     int64_t total_bytes,
     DownloadLocationDialogType dialog_type,
     const base::FilePath& suggested_path,
-    bool supports_later_dialog,
     DownloadDialogBridge::DialogCallback callback) {
   DCHECK(download_dialog_bridge_);
   auto connection_type = net::NetworkChangeNotifier::GetConnectionType();
-  bool show_date_time_picker = DownloadDialogBridge::ShouldShowDateTimePicker();
   bool is_incognito = profile_->IsOffTheRecord();
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          download::switches::kDownloadLaterDebugOnWifi)) {
-    connection_type = net::NetworkChangeNotifier::ConnectionType::CONNECTION_2G;
-  }
   download_dialog_bridge_->ShowDialog(
       native_window, total_bytes, connection_type, dialog_type, suggested_path,
-      supports_later_dialog, show_date_time_picker, is_incognito,
-      std::move(callback));
+      is_incognito, std::move(callback));
 }
 
 void ChromeDownloadManagerDelegate::SetDownloadDialogBridgeForTesting(
@@ -998,7 +990,6 @@
 #if BUILDFLAG(IS_ANDROID)
 void ChromeDownloadManagerDelegate::RequestIncognitoWarningConfirmation(
     IncognitoWarningConfirmationCallback callback) {
-
   download_message_bridge_->ShowIncognitoDownloadMessage(std::move(callback));
 }
 #endif
@@ -1066,9 +1057,7 @@
         return;
       }
 
-      bool show_download_later_dialog = ShouldShowDownloadLaterDialog(download);
-      if (!show_download_later_dialog &&
-          !download_prefs_->PromptForDownload()) {
+      if (!download_prefs_->PromptForDownload()) {
         DuplicateDownloadDialogBridgeDelegate::GetInstance()->CreateDialog(
             download, suggested_path, web_contents, std::move(callback));
         return;
@@ -1082,7 +1071,7 @@
           base::BindOnce(
               &ChromeDownloadManagerDelegate::GenerateUniqueFileNameDone,
               weak_ptr_factory_.GetWeakPtr(), native_window,
-              show_download_later_dialog, std::move(callback)));
+              std::move(callback)));
       return;
     }
 
@@ -1111,7 +1100,6 @@
     gfx::NativeWindow native_window = web_contents->GetTopLevelNativeWindow();
     ShowDownloadDialog(
         native_window, download->GetTotalBytes(), dialog_type, suggested_path,
-        ShouldShowDownloadLaterDialog(download),
         base::BindOnce(&OnDownloadDialogClosed, std::move(callback)));
     return;
 
@@ -1174,7 +1162,6 @@
 #if BUILDFLAG(IS_ANDROID)
 void ChromeDownloadManagerDelegate::GenerateUniqueFileNameDone(
     gfx::NativeWindow native_window,
-    bool show_download_later_dialog,
     DownloadTargetDeterminerDelegate::ConfirmationCallback callback,
     PathValidationResult result,
     const base::FilePath& target_path) {
@@ -1182,11 +1169,10 @@
   // with the filename automatically set to be the unique filename.
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (result == PathValidationResult::SUCCESS) {
-    if (download_prefs_->PromptForDownload() || show_download_later_dialog) {
+    if (download_prefs_->PromptForDownload()) {
       ShowDownloadDialog(
           native_window, 0 /* total_bytes */,
           DownloadLocationDialogType::NAME_CONFLICT, target_path,
-          show_download_later_dialog,
           base::BindOnce(&OnDownloadDialogClosed, std::move(callback)));
       return;
     }
@@ -1209,43 +1195,6 @@
     bool has_no_external_storage) {
   DownloadManagerService::OnDownloadCanceled(download, has_no_external_storage);
 }
-
-bool ChromeDownloadManagerDelegate::ShouldShowDownloadLaterDialog(
-    const download::DownloadItem* download) const {
-  if (!base::FeatureList::IsEnabled(download::features::kDownloadLater) ||
-      profile_->IsOffTheRecord() || !download_prefs_->PromptDownloadLater()) {
-    return false;
-  }
-
-  // Show download later dialog on slow network connection types.
-  using ConnectionType = net::NetworkChangeNotifier::ConnectionType;
-  auto network_type = net::NetworkChangeNotifier::GetConnectionType();
-  bool met_network_condition =
-      network_type == ConnectionType::CONNECTION_2G ||
-      network_type == ConnectionType::CONNECTION_BLUETOOTH;
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          download::switches::kDownloadLaterDebugOnWifi)) {
-    met_network_condition = true;
-  }
-
-  if (met_network_condition)
-    return true;
-
-  // If the options to user are "download now" and "download on wifi" and the
-  // user is already on wifi, then don't show.
-  if (network_type == ConnectionType::CONNECTION_WIFI &&
-      !DownloadDialogBridge::ShouldShowDateTimePicker()) {
-    return false;
-  }
-
-  int64_t min_file_size_kb =
-      static_cast<int64_t>(DownloadDialogBridge::GetDownloadLaterMinFileSize());
-
-  // Show download later dialog on large download file.
-  bool met_file_size_condition =
-      download && download->GetTotalBytes() >= min_file_size_kb * 1024;
-  return met_file_size_condition;
-}
 #endif  // BUILDFLAG(IS_ANDROID)
 
 void ChromeDownloadManagerDelegate::DetermineLocalPath(
diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h
index eee1784..01d1737 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.h
+++ b/chrome/browser/download/chrome_download_manager_delegate.h
@@ -78,7 +78,6 @@
                           int64_t total_bytes,
                           DownloadLocationDialogType dialog_type,
                           const base::FilePath& suggested_path,
-                          bool supports_later_dialog,
                           DownloadDialogBridge::DialogCallback callback);
 
   void SetDownloadDialogBridgeForTesting(DownloadDialogBridge* bridge);
@@ -299,14 +298,9 @@
   // TARGET_CONFLICT and the new file name should be displayed to the user.
   void GenerateUniqueFileNameDone(
       gfx::NativeWindow native_window,
-      bool show_download_later_dialog,
       DownloadTargetDeterminerDelegate::ConfirmationCallback callback,
       download::PathValidationResult result,
       const base::FilePath& target_path);
-
-  // Returns whether to show download later dialog.
-  bool ShouldShowDownloadLaterDialog(
-      const download::DownloadItem* download) const;
 #endif
 
   raw_ptr<Profile> profile_;
diff --git a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
index 2f9f2846..3fe5e62 100644
--- a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
@@ -124,7 +124,6 @@
   base::FilePath display_name;
   download::DownloadInterruptReason interrupt_reason =
       download::DOWNLOAD_INTERRUPT_REASON_NONE;
-  absl::optional<download::DownloadSchedule> download_schedule;
   std::string mime_type;
 };
 
@@ -414,7 +413,6 @@
     const base::FilePath& intermediate_path,
     const base::FilePath& display_name,
     const std::string& mime_type,
-    absl::optional<download::DownloadSchedule> download_schedule,
     download::DownloadInterruptReason interrupt_reason) {
   result->target_path = target_path;
   result->disposition = target_disposition;
@@ -423,7 +421,6 @@
   result->intermediate_path = intermediate_path;
   result->display_name = display_name;
   result->interrupt_reason = interrupt_reason;
-  result->download_schedule = std::move(download_schedule);
   result->mime_type = mime_type;
   quit_runloop.Run();
 }
@@ -1271,8 +1268,6 @@
     const base::FilePath& virtual_path,
     absl::optional<download::DownloadSchedule> download_schedule) {
   ASSERT_EQ(result, expected_result);
-  ASSERT_FALSE(download_schedule)
-      << "DownloadSchedule is only used on Android.";
   std::move(completion_closure).Run();
 }
 }  // namespace
@@ -1752,8 +1747,6 @@
                   ConnectionType connection_type,
                   DownloadLocationDialogType dialog_type,
                   const base::FilePath& suggested_path,
-                  bool supports_later_dialog,
-                  bool show_date_time_picker,
                   bool is_incognito,
                   DownloadDialogBridge::DialogCallback callback) override {
     dialog_shown_count_++;
@@ -1909,84 +1902,4 @@
     download_item->NotifyObserversDownloadUpdated();
   }
 }
-
-class MockNetworkChangeNotifier : public net::NetworkChangeNotifier {
- public:
-  explicit MockNetworkChangeNotifier(ConnectionType type)
-      : connection_type_(type) {}
-
-  // net::NetworkChangeNotifier implementation.
-  ConnectionType GetCurrentConnectionType() const override {
-    return connection_type_;
-  }
-
- private:
-  ConnectionType connection_type_;
-};
-
-class DownloadLaterTriggerTest : public ChromeDownloadManagerDelegateTest {
- public:
-  void SetUp() override {
-    // Enable the download later feature first to ensure download pref loads
-    // correctly.
-    scoped_feature_list_.InitAndEnableFeatureWithParameters(
-        download::features::kDownloadLater,
-        {{download::features::kDownloadLaterMinFileSizeKb, "204800"},
-         {download::features::kDownloadLaterShowDateTimePicker, "false"}});
-    ChromeDownloadManagerDelegateTest::SetUp();
-  }
-
-  void SetConnectionType(ConnectionType connection_type) {
-    ResetNetworkNotifier();
-    mock_network_notifier_ =
-        std::make_unique<MockNetworkChangeNotifier>(connection_type);
-  }
-
-  void ResetNetworkNotifier() { mock_network_notifier_.reset(); }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-  std::unique_ptr<MockNetworkChangeNotifier> mock_network_notifier_;
-};
-
-TEST_F(DownloadLaterTriggerTest, DownloadLaterTrigger) {
-  net::NetworkChangeNotifier::DisableForTest disable_for_test;
-  SetConnectionType(ConnectionType::CONNECTION_2G);
-
-  std::unique_ptr<download::MockDownloadItem> download_item =
-      CreateActiveDownloadItem(1);
-  ON_CALL(*download_item, GetTotalBytes()).WillByDefault(Return(0));
-
-  // Slow connection.
-  pref_service()->SetInteger(
-      prefs::kDownloadLaterPromptStatus,
-      static_cast<int>(DownloadLaterPromptStatus::kShowInitial));
-  EXPECT_EQ(ConnectionType::CONNECTION_2G,
-            net::NetworkChangeNotifier::GetConnectionType());
-  EXPECT_TRUE(delegate()->ShouldShowDownloadLaterDialog(download_item.get()));
-
-  SetConnectionType(ConnectionType::CONNECTION_4G);
-  EXPECT_FALSE(delegate()->ShouldShowDownloadLaterDialog(download_item.get()));
-
-  // Large file.
-  ON_CALL(*download_item, GetTotalBytes())
-      .WillByDefault(Return(400 * 1024 * 1024));
-  EXPECT_TRUE(delegate()->ShouldShowDownloadLaterDialog(download_item.get()));
-  SetConnectionType(ConnectionType::CONNECTION_WIFI);
-  EXPECT_FALSE(delegate()->ShouldShowDownloadLaterDialog(download_item.get()));
-
-  // Small file.
-  SetConnectionType(ConnectionType::CONNECTION_4G);
-  ON_CALL(*download_item, GetTotalBytes())
-      .WillByDefault(Return(190 * 1024 * 1024));
-  EXPECT_FALSE(delegate()->ShouldShowDownloadLaterDialog(download_item.get()));
-
-  // Pref turn off.
-  SetConnectionType(ConnectionType::CONNECTION_2G);
-  pref_service()->SetInteger(
-      prefs::kDownloadLaterPromptStatus,
-      static_cast<int>(DownloadLaterPromptStatus::kDontShow));
-  EXPECT_FALSE(delegate()->ShouldShowDownloadLaterDialog(download_item.get()));
-  ResetNetworkNotifier();
-}
 #endif  // BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index cf9d4e03..d8e3e81 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -4990,8 +4990,7 @@
           false /* allow_metered */, false /* opened */, current_time,
           false /* transient */,
           std::vector<download::DownloadItem::ReceivedSlice>(),
-          download::DownloadItemRerouteInfo(),
-          absl::nullopt /*download_schedule*/, download::kInvalidRange,
+          download::DownloadItemRerouteInfo(), download::kInvalidRange,
           download::kInvalidRange, nullptr /* download_entry */));
 
   download::DownloadItem* download = coordinator->GetDownloadByGuid(guid);
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index 1b02eb4..f242c490 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -160,10 +160,7 @@
 // static
 DownloadUIModel::DownloadUIModelPtr DownloadItemModel::Wrap(
     download::DownloadItem* download) {
-  DownloadUIModel::DownloadUIModelPtr model(
-      new DownloadItemModel(download),
-      base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
-  return model;
+  return std::make_unique<DownloadItemModel>(download);
 }
 
 // static
@@ -171,10 +168,8 @@
     download::DownloadItem* download,
     std::unique_ptr<DownloadUIModel::StatusTextBuilderBase>
         status_text_builder) {
-  DownloadUIModel::DownloadUIModelPtr model(
-      new DownloadItemModel(download, std::move(status_text_builder)),
-      base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
-  return model;
+  return std::make_unique<DownloadItemModel>(download,
+                                             std::move(status_text_builder));
 }
 
 DownloadItemModel::DownloadItemModel(DownloadItem* download)
@@ -618,19 +613,21 @@
 }
 
 void DownloadItemModel::OnDownloadUpdated(DownloadItem* download) {
-  for (auto& obs : observers_)
-    obs.OnDownloadUpdated();
+  if (delegate_)
+    delegate_->OnDownloadUpdated();
 }
 
 void DownloadItemModel::OnDownloadOpened(DownloadItem* download) {
-  for (auto& obs : observers_)
-    obs.OnDownloadOpened();
+  if (delegate_)
+    delegate_->OnDownloadOpened();
 }
 
 void DownloadItemModel::OnDownloadDestroyed(DownloadItem* download) {
-  for (auto& obs : observers_)
-    obs.OnDownloadDestroyed();
+  ContentId id = GetContentId();
   download_ = nullptr;
+  // The object could get deleted after this.
+  if (delegate_)
+    delegate_->OnDownloadDestroyed(id);
 }
 
 void DownloadItemModel::OpenUsingPlatformHandler() {
diff --git a/chrome/browser/download/download_shelf_context_menu.cc b/chrome/browser/download/download_shelf_context_menu.cc
index 10e06f5..b1b21ba 100644
--- a/chrome/browser/download/download_shelf_context_menu.cc
+++ b/chrome/browser/download/download_shelf_context_menu.cc
@@ -40,7 +40,6 @@
     base::WeakPtr<DownloadUIModel> download)
     : download_(download), download_commands_(new DownloadCommands(download)) {
   DCHECK(download_);
-  download_->AddObserver(this);
 }
 
 void DownloadShelfContextMenu::RecordCommandsEnabled(
@@ -220,7 +219,6 @@
     return;
 
   download_commands_.reset();
-  download_->RemoveObserver(this);
   download_ = nullptr;
 }
 
diff --git a/chrome/browser/download/download_shelf_context_menu.h b/chrome/browser/download/download_shelf_context_menu.h
index 93fcbd42..7207cabd 100644
--- a/chrome/browser/download/download_shelf_context_menu.h
+++ b/chrome/browser/download/download_shelf_context_menu.h
@@ -21,8 +21,7 @@
 //
 // The DownloadItem corresponding to the context menu is observed for removal or
 // destruction.
-class DownloadShelfContextMenu : public ui::SimpleMenuModel::Delegate,
-                                 public DownloadUIModel::Observer {
+class DownloadShelfContextMenu : public ui::SimpleMenuModel::Delegate {
  public:
   // Only show a context menu for a dangerous download if it is malicious.
   static bool WantsContextMenu(DownloadUIModel* download_model);
@@ -32,6 +31,9 @@
 
   ~DownloadShelfContextMenu() override;
 
+  // Called when download is destroyed.
+  void OnDownloadDestroyed();
+
  protected:
   explicit DownloadShelfContextMenu(base::WeakPtr<DownloadUIModel> download);
 
@@ -59,9 +61,6 @@
   // destroyed or when this object is being destroyed.
   void DetachFromDownloadItem();
 
-  // DownloadUIModel::Observer overrides.
-  void OnDownloadDestroyed() override;
-
   ui::SimpleMenuModel* GetInProgressMenuModel(bool is_download);
   ui::SimpleMenuModel* GetInProgressPausedMenuModel(bool is_download);
   ui::SimpleMenuModel* GetFinishedMenuModel(bool is_download);
diff --git a/chrome/browser/download/download_shelf_context_menu_unittest.cc b/chrome/browser/download/download_shelf_context_menu_unittest.cc
index 594b245d..e763aac 100644
--- a/chrome/browser/download/download_shelf_context_menu_unittest.cc
+++ b/chrome/browser/download/download_shelf_context_menu_unittest.cc
@@ -39,8 +39,8 @@
   auto download_weak_ptr = download_ui_model->GetWeakPtr();
   EXPECT_CALL(*item, IsMixedContent()).WillRepeatedly(Return(true));
   EXPECT_CALL(*item, IsPaused()).WillRepeatedly(Return(true));
-  // 2 out of 3 commands should be executed.
-  EXPECT_CALL(*item, OpenDownload()).Times(2);
+  // 1 out of 2 commands should be executed.
+  EXPECT_CALL(*item, OpenDownload()).Times(1);
 
   MakeContextMenu(download_ui_model.get());
   EXPECT_NE(menu()->GetMenuModel(), nullptr);
@@ -49,15 +49,8 @@
   EXPECT_TRUE(menu()->IsCommandIdVisible(DownloadCommands::PAUSE));
   menu()->ExecuteCommand(DownloadCommands::OPEN_WHEN_COMPLETE, 0);
 
+  // Weakptr should be invalidated when `download_ui_model` is released.
   download_ui_model.reset();
-  EXPECT_NE(menu()->GetMenuModel(), nullptr);
-  EXPECT_TRUE(menu()->IsCommandIdEnabled(DownloadCommands::KEEP));
-  EXPECT_TRUE(menu()->IsCommandIdChecked(DownloadCommands::PAUSE));
-  EXPECT_TRUE(menu()->IsCommandIdVisible(DownloadCommands::PAUSE));
-  menu()->ExecuteCommand(DownloadCommands::OPEN_WHEN_COMPLETE, 0);
-
-  // |download_ui_model| is released by the task runner.
-  RunUntilIdle();
   EXPECT_EQ(menu()->GetMenuModel(), nullptr);
   EXPECT_FALSE(menu()->IsCommandIdEnabled(DownloadCommands::KEEP));
   EXPECT_FALSE(menu()->IsCommandIdChecked(DownloadCommands::PAUSE));
diff --git a/chrome/browser/download/download_ui_model.cc b/chrome/browser/download/download_ui_model.cc
index b9c7f62..255affb 100644
--- a/chrome/browser/download/download_ui_model.cc
+++ b/chrome/browser/download/download_ui_model.cc
@@ -6,7 +6,6 @@
 
 #include "base/feature_list.h"
 #include "base/i18n/rtl.h"
-#include "base/observer_list.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -153,12 +152,8 @@
 
 DownloadUIModel::~DownloadUIModel() = default;
 
-void DownloadUIModel::AddObserver(Observer* observer) {
-  observers_.AddObserver(observer);
-}
-
-void DownloadUIModel::RemoveObserver(Observer* observer) {
-  observers_.RemoveObserver(observer);
+void DownloadUIModel::SetDelegate(Delegate* delegate) {
+  delegate_ = delegate;
 }
 
 base::WeakPtr<DownloadUIModel> DownloadUIModel::GetWeakPtr() {
diff --git a/chrome/browser/download/download_ui_model.h b/chrome/browser/download/download_ui_model.h
index d889c4a0..920b03f 100644
--- a/chrome/browser/download/download_ui_model.h
+++ b/chrome/browser/download/download_ui_model.h
@@ -12,7 +12,6 @@
 #include "base/files/file_path.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/time/default_clock.h"
 #include "build/build_config.h"
@@ -142,8 +141,7 @@
   };
 #endif
 
-  using DownloadUIModelPtr =
-      std::unique_ptr<DownloadUIModel, base::OnTaskRunnerDeleter>;
+  using DownloadUIModelPtr = std::unique_ptr<DownloadUIModel>;
 
   DownloadUIModel();
 
@@ -155,18 +153,17 @@
 
   virtual ~DownloadUIModel();
 
-  // Observer for a single DownloadUIModel.
-  class Observer {
+  // Delegate for a single DownloadUIModel.
+  class Delegate {
    public:
     virtual void OnDownloadUpdated() {}
     virtual void OnDownloadOpened() {}
-    virtual void OnDownloadDestroyed() {}
+    virtual void OnDownloadDestroyed(const ContentId& id) {}
 
-    virtual ~Observer() {}
+    virtual ~Delegate() = default;
   };
 
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
+  void SetDelegate(Delegate* delegate);
 
   base::WeakPtr<DownloadUIModel> GetWeakPtr();
 
@@ -485,7 +482,7 @@
   // Returns the message, if any, to be displayed for file rerouted.
   virtual std::u16string GetWebDriveMessage(bool verbose) const;
 
-  base::ObserverList<Observer>::Unchecked observers_;
+  raw_ptr<Delegate> delegate_ = nullptr;
 
  private:
   friend class DownloadItemModelTest;
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java
index 514fa13..4363060 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java
@@ -150,6 +150,24 @@
     }
 
     /**
+     * Represents the values for the histogram Download.Incognito.Message.
+     */
+    @IntDef({IncognitoMessageEvent.SHOWN, IncognitoMessageEvent.ACCEPTED,
+            IncognitoMessageEvent.DISMISSED_WITH_GESTURE,
+            IncognitoMessageEvent.DISMISSED_WITH_TIMER, IncognitoMessageEvent.NUM_ENTRIES,
+            IncognitoMessageEvent.DISMISSED_WITH_DIFFERENT_REASON})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface IncognitoMessageEvent {
+        int SHOWN = 0;
+        int ACCEPTED = 1;
+        int DISMISSED_WITH_GESTURE = 2;
+        int DISMISSED_WITH_TIMER = 3;
+        int DISMISSED_WITH_DIFFERENT_REASON = 4;
+
+        int NUM_ENTRIES = 5;
+    }
+
+    /**
      * Represents the data required to show UI elements of the message.
      */
     public static class DownloadProgressMessageUiData {
@@ -342,15 +360,25 @@
         mPropertyModel.set(MessageBannerProperties.PRIMARY_BUTTON_TEXT,
                 context.getString(R.string.incognito_download_message_button));
         mPropertyModel.set(MessageBannerProperties.ICON,
-                AppCompatResources.getDrawable(context, R.drawable.infobar_download_complete));
+                AppCompatResources.getDrawable(context, R.drawable.ic_incognito_download_message));
         mPropertyModel.set(MessageBannerProperties.ON_PRIMARY_ACTION, () -> {
             callback.onResult(/*accepted=*/true);
+            recordIncognitoDownloadMessage(IncognitoMessageEvent.ACCEPTED);
             return PrimaryActionClickBehavior.DISMISS_IMMEDIATELY;
         });
-        mPropertyModel.set(MessageBannerProperties.ON_DISMISSED,
-                (dismissReason) -> callback.onResult(/*accepted=*/false));
-
+        mPropertyModel.set(MessageBannerProperties.ON_DISMISSED, (dismissReason) -> {
+            if (dismissReason == DismissReason.TIMER) {
+                recordIncognitoDownloadMessage(IncognitoMessageEvent.DISMISSED_WITH_TIMER);
+            } else if (dismissReason == DismissReason.GESTURE) {
+                recordIncognitoDownloadMessage(IncognitoMessageEvent.DISMISSED_WITH_GESTURE);
+            } else {
+                recordIncognitoDownloadMessage(
+                        IncognitoMessageEvent.DISMISSED_WITH_DIFFERENT_REASON);
+            }
+            callback.onResult(/*accepted=*/false);
+        });
         getMessageDispatcher().enqueueWindowScopedMessage(mPropertyModel, /*highPriority=*/true);
+        recordIncognitoDownloadMessage(IncognitoMessageEvent.SHOWN);
     }
 
     /** Associates a notification ID with the tracked download for future usage. */
@@ -1050,4 +1078,13 @@
             RecordUserAction.record("Android.Download.InfoBar.LinkClicked.OpenDownloadHome");
         }
     }
+
+    /**
+     * Collects incognito download message event metrics.
+     * @param event The UI event to collect.
+     */
+    private static void recordIncognitoDownloadMessage(@IncognitoMessageEvent int event) {
+        RecordHistogram.recordEnumeratedHistogram(
+                "Download.Incognito.Message", event, IncognitoMessageEvent.NUM_ENTRIES);
+    }
 }
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc
index 28711d1..bc42c58 100644
--- a/chrome/browser/download/notification/download_item_notification.cc
+++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -242,7 +242,7 @@
     Profile* profile,
     DownloadUIModel::DownloadUIModelPtr item)
     : profile_(profile), item_(std::move(item)) {
-  item_->AddObserver(this);
+  item_->SetDelegate(this);
   // Creates the notification instance. |title|, |body| and |icon| will be
   // overridden by UpdateNotificationData() below.
   message_center::RichNotificationData rich_notification_data;
@@ -276,8 +276,6 @@
 }
 
 DownloadItemNotification::~DownloadItemNotification() {
-  ShutDown();
-
   if (image_decode_status_ == IN_PROGRESS)
     ImageDecoder::Cancel(this);
 }
@@ -294,16 +292,16 @@
   Update();
 }
 
-void DownloadItemNotification::OnDownloadDestroyed() {
+void DownloadItemNotification::OnDownloadDestroyed(const ContentId& id) {
+  item_.reset();
   NotificationDisplayServiceFactory::GetForProfile(profile())->Close(
-      NotificationHandler::Type::TRANSIENT, GetNotificationId());
+      NotificationHandler::Type::TRANSIENT, id.id);
   // |this| will be deleted before there's a chance for Close() to be called
   // through the delegate, so preemptively call it now.
   Close(false);
-  ShutDown();
 
   // This object may get deleted after this call.
-  observer_->OnDownloadDestroyed(item_->GetContentId());
+  observer_->OnDownloadDestroyed(id);
 }
 
 void DownloadItemNotification::DisablePopup() {
@@ -443,11 +441,6 @@
   }
 }
 
-void DownloadItemNotification::ShutDown() {
-  if (item_)
-    item_->RemoveObserver(this);
-}
-
 std::string DownloadItemNotification::GetNotificationId() const {
   return item_->GetContentId().id;
 }
diff --git a/chrome/browser/download/notification/download_item_notification.h b/chrome/browser/download/notification/download_item_notification.h
index 2c85a514..c051651 100644
--- a/chrome/browser/download/notification/download_item_notification.h
+++ b/chrome/browser/download/notification/download_item_notification.h
@@ -32,7 +32,7 @@
 // Handles the notification on ChromeOS for one download item.
 class DownloadItemNotification : public ImageDecoder::ImageRequest,
                                  public message_center::NotificationObserver,
-                                 public DownloadUIModel::Observer {
+                                 public DownloadUIModel::Delegate {
  public:
   DownloadItemNotification(Profile* profile,
                            DownloadUIModel::DownloadUIModelPtr item);
@@ -53,9 +53,9 @@
 
   DownloadUIModel* GetDownload();
 
-  // DownloadUIModel::Observer overrides.
+  // DownloadUIModel::Delegate overrides.
   void OnDownloadUpdated() override;
-  void OnDownloadDestroyed() override;
+  void OnDownloadDestroyed(const ContentId& id) override;
 
   // Disables popup by setting low priority.
   void DisablePopup();
@@ -65,8 +65,6 @@
   void Click(const absl::optional<int>& button_index,
              const absl::optional<std::u16string>& reply) override;
 
-  void ShutDown();
-
  private:
   friend class test::DownloadItemNotificationTest;
 
diff --git a/chrome/browser/download/notification/download_notification_manager.cc b/chrome/browser/download/notification/download_notification_manager.cc
index c75b6ba..64835bb2 100644
--- a/chrome/browser/download/notification/download_notification_manager.cc
+++ b/chrome/browser/download/notification/download_notification_manager.cc
@@ -15,7 +15,6 @@
     DownloadUIModel* model = download_notification->GetDownload();
     if (model->GetState() == download::DownloadItem::IN_PROGRESS)
       download_notification->DisablePopup();
-    download_notification->ShutDown();
   }
 }
 
@@ -29,9 +28,7 @@
       download_notification->DisablePopup();
   }
 
-  DownloadUIModel::DownloadUIModelPtr model(
-      new DownloadItemModel(item),
-      base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
+  auto model = std::make_unique<DownloadItemModel>(item);
   ContentId contentId = model->GetContentId();
   items_.emplace(contentId,
                  new DownloadItemNotification(profile_, std::move(model)));
diff --git a/chrome/browser/download/offline_item_model.cc b/chrome/browser/download/offline_item_model.cc
index bacad682..d31d462 100644
--- a/chrome/browser/download/offline_item_model.cc
+++ b/chrome/browser/download/offline_item_model.cc
@@ -27,10 +27,7 @@
 DownloadUIModel::DownloadUIModelPtr OfflineItemModel::Wrap(
     OfflineItemModelManager* manager,
     const OfflineItem& offline_item) {
-  DownloadUIModel::DownloadUIModelPtr model(
-      new OfflineItemModel(manager, offline_item),
-      base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
-  return model;
+  return std::make_unique<OfflineItemModel>(manager, offline_item);
 }
 
 // static
@@ -39,11 +36,8 @@
     const OfflineItem& offline_item,
     std::unique_ptr<DownloadUIModel::StatusTextBuilderBase>
         status_text_builder) {
-  DownloadUIModel::DownloadUIModelPtr model(
-      new OfflineItemModel(manager, offline_item,
-                           std::move(status_text_builder)),
-      base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
-  return model;
+  return std::make_unique<OfflineItemModel>(manager, offline_item,
+                                            std::move(status_text_builder));
 }
 
 OfflineItemModel::OfflineItemModel(OfflineItemModelManager* manager,
@@ -259,17 +253,18 @@
 }
 
 void OfflineItemModel::OnItemRemoved(const ContentId& id) {
-  for (auto& obs : observers_)
-    obs.OnDownloadDestroyed();
   offline_item_.reset();
+  // The object could get deleted after this.
+  if (delegate_)
+    delegate_->OnDownloadDestroyed(id);
 }
 
 void OfflineItemModel::OnItemUpdated(
     const OfflineItem& item,
     const absl::optional<UpdateDelta>& update_delta) {
   offline_item_ = std::make_unique<OfflineItem>(item);
-  for (auto& obs : observers_)
-    obs.OnDownloadUpdated();
+  if (delegate_)
+    delegate_->OnDownloadUpdated();
 }
 
 FailState OfflineItemModel::GetLastFailState() const {
diff --git a/chrome/browser/enterprise/signals/BUILD.gn b/chrome/browser/enterprise/signals/BUILD.gn
index f114101..8bf0267 100644
--- a/chrome/browser/enterprise/signals/BUILD.gn
+++ b/chrome/browser/enterprise/signals/BUILD.gn
@@ -22,23 +22,3 @@
     "//components/safe_browsing/core/common:safe_browsing_prefs",
   ]
 }
-
-source_set("features") {
-  public = [ "signals_features.h" ]
-
-  sources = [ "signals_features.cc" ]
-
-  public_deps = [ "//base" ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-  sources = [ "signals_features_unittest.cc" ]
-
-  deps = [
-    ":features",
-    "//base",
-    "//base/test:test_support",
-    "//testing/gtest",
-  ]
-}
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index c809b55..88ff9da 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -959,7 +959,7 @@
       "api/system_indicator/system_indicator_manager_factory.h",
     ]
 
-    deps += [ "//chrome/browser/enterprise/signals:features" ]
+    deps += [ "//components/device_signals/core/common:features" ]
   }
 
   if (is_chromeos) {
diff --git a/chrome/browser/extensions/api/alarms/alarms_apitest.cc b/chrome/browser/extensions/api/alarms/alarms_apitest.cc
index fd888e45..01f3e0d 100644
--- a/chrome/browser/extensions/api/alarms/alarms_apitest.cc
+++ b/chrome/browser/extensions/api/alarms/alarms_apitest.cc
@@ -31,7 +31,7 @@
     ASSERT_TRUE(StartEmbeddedTestServer());
   }
 
-  static std::vector<base::Value> BuildEventArguments(const bool last_message) {
+  static base::Value::List BuildEventArguments(const bool last_message) {
     api::test::OnMessage::Info info;
     info.data = "";
     info.last_message = last_message;
diff --git a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
index d4c0c54..9f3a5d63 100644
--- a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
+++ b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
@@ -197,7 +197,7 @@
 void BookmarkManagerPrivateEventRouter::DispatchEvent(
     events::HistogramValue histogram_value,
     const std::string& event_name,
-    std::vector<base::Value> event_args) {
+    base::Value::List event_args) {
   EventRouter::Get(browser_context_)
       ->BroadcastEvent(std::make_unique<Event>(histogram_value, event_name,
                                                std::move(event_args)));
@@ -260,7 +260,7 @@
 void BookmarkManagerPrivateDragEventRouter::DispatchEvent(
     events::HistogramValue histogram_value,
     const std::string& event_name,
-    std::vector<base::Value> args) {
+    base::Value::List args) {
   EventRouter* event_router = EventRouter::Get(profile_);
   if (!event_router)
     return;
diff --git a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h
index eef0608..94d4c32 100644
--- a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h
+++ b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h
@@ -50,7 +50,7 @@
   // Helper to actually dispatch an event to extension listeners.
   void DispatchEvent(events::HistogramValue histogram_value,
                      const std::string& event_name,
-                     std::vector<base::Value> event_args);
+                     base::Value::List event_args);
 
   // Remembers the previous meta info of a node before it was changed.
   bookmarks::BookmarkNode::MetaInfoMap prev_meta_info_;
@@ -122,7 +122,7 @@
   // Helper to actually dispatch an event to extension listeners.
   void DispatchEvent(events::HistogramValue histogram_value,
                      const std::string& event_name,
-                     std::vector<base::Value> args);
+                     base::Value::List args);
 
   raw_ptr<Profile> profile_;
   bookmarks::BookmarkNodeData bookmark_drag_data_;
diff --git a/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc b/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
index e8a59cc..e752032 100644
--- a/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
+++ b/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
@@ -248,7 +248,7 @@
 
 void BookmarkEventRouter::DispatchEvent(events::HistogramValue histogram_value,
                                         const std::string& event_name,
-                                        std::vector<base::Value> event_args) {
+                                        base::Value::List event_args) {
   EventRouter* event_router = EventRouter::Get(browser_context_);
   if (event_router) {
     event_router->BroadcastEvent(std::make_unique<extensions::Event>(
diff --git a/chrome/browser/extensions/api/bookmarks/bookmarks_api.h b/chrome/browser/extensions/api/bookmarks/bookmarks_api.h
index 47f0145..a34d19f8 100644
--- a/chrome/browser/extensions/api/bookmarks/bookmarks_api.h
+++ b/chrome/browser/extensions/api/bookmarks/bookmarks_api.h
@@ -88,7 +88,7 @@
   // Helper to actually dispatch an event to extension listeners.
   void DispatchEvent(events::HistogramValue histogram_value,
                      const std::string& event_name,
-                     std::vector<base::Value> event_args);
+                     base::Value::List event_args);
 
   raw_ptr<content::BrowserContext> browser_context_;
   raw_ptr<bookmarks::BookmarkModel> model_;
diff --git a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
index dcb4ff09..1553d8e 100644
--- a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
+++ b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
@@ -175,8 +175,7 @@
 DashboardPrivateShowPermissionPromptForDelegatedInstallFunction::BuildResponse(
     api::dashboard_private::Result result, const std::string& error) {
   // The web store expects an empty string on success.
-  std::vector<base::Value> args =
-      ShowPermissionPromptForDelegatedInstall::Results::Create(result);
+  auto args = ShowPermissionPromptForDelegatedInstall::Results::Create(result);
   if (result == api::dashboard_private::RESULT_EMPTY_STRING)
     return ArgumentList(std::move(args));
   return ErrorWithArguments(std::move(args), error);
diff --git a/chrome/browser/extensions/api/desktop_capture/OWNERS b/chrome/browser/extensions/api/desktop_capture/OWNERS
index 39013c0..da4c285 100644
--- a/chrome/browser/extensions/api/desktop_capture/OWNERS
+++ b/chrome/browser/extensions/api/desktop_capture/OWNERS
@@ -1,4 +1,3 @@
-# Please send the changes to braveyao@chromium.org first.
 sergeyu@chromium.org
 wez@chromium.org
-braveyao@chromium.org
+eladalon@chromium.org
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index 15609e7..23a8bcb 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -97,11 +97,9 @@
     return false;
 
   const Event& event = *iter->second;
-  CHECK(event.event_args);
-  CHECK_GE(1u, event.event_args->GetListDeprecated().size());
+  CHECK_GE(1u, event.event_args.size());
   std::unique_ptr<api::developer_private::EventData> event_data =
-      api::developer_private::EventData::FromValue(
-          event.event_args->GetListDeprecated()[0]);
+      api::developer_private::EventData::FromValue(event.event_args[0]);
   if (!event_data)
     return false;
 
@@ -124,10 +122,9 @@
     return false;
 
   const Event& event = *iter->second;
-  CHECK(event.event_args);
-  CHECK_GE(1u, event.event_args->GetListDeprecated().size());
-  auto site_settings = api::developer_private::UserSiteSettings::FromValue(
-      event.event_args->GetListDeprecated()[0]);
+  CHECK_GE(1u, event.event_args.size());
+  auto site_settings =
+      api::developer_private::UserSiteSettings::FromValue(event.event_args[0]);
   if (!site_settings)
     return false;
 
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index 65b3ff5..ccd5e2f0 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -208,7 +208,8 @@
 
     Event* new_event = new Event(
         Profile::FromBrowserContext(event.restrict_to_browser_context),
-        event.event_name, *event.event_args.get(), base::Time::Now());
+        event.event_name, base::Value(event.event_args.Clone()),
+        base::Time::Now());
     events_.push_back(base::WrapUnique(new_event));
     if (waiting_ && waiting_for_.get() && new_event->Satisfies(*waiting_for_)) {
       waiting_ = false;
@@ -1967,6 +1968,7 @@
       "hOsT",
       "kEEp-aLivE",
       "rEfErEr",
+      "sEt-cOoKiE",
       "tE",
       "trAilER",
       "trANsfer-eNcodiNg",
diff --git a/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc b/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
index 5457b9e..6d7f4be 100644
--- a/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
+++ b/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
@@ -83,9 +83,9 @@
     proto->set_device_hostname_template(kHostname);
     device_policy->Build();
 
-    chromeos::FakeSessionManagerClient::Get()->set_device_policy(
+    ash::FakeSessionManagerClient::Get()->set_device_policy(
         device_policy->GetBlob());
-    chromeos::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
+    ash::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
   }
 
  private:
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
index 1efc6d6..1b44f40 100644
--- a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
+++ b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
@@ -33,11 +33,11 @@
 
 #if BUILDFLAG(IS_WIN)
 #include "chrome/browser/enterprise/signals/signals_aggregator_factory.h"
-#include "chrome/browser/enterprise/signals/signals_features.h"  // nogncheck
 #include "chrome/browser/extensions/api/enterprise_reporting_private/conversion_utils.h"
 #include "components/device_signals/core/browser/signals_aggregator.h"
 #include "components/device_signals/core/browser/signals_types.h"
 #include "components/device_signals/core/browser/user_context.h"
+#include "components/device_signals/core/common/signals_features.h"  // nogncheck
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #endif  // BUILDFLAG(IS_WIN)
 
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
index 0b25242..427ca78 100644
--- a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
+++ b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
@@ -53,10 +53,10 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_reg_util_win.h"
 #include "chrome/browser/enterprise/signals/signals_aggregator_factory.h"
-#include "chrome/browser/enterprise/signals/signals_features.h"  // nogncheck
 #include "components/device_signals/core/browser/mock_signals_aggregator.h"  // nogncheck
 #include "components/device_signals/core/browser/signals_aggregator.h"  // nogncheck
 #include "components/device_signals/core/common/signals_constants.h"  // nogncheck
+#include "components/device_signals/core/common/signals_features.h"  // nogncheck
 #endif
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
index 4f2a14fe..8e29c13e 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
@@ -613,8 +613,9 @@
 // TODO(crbug.com/1249851): Test crashes on Windows
 #if BUILDFLAG(IS_WIN)
 #define MAYBE_BrowserActionPopup DISABLED_BrowserActionPopup
-#elif BUILDFLAG(IS_LINUX) && defined(THREAD_SANITIZER)
-// TODO(crbug.com/1269076): Test is flaky for linux tsan builds
+#elif BUILDFLAG(IS_LINUX) && \
+    (defined(THREAD_SANITIZER) || defined(ADDRESS_SANITIZER))
+// TODO(crbug.com/1269076): Test is flaky for linux tsan and asan builds
 #define MAYBE_BrowserActionPopup DISABLED_BrowserActionPopup
 #elif BUILDFLAG(IS_MAC)
 // TODO(crbug.com/1269076): Test is flaky on Mac as well.
diff --git a/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc b/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc
index 63c1b32..3d9f726 100644
--- a/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc
+++ b/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc
@@ -69,7 +69,7 @@
     SetUpInProcessBrowserTestFixture() {
   // Initialize clients here so they are available during setup. They will be
   // shutdown in ChromeBrowserMain.
-  chromeos::SessionManagerClient::InitializeFakeInMemory();
+  ash::SessionManagerClient::InitializeFakeInMemory();
 
   // Init the user policy provider.
   policy_provider_.SetDefaultReturns(
diff --git a/chrome/browser/extensions/api/history/history_api.cc b/chrome/browser/extensions/api/history/history_api.cc
index b951eaf..e1b9e337 100644
--- a/chrome/browser/extensions/api/history/history_api.cc
+++ b/chrome/browser/extensions/api/history/history_api.cc
@@ -170,7 +170,7 @@
 void HistoryEventRouter::DispatchEvent(Profile* profile,
                                        events::HistogramValue histogram_value,
                                        const std::string& event_name,
-                                       std::vector<base::Value> event_args) {
+                                       base::Value::List event_args) {
   if (profile && EventRouter::Get(profile)) {
     auto event = std::make_unique<Event>(histogram_value, event_name,
                                          std::move(event_args), profile);
diff --git a/chrome/browser/extensions/api/history/history_api.h b/chrome/browser/extensions/api/history/history_api.h
index 945f0dd..2b8f489 100644
--- a/chrome/browser/extensions/api/history/history_api.h
+++ b/chrome/browser/extensions/api/history/history_api.h
@@ -47,7 +47,7 @@
   void DispatchEvent(Profile* profile,
                      events::HistogramValue histogram_value,
                      const std::string& event_name,
-                     std::vector<base::Value> event_args);
+                     base::Value::List event_args);
 
   raw_ptr<Profile> profile_;
   base::ScopedObservation<history::HistoryService,
diff --git a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
index c08c89b..e7151a03 100644
--- a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
+++ b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h"
 
 #include "base/bind.h"
-#include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/escape.h"
 #include "build/chromeos_buildflags.h"
@@ -16,7 +15,6 @@
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/signin/core/browser/account_reconcilor.h"
 #include "components/signin/public/base/multilogin_parameters.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
 #include "content/public/browser/storage_partition.h"
@@ -71,8 +69,7 @@
         WebAuthFlow::GET_AUTH_TOKEN);
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
     // `profile_` may be nullptr in tests.
-    if (profile_ &&
-        base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
+    if (profile_) {
       AccountReconcilorFactory::GetForProfile(profile_)
           ->GetConsistencyCookieManager()
           ->AddExtraCookieManager(GetCookieManagerForPartition());
@@ -198,8 +195,7 @@
   web_flow_ = std::move(web_auth_flow);
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // `profile_` may be nullptr in tests.
-  if (profile_ &&
-      base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
+  if (profile_) {
     AccountReconcilorFactory::GetForProfile(profile_)
         ->GetConsistencyCookieManager()
         ->AddExtraCookieManager(GetCookieManagerForPartition());
@@ -260,8 +256,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // `profile_` may be nullptr in tests.
-  if (profile_ &&
-      base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
+  if (profile_) {
     AccountReconcilorFactory::GetForProfile(profile_)
         ->GetConsistencyCookieManager()
         ->RemoveExtraCookieManager(GetCookieManagerForPartition());
diff --git a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_unittest.cc b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_unittest.cc
index 8b77aa3..e703920 100644
--- a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_unittest.cc
+++ b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_unittest.cc
@@ -9,9 +9,7 @@
 
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "build/chromeos_buildflags.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -112,11 +110,6 @@
   base::test::TaskEnvironment task_env_;
   base::HistogramTester histogram_tester_;
   testing::StrictMock<MockGaiaRemoteConsentFlowDelegate> delegate_;
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  base::test::ScopedFeatureList scoped_feature_list_{
-      switches::kLacrosNonSyncingProfiles};
-#endif
 };
 
 TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult) {
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 469ae5a8..684d97f6 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -3511,7 +3511,7 @@
   // been added. This is because the order of multiple events firing due to the
   // same underlying state change is undefined in the
   // chrome.identity.onSignInEventChanged() API.
-  void AddExpectedEvent(std::vector<base::Value> args) {
+  void AddExpectedEvent(base::Value::List args) {
     expected_events_.insert(
         std::make_unique<Event>(events::IDENTITY_ON_SIGN_IN_CHANGED,
                                 api::identity::OnSignInChanged::kEventName,
@@ -3526,13 +3526,13 @@
 
     // Search for |event| in the set of expected events.
     bool found_event = false;
-    const auto* event_args = event->event_args.get();
+    const auto& event_args = event->event_args;
     for (const auto& expected_event : expected_events_) {
       EXPECT_EQ(expected_event->histogram_value, event->histogram_value);
       EXPECT_EQ(expected_event->event_name, event->event_name);
 
-      const auto* expected_event_args = expected_event->event_args.get();
-      if (*event_args != *expected_event_args)
+      const auto& expected_event_args = expected_event->event_args;
+      if (event_args != expected_event_args)
         continue;
 
       expected_events_.erase(expected_event);
@@ -3546,11 +3546,11 @@
       LOG(INFO) << "Was expecting events with these args:";
 
       for (const auto& expected_event : expected_events_) {
-        LOG(INFO) << *(expected_event->event_args.get());
+        LOG(INFO) << expected_event->event_args;
       }
 
       LOG(INFO) << "But received event with different args:";
-      LOG(INFO) << *event_args;
+      LOG(INFO) << event_args;
     }
   }
 
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index df01683..395c87c 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -291,8 +291,8 @@
       return;
     }
     // Note: this is a private API event.
-    std::vector<base::Value> args;
-    args.push_back(base::Value(is_projected));
+    base::Value::List args;
+    args.Append(is_projected);
 
     DispatchEventToExtension(
         extensions::events::INPUT_METHOD_PRIVATE_ON_SCREEN_PROJECTION_CHANGED,
@@ -412,7 +412,7 @@
     }
 
     // Note: this is a private API event.
-    std::vector<base::Value> bounds_list;
+    base::Value::List bounds_list;
     bounds_list.reserve(bounds.size());
     for (const auto& bound : bounds) {
       base::Value bounds_value(base::Value::Type::DICTIONARY);
@@ -420,15 +420,15 @@
       bounds_value.SetIntKey("y", bound.y());
       bounds_value.SetIntKey("w", bound.width());
       bounds_value.SetIntKey("h", bound.height());
-      bounds_list.push_back(std::move(bounds_value));
+      bounds_list.Append(std::move(bounds_value));
     }
 
-    std::vector<base::Value> args;
+    base::Value::List args;
 
     // The old extension code uses the first parameter to get the bounds of the
     // first composition character, so for backward compatibility, add it here.
-    args.push_back(bounds_list[0].Clone());
-    args.push_back(base::Value(std::move(bounds_list)));
+    args.Append(bounds_list[0].Clone());
+    args.Append(std::move(bounds_list));
 
     DispatchEventToExtension(
         extensions::events::INPUT_METHOD_PRIVATE_ON_COMPOSITION_BOUNDS_CHANGED,
@@ -594,7 +594,7 @@
   void DispatchEventToExtension(
       extensions::events::HistogramValue histogram_value,
       const std::string& event_name,
-      std::vector<base::Value> args) {
+      base::Value::List args) {
     if (event_name == input_ime::OnActivate::kEventName) {
       // Send onActivate event regardless of it's listened by the IME.
       auto event = std::make_unique<extensions::Event>(
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
index cac2da0..ac98ad1 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
@@ -828,24 +828,22 @@
   std::string input_methods = base::JoinString(input_method_list, ",");
   prefs->SetString(pref_name, input_methods);
 
-  // In LSV2 Update 2, we want to automatically enable "Show input options in
-  // shelf" when the user has multiple input methods.
+  // We want to automatically enable "Show input options in shelf" when the user
+  // has multiple input methods.
   // We don't want to repeatedly enable it every time the user adds an input
   // method, as a user may want to intentionally turn it off - so we only enable
   // it once the user reaches two input methods.
-  if (base::FeatureList::IsEnabled(ash::features::kLanguageSettingsUpdate2)) {
-    // As pref_name and input_method_set only refer to the preference related to
-    // the list of IMEs for which this newly-added IME is in, we need the other
-    // IME list to calculate the total number of IMEs.
-    const char* other_ime_list_pref_name = is_component_extension_ime
-                                               ? prefs::kLanguageEnabledImes
-                                               : prefs::kLanguagePreloadEngines;
-    base::flat_set<std::string> other_input_method_set(
-        GetIMEsFromPref(prefs, other_ime_list_pref_name));
-    if (input_method_set.size() + other_input_method_set.size() ==
-        kNumImesToAutoEnableImeMenu) {
-      prefs->SetBoolean(prefs::kLanguageImeMenuActivated, true);
-    }
+  // As pref_name and input_method_set only refer to the preference related to
+  // the list of IMEs for which this newly-added IME is in, we need the other
+  // IME list to calculate the total number of IMEs.
+  const char* other_ime_list_pref_name = is_component_extension_ime
+                                             ? prefs::kLanguageEnabledImes
+                                             : prefs::kLanguagePreloadEngines;
+  base::flat_set<std::string> other_input_method_set(
+      GetIMEsFromPref(prefs, other_ime_list_pref_name));
+  if (input_method_set.size() + other_input_method_set.size() ==
+      kNumImesToAutoEnableImeMenu) {
+    prefs->SetBoolean(prefs::kLanguageImeMenuActivated, true);
   }
 #endif
   return RespondNow(NoArguments());
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
index 7e19fd7b..89361e9 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
@@ -114,9 +114,6 @@
     // Force Windows hybrid spellcheck to be enabled.
     feature_list_.InitAndEnableFeature(spellcheck::kWinUseBrowserSpellChecker);
 #endif  // BUILDFLAG(IS_WIN)
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-    feature_list_.InitAndEnableFeature(ash::features::kLanguageSettingsUpdate2);
-#endif
   }
 
 #if BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc b/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
index ede617b1..71aa5fe 100644
--- a/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
+++ b/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
@@ -122,18 +122,14 @@
 
   virtual bool MatchAndExplain(const Event& e,
                                testing::MatchResultListener* listener) const {
-    if (!e.event_args) {
-      *listener << "event.event_arg is null when it shouldn't be";
-      return false;
-    }
-    if (e.event_args->GetListDeprecated().size() != 1) {
+    if (e.event_args.size() != 1) {
       *listener << "event.event_arg.GetSize() should be 1 but is "
-                << e.event_args->GetListDeprecated().size();
+                << e.event_args.size();
       return false;
     }
     const base::ListValue* services = nullptr;
     {
-      const base::Value& out = e.event_args->GetListDeprecated()[0];
+      const base::Value& out = e.event_args[0];
       services = static_cast<const base::ListValue*>(&out);
     }
     if (!services) {
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index 8506042..85ab1fd 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -20,7 +20,10 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/networking_private/networking_private_ui_delegate_chromeos.h"
 #include "chrome/browser/extensions/extension_apitest.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/ash/components/network/cellular_metrics_logger.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/onc/network_onc_utils.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
@@ -28,12 +31,9 @@
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_certificate_handler.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_type_pattern.h"
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 375950c..2f136c56 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
@@ -1265,8 +1265,8 @@
   delegate().StartPasswordCheck();
   EXPECT_EQ(events::PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED,
             event_iter->second->histogram_value);
-  auto status = PasswordCheckStatus::FromValue(
-      event_iter->second->event_args->GetListDeprecated().front());
+  auto status =
+      PasswordCheckStatus::FromValue(event_iter->second->event_args.front());
   EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_RUNNING,
             status->state);
   EXPECT_EQ(0, *status->already_processed);
@@ -1275,8 +1275,8 @@
   static_cast<BulkLeakCheckDelegateInterface*>(service())->OnFinishedCredential(
       LeakCheckCredential(kUsername1, kPassword1), IsLeaked(false));
 
-  status = PasswordCheckStatus::FromValue(
-      event_iter->second->event_args->GetListDeprecated().front());
+  status =
+      PasswordCheckStatus::FromValue(event_iter->second->event_args.front());
   EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_RUNNING,
             status->state);
   EXPECT_EQ(2, *status->already_processed);
@@ -1285,8 +1285,8 @@
   static_cast<BulkLeakCheckDelegateInterface*>(service())->OnFinishedCredential(
       LeakCheckCredential(kUsername2, kPassword2), IsLeaked(false));
 
-  status = PasswordCheckStatus::FromValue(
-      event_iter->second->event_args->GetListDeprecated().front());
+  status =
+      PasswordCheckStatus::FromValue(event_iter->second->event_args.front());
   EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_RUNNING,
             status->state);
   EXPECT_EQ(4, *status->already_processed);
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 ecadc36..7979ebe 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
@@ -10,10 +10,10 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/check.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "base/notreached.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
@@ -22,22 +22,20 @@
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/sync/sync_service_factory.h"
-#include "chrome/browser/ui/passwords/ui_utils.h"
 #include "chrome/common/extensions/api/passwords_private.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/keyed_service/core/service_access_type.h"
-#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
+#include "components/password_manager/core/browser/move_password_to_account_store_helper.h"
 #include "components/password_manager/core/browser/password_form.h"
-#include "components/password_manager/core/browser/password_list_sorter.h"
 #include "components/password_manager/core/browser/password_manager_features_util.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/plaintext_reason.h"
-#include "components/password_manager/core/common/password_manager_features.h"
+#include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/base/signin_metrics.h"
+#include "components/sync/driver/sync_service.h"
+#include "components/url_formatter/elide_url.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/clipboard/scoped_clipboard_writer.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -57,6 +55,8 @@
 
 namespace {
 
+using password_manager::CredentialUIEntry;
+
 // The error message returned to the UI when Chrome refuses to start multiple
 // exports.
 const char kExportInProgress[] = "in-progress";
@@ -107,35 +107,20 @@
   return password_manager::ReauthPurpose::VIEW_PASSWORD;
 }
 
-password_manager::PlaintextReason ConvertPlaintextReason(
+password_manager::metrics_util::AccessPasswordInSettingsEvent
+ConvertPlaintextReason(
     extensions::api::passwords_private::PlaintextReason reason) {
   switch (reason) {
-    case extensions::api::passwords_private::PLAINTEXT_REASON_VIEW:
-      return password_manager::PlaintextReason::kView;
     case extensions::api::passwords_private::PLAINTEXT_REASON_COPY:
-      return password_manager::PlaintextReason::kCopy;
+      return password_manager::metrics_util::ACCESS_PASSWORD_COPIED;
+    case extensions::api::passwords_private::PLAINTEXT_REASON_VIEW:
+      return password_manager::metrics_util::ACCESS_PASSWORD_VIEWED;
     case extensions::api::passwords_private::PLAINTEXT_REASON_EDIT:
-      return password_manager::PlaintextReason::kEdit;
+      return password_manager::metrics_util::ACCESS_PASSWORD_EDITED;
     case extensions::api::passwords_private::PLAINTEXT_REASON_NONE:
-      break;
+      NOTREACHED();
+      return password_manager::metrics_util::ACCESS_PASSWORD_VIEWED;
   }
-
-  NOTREACHED();
-  return password_manager::PlaintextReason::kView;
-}
-
-// Gets all the existing keys in |generator| corresponding to |ids|. If no key
-// is found for an id, it is simply ignored.
-std::vector<std::string> GetSortKeys(
-    const extensions::IdGenerator<std::string>& generator,
-    const std::vector<int> ids) {
-  std::vector<std::string> sort_keys;
-  sort_keys.reserve(ids.size());
-  for (int id : ids) {
-    if (const std::string* sort_key = generator.TryGetKey(id))
-      sort_keys.emplace_back(*sort_key);
-  }
-  return sort_keys;
 }
 
 }  // namespace
@@ -144,8 +129,6 @@
 
 PasswordsPrivateDelegateImpl::PasswordsPrivateDelegateImpl(Profile* profile)
     : profile_(profile),
-      password_manager_presenter_(
-          std::make_unique<PasswordManagerPresenter>(this)),
       saved_passwords_presenter_(PasswordStoreFactory::GetForProfile(
                                      profile,
                                      ServiceAccessType::EXPLICIT_ACCESS),
@@ -171,21 +154,14 @@
                                   base::Unretained(this)))),
       password_check_delegate_(profile, &saved_passwords_presenter_),
       current_entries_initialized_(false),
-      current_exceptions_initialized_(false),
       is_initialized_(false),
       web_contents_(nullptr) {
-  password_manager_presenter_->Initialize();
-  password_manager_presenter_->UpdatePasswordLists();
+  saved_passwords_presenter_.AddObserver(this);
   saved_passwords_presenter_.Init();
 }
 
-PasswordsPrivateDelegateImpl::~PasswordsPrivateDelegateImpl() {}
-
-void PasswordsPrivateDelegateImpl::SendSavedPasswordsList() {
-  PasswordsPrivateEventRouter* router =
-      PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
-  if (router)
-    router->OnSavedPasswordsListChanged(current_entries_);
+PasswordsPrivateDelegateImpl::~PasswordsPrivateDelegateImpl() {
+  saved_passwords_presenter_.RemoveObserver(this);
 }
 
 void PasswordsPrivateDelegateImpl::GetSavedPasswordsList(
@@ -196,16 +172,9 @@
     get_saved_passwords_list_callbacks_.push_back(std::move(callback));
 }
 
-void PasswordsPrivateDelegateImpl::SendPasswordExceptionsList() {
-  PasswordsPrivateEventRouter* router =
-      PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
-  if (router)
-    router->OnPasswordExceptionsListChanged(current_exceptions_);
-}
-
 void PasswordsPrivateDelegateImpl::GetPasswordExceptionsList(
     ExceptionEntriesCallback callback) {
-  if (current_exceptions_initialized_)
+  if (current_entries_initialized_)
     std::move(callback).Run(current_exceptions_);
   else
     get_password_exception_list_callbacks_.push_back(std::move(callback));
@@ -264,57 +233,57 @@
 bool PasswordsPrivateDelegateImpl::ChangeSavedPassword(
     const std::vector<int>& ids,
     const api::passwords_private::ChangeSavedPasswordParams& params) {
-  const std::vector<std::string> sort_keys =
-      GetSortKeys(password_id_generator_, ids);
-
-  DCHECK(!sort_keys.empty());
-  if (ids.empty() || sort_keys.size() != ids.size())
+  DCHECK(!ids.empty());
+  DCHECK_LE(ids.size(), 2u);
+  // It may have 2 elements but only if it's the same password in two stores. In
+  // this case updating only one of them is enough as
+  // |saved_passwords_presenter_| will update both of them anyway.
+  const CredentialUIEntry* entry = credential_id_generator_.TryGetKey(ids[0]);
+  if (!entry)
     return false;
 
-  std::vector<password_manager::PasswordForm> forms_to_change;
-
-  for (const auto& key : sort_keys) {
-    auto forms_for_key = password_manager_presenter_->GetPasswordsForKey(key);
-    if (forms_for_key.empty())
-      return false;
-    for (const auto& form : forms_for_key)
-      forms_to_change.push_back(*form);
-  }
-
-  std::u16string username = base::UTF8ToUTF16(params.username);
-  std::u16string password = base::UTF8ToUTF16(params.password);
+  CredentialUIEntry to_edit = *entry;
+  to_edit.username = base::UTF8ToUTF16(params.username);
+  to_edit.password = base::UTF8ToUTF16(params.password);
   if (params.note) {
-    return saved_passwords_presenter_.EditSavedPasswords(
-        forms_to_change, username, password, base::UTF8ToUTF16(*params.note));
+    to_edit.note = password_manager::PasswordNote(
+        base::UTF8ToUTF16(*params.note), base::Time::Now());
   }
-  return saved_passwords_presenter_.EditSavedPasswords(forms_to_change,
-                                                       username, password);
+  return saved_passwords_presenter_.EditSavedCredentials(to_edit);
 }
 
 void PasswordsPrivateDelegateImpl::RemoveSavedPasswords(
     const std::vector<int>& ids) {
-  ExecuteFunction(base::BindOnce(
-      &PasswordsPrivateDelegateImpl::RemoveSavedPasswordsInternal,
-      base::Unretained(this), ids));
+  ExecuteFunction(
+      base::BindOnce(&PasswordsPrivateDelegateImpl::RemoveEntryInternal,
+                     base::Unretained(this), ids));
 }
 
-void PasswordsPrivateDelegateImpl::RemoveSavedPasswordsInternal(
+void PasswordsPrivateDelegateImpl::RemoveEntryInternal(
     const std::vector<int>& ids) {
-  password_manager_presenter_->RemoveSavedPasswords(
-      GetSortKeys(password_id_generator_, ids));
+  DCHECK(!ids.empty());
+  for (int id : ids) {
+    const CredentialUIEntry* entry = credential_id_generator_.TryGetKey(id);
+    if (!entry) {
+      continue;
+    }
+    saved_passwords_presenter_.RemoveCredential(*entry);
+
+    if (entry->blocked_by_user) {
+      base::RecordAction(
+          base::UserMetricsAction("PasswordManager_RemovePasswordException"));
+    } else {
+      base::RecordAction(
+          base::UserMetricsAction("PasswordManager_RemoveSavedPassword"));
+    }
+  }
 }
 
 void PasswordsPrivateDelegateImpl::RemovePasswordExceptions(
     const std::vector<int>& ids) {
-  ExecuteFunction(base::BindOnce(
-      &PasswordsPrivateDelegateImpl::RemovePasswordExceptionsInternal,
-      base::Unretained(this), ids));
-}
-
-void PasswordsPrivateDelegateImpl::RemovePasswordExceptionsInternal(
-    const std::vector<int>& ids) {
-  password_manager_presenter_->RemovePasswordExceptions(
-      GetSortKeys(exception_id_generator_, ids));
+  ExecuteFunction(
+      base::BindOnce(&PasswordsPrivateDelegateImpl::RemoveEntryInternal,
+                     base::Unretained(this), ids));
 }
 
 void PasswordsPrivateDelegateImpl::UndoRemoveSavedPasswordOrException() {
@@ -325,7 +294,7 @@
 
 void PasswordsPrivateDelegateImpl::
     UndoRemoveSavedPasswordOrExceptionInternal() {
-  password_manager_presenter_->UndoRemoveSavedPasswordOrException();
+  saved_passwords_presenter_.UndoLastRemoval();
 }
 
 void PasswordsPrivateDelegateImpl::RequestPlaintextPassword(
@@ -369,46 +338,78 @@
 #endif
 }
 
-Profile* PasswordsPrivateDelegateImpl::GetProfile() {
-  return profile_;
-}
-
-void PasswordsPrivateDelegateImpl::SetPasswordList(
-    const std::vector<std::unique_ptr<password_manager::PasswordForm>>&
-        password_list) {
-  // Create a list of PasswordUiEntry objects to send to observers.
+void PasswordsPrivateDelegateImpl::SetCredentials(
+    const std::vector<CredentialUIEntry>& credentials) {
+  // Create lists of PasswordUiEntry and ExceptionEntry objects to send to
+  // observers.
   current_entries_.clear();
+  current_exceptions_.clear();
 
-  for (const auto& form : password_list) {
-    api::passwords_private::PasswordUiEntry entry;
-    entry.urls = CreateUrlCollectionFromForm(*form);
-    entry.username = base::UTF16ToUTF8(form->username_value);
-    const auto& note_itr = base::ranges::find_if(
-        form->notes, &std::u16string::empty,
-        &password_manager::PasswordNote::unique_display_name);
-    entry.password_note =
-        note_itr == form->notes.end() ? "" : base::UTF16ToUTF8(note_itr->value);
-    entry.id = password_id_generator_.GenerateId(
-        password_manager::CreateSortKey(*form));
-    entry.frontend_id = password_frontend_id_generator_.GenerateId(
-        password_manager::CreateSortKey(*form,
-                                        password_manager::IgnoreStore(true)));
+  for (const CredentialUIEntry& credential : credentials) {
+    // TODO(crbug.com/1201643): A separate entity should be created for every
+    // store where the credential is stored. This can be removed when the UI
+    // will support the new model.
 
-    if (!form->federation_origin.opaque()) {
-      entry.federation_text =
-          std::make_unique<std::string>(l10n_util::GetStringFUTF8(
-              IDS_PASSWORDS_VIA_FEDERATION, GetDisplayFederation(*form)));
+    // Frontend id is used to group identical credentials no matter what
+    // storage they use. It should be generated from the original credential.
+    int frontend_id = credential_id_generator_.GenerateId(credential);
+    for (const password_manager::PasswordForm::Store& store :
+         credential.stored_in) {
+      // A copy of credential with a single storage should be created to obtain
+      // id. This is important because the credential can be removed only from
+      // one storage at a time. If credential is present only on one storage
+      // |frontend_id| and |id| are equal.
+      CredentialUIEntry copy_for_this_store = credential;
+      copy_for_this_store.stored_in = {store};
+      int id = credential_id_generator_.GenerateId(copy_for_this_store);
+      if (credential.blocked_by_user) {
+        api::passwords_private::ExceptionEntry current_exception_entry;
+        current_exception_entry.urls =
+            CreateUrlCollectionFromCredential(credential);
+        current_exception_entry.id = id;
+        current_exception_entry.frontend_id = frontend_id;
+
+        current_exception_entry.from_account_store =
+            store == password_manager::PasswordForm::Store::kAccountStore;
+        current_exceptions_.push_back(std::move(current_exception_entry));
+      } else {
+        api::passwords_private::PasswordUiEntry entry;
+        entry.urls = CreateUrlCollectionFromCredential(credential);
+        entry.username = base::UTF16ToUTF8(credential.username);
+        entry.password_note = base::UTF16ToUTF8(credential.note.value);
+        entry.id = id;
+        entry.frontend_id = frontend_id;
+
+        if (!credential.federation_origin.opaque()) {
+          std::u16string formatted_origin =
+              url_formatter::FormatOriginForSecurityDisplay(
+                  credential.federation_origin,
+                  url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
+
+          entry.federation_text =
+              std::make_unique<std::string>(l10n_util::GetStringFUTF8(
+                  IDS_PASSWORDS_VIA_FEDERATION, formatted_origin));
+        }
+
+        entry.from_account_store =
+            store == password_manager::PasswordForm::Store::kAccountStore;
+
+        current_entries_.push_back(std::move(entry));
+      }
     }
-
-    entry.from_account_store = form->IsUsingAccountStore();
-
-    current_entries_.push_back(std::move(entry));
   }
 
-  SendSavedPasswordsList();
+  if (current_entries_initialized_) {
+    DCHECK(get_saved_passwords_list_callbacks_.empty());
+    DCHECK(get_password_exception_list_callbacks_.empty());
+  }
 
-  DCHECK(!current_entries_initialized_ ||
-         get_saved_passwords_list_callbacks_.empty());
+  PasswordsPrivateEventRouter* router =
+      PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
+  if (router) {
+    router->OnSavedPasswordsListChanged(current_entries_);
+    router->OnPasswordExceptionsListChanged(current_exceptions_);
+  }
 
   current_entries_initialized_ = true;
   InitializeIfNecessary();
@@ -416,36 +417,6 @@
   for (auto& callback : get_saved_passwords_list_callbacks_)
     std::move(callback).Run(current_entries_);
   get_saved_passwords_list_callbacks_.clear();
-}
-
-void PasswordsPrivateDelegateImpl::SetPasswordExceptionList(
-    const std::vector<std::unique_ptr<password_manager::PasswordForm>>&
-        password_exception_list) {
-  // Creates a list of exceptions to send to observers.
-  current_exceptions_.clear();
-
-  for (const auto& form : password_exception_list) {
-    api::passwords_private::ExceptionEntry current_exception_entry;
-    current_exception_entry.urls = CreateUrlCollectionFromForm(*form);
-    current_exception_entry.id = exception_id_generator_.GenerateId(
-        password_manager::CreateSortKey(*form));
-    current_exception_entry.frontend_id =
-        exception_frontend_id_generator_.GenerateId(
-            password_manager::CreateSortKey(
-                *form, password_manager::IgnoreStore(true)));
-
-    current_exception_entry.from_account_store = form->IsUsingAccountStore();
-    current_exceptions_.push_back(std::move(current_exception_entry));
-  }
-
-  SendPasswordExceptionsList();
-
-  DCHECK(!current_entries_initialized_ ||
-         get_saved_passwords_list_callbacks_.empty());
-
-  current_exceptions_initialized_ = true;
-  InitializeIfNecessary();
-
   for (auto& callback : get_password_exception_list_callbacks_)
     std::move(callback).Run(current_exceptions_);
   get_password_exception_list_callbacks_.clear();
@@ -456,12 +427,34 @@
     content::WebContents* web_contents) {
   auto* client = ChromePasswordManagerClient::FromWebContents(web_contents);
   DCHECK(client);
-  std::vector<std::string> sort_keys;
-  for (int id : ids) {
-    if (const std::string* sort_key = password_id_generator_.TryGetKey(id))
-      sort_keys.push_back(*sort_key);
+
+  if (!client->GetPasswordFeatureManager()->IsOptedInForAccountStorage() ||
+      SyncServiceFactory::GetForProfile(profile_)->IsSyncFeatureEnabled()) {
+    return;
   }
-  password_manager_presenter_->MovePasswordsToAccountStore(sort_keys, client);
+
+  std::vector<password_manager::PasswordForm> forms_to_move;
+  for (int id : ids) {
+    const CredentialUIEntry* entry = credential_id_generator_.TryGetKey(id);
+    if (!entry) {
+      continue;
+    }
+
+    std::vector<password_manager::PasswordForm> corresponding_forms =
+        saved_passwords_presenter_.GetCorrespondingPasswordForms(entry->key());
+    if (corresponding_forms.empty()) {
+      continue;
+    }
+
+    // password_manager::MovePasswordsToAccountStore() takes care of moving the
+    // entire equivalence class, so passing the first element is fine.
+    forms_to_move.push_back(std::move(corresponding_forms[0]));
+  }
+
+  password_manager::MovePasswordsToAccountStore(
+      forms_to_move, client,
+      password_manager::metrics_util::MoveToAccountStoreTrigger::
+          kExplicitlyTriggeredInSettings);
 }
 
 void PasswordsPrivateDelegateImpl::ImportPasswords(
@@ -612,35 +605,39 @@
     return;
   }
 
-  // Request the password. When it is retrieved, ShowPassword() will be called.
-  const std::string* sort_key = password_id_generator_.TryGetKey(id);
-  if (!sort_key) {
+  const CredentialUIEntry* entry = credential_id_generator_.TryGetKey(id);
+  if (!entry) {
     std::move(callback).Run(absl::nullopt);
     return;
   }
 
   if (reason == api::passwords_private::PLAINTEXT_REASON_COPY) {
+    ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
+    clipboard_writer.WriteText(entry->password);
+    clipboard_writer.MarkAsConfidential();
     // In case of copy we don't need to give password back to UI. callback
     // will receive either empty string in case of success or null otherwise.
     // Copying occurs here so javascript doesn't need plaintext password.
-    callback = base::BindOnce(
-        [](PlaintextPasswordCallback callback,
-           absl::optional<std::u16string> password) {
-          if (!password) {
-            std::move(callback).Run(absl::nullopt);
-            return;
-          }
-          ui::ScopedClipboardWriter clipboard_writer(
-              ui::ClipboardBuffer::kCopyPaste);
-          clipboard_writer.WriteText(*password);
-          clipboard_writer.MarkAsConfidential();
-          std::move(callback).Run(std::u16string());
-        },
-        std::move(callback));
+    std::move(callback).Run(std::u16string());
+  } else {
+    std::move(callback).Run(entry->password);
   }
 
-  password_manager_presenter_->RequestPlaintextPassword(
-      *sort_key, ConvertPlaintextReason(reason), std::move(callback));
+  syncer::SyncService* sync_service = nullptr;
+  if (SyncServiceFactory::HasSyncService(profile_)) {
+    sync_service = SyncServiceFactory::GetForProfile(profile_);
+  }
+  if (password_manager::sync_util::IsSyncAccountCredential(
+          entry->url, entry->username, sync_service,
+          IdentityManagerFactory::GetForProfile(profile_))) {
+    base::RecordAction(
+        base::UserMetricsAction("PasswordManager_SyncCredentialShown"));
+  }
+
+  UMA_HISTOGRAM_ENUMERATION(
+      "PasswordManager.AccessPasswordInSettings",
+      ConvertPlaintextReason(reason),
+      password_manager::metrics_util::ACCESS_PASSWORD_COUNT);
 }
 
 void PasswordsPrivateDelegateImpl::OnExportPasswordsAuthResult(
@@ -682,12 +679,6 @@
 void PasswordsPrivateDelegateImpl::Shutdown() {
   password_account_storage_settings_watcher_.reset();
   password_manager_porter_.reset();
-  password_manager_presenter_.reset();
-}
-
-IdGenerator<std::string>&
-PasswordsPrivateDelegateImpl::GetPasswordIdGeneratorForTesting() {
-  return password_id_generator_;
 }
 
 void PasswordsPrivateDelegateImpl::ExecuteFunction(base::OnceClosure callback) {
@@ -699,9 +690,13 @@
   pre_initialization_callbacks_.emplace_back(std::move(callback));
 }
 
+void PasswordsPrivateDelegateImpl::OnSavedPasswordsChanged(
+    password_manager::SavedPasswordsPresenter::SavedPasswordsView passwords) {
+  SetCredentials(saved_passwords_presenter_.GetSavedCredentials());
+}
+
 void PasswordsPrivateDelegateImpl::InitializeIfNecessary() {
-  if (is_initialized_ || !current_entries_initialized_ ||
-      !current_exceptions_initialized_)
+  if (is_initialized_ || !current_entries_initialized_)
     return;
 
   is_initialized_ = true;
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 733f584..283d117b 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
@@ -9,6 +9,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/callback.h"
@@ -19,7 +20,6 @@
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_utils.h"
 #include "chrome/browser/ui/passwords/settings/password_manager_porter.h"
-#include "chrome/browser/ui/passwords/settings/password_manager_presenter.h"
 #include "chrome/browser/ui/passwords/settings/password_ui_view.h"
 #include "chrome/common/extensions/api/passwords_private.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -40,8 +40,9 @@
 namespace extensions {
 
 // Concrete PasswordsPrivateDelegate implementation.
-class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
-                                     public PasswordUIView {
+class PasswordsPrivateDelegateImpl
+    : public PasswordsPrivateDelegate,
+      public password_manager::SavedPasswordsPresenter::Observer {
  public:
   explicit PasswordsPrivateDelegateImpl(Profile* profile);
 
@@ -113,21 +114,15 @@
   password_manager::InsecureCredentialsManager* GetInsecureCredentialsManager()
       override;
 
-  // PasswordUIView implementation.
-  Profile* GetProfile() override;
-  void SetPasswordList(
-      const std::vector<std::unique_ptr<password_manager::PasswordForm>>&
-          password_list) override;
-  void SetPasswordExceptionList(
-      const std::vector<std::unique_ptr<password_manager::PasswordForm>>&
-          password_exception_list) override;
-
   // KeyedService overrides:
   void Shutdown() override;
 
-  IdGenerator<std::string>& GetPasswordIdGeneratorForTesting();
-
 #if defined(UNIT_TEST)
+  int GetIdForCredential(
+      const password_manager::CredentialUIEntry& credential) {
+    return credential_id_generator_.GenerateId(credential);
+  }
+
   // Use this in tests to mock the OS-level reauthentication.
   void set_os_reauth_call(
       password_manager::PasswordAccessAuthenticator::ReauthCallback
@@ -138,6 +133,19 @@
 #endif  // defined(UNIT_TEST)
 
  private:
+  struct CredentialUIEntryLess {
+    bool operator()(const password_manager::CredentialUIEntry& lhs,
+                    const password_manager::CredentialUIEntry& rhs) const {
+      return std::tie(lhs.key(), lhs.stored_in) <
+             std::tie(rhs.key(), rhs.stored_in);
+    }
+  };
+
+  // password_manager::SavedPasswordsPresenter::Observer implementation.
+  void OnSavedPasswordsChanged(
+      password_manager::SavedPasswordsPresenter::SavedPasswordsView passwords)
+      override;
+
   // Called after the lists are fetched. Once both lists have been set, the
   // class is considered initialized and any queued functions (which could
   // not be executed immediately due to uninitialized data) are invoked.
@@ -147,11 +155,10 @@
   // has been initialized or by deferring it until initialization has completed.
   void ExecuteFunction(base::OnceClosure callback);
 
-  void SendSavedPasswordsList();
-  void SendPasswordExceptionsList();
+  void SetCredentials(
+      const std::vector<password_manager::CredentialUIEntry>& credentials);
 
-  void RemoveSavedPasswordsInternal(const std::vector<int>& ids);
-  void RemovePasswordExceptionsInternal(const std::vector<int>& ids);
+  void RemoveEntryInternal(const std::vector<int>& ids);
   void UndoRemoveSavedPasswordOrExceptionInternal();
 
   // Callback for when the password list has been written to the destination.
@@ -192,9 +199,6 @@
   // Not owned by this class.
   raw_ptr<Profile> profile_;
 
-  // Used to communicate with the password store.
-  std::unique_ptr<PasswordManagerPresenter> password_manager_presenter_;
-
   // Used to add/edit passwords and to create |password_check_delegate_|.
   password_manager::SavedPasswordsPresenter saved_passwords_presenter_;
 
@@ -214,23 +218,18 @@
   UiEntries current_entries_;
   ExceptionEntries current_exceptions_;
 
-  // Generators that map between sort keys used by |password_manager_presenter_|
-  // and ids used by the JavaScript front end.
-  IdGenerator<std::string> password_id_generator_;
-  IdGenerator<std::string> password_frontend_id_generator_;
-  IdGenerator<std::string> exception_id_generator_;
-  IdGenerator<std::string> exception_frontend_id_generator_;
+  // An id generator for saved passwords and blocked websites.
+  IdGenerator<password_manager::CredentialUIEntry, int, CredentialUIEntryLess>
+      credential_id_generator_;
 
-  // Whether SetPasswordList and SetPasswordExceptionList have been called, and
-  // whether this class has been initialized, meaning both have been called.
+  // Whether SetCredentials has been called, and whether this class has been
+  // initialized.
   bool current_entries_initialized_;
-  bool current_exceptions_initialized_;
   bool is_initialized_;
 
   // Vector of callbacks which are queued up before the password store has been
-  // initialized. Once both SetPasswordList() and SetPasswordExceptionList()
-  // have been called, this class is considered initialized and can these
-  // callbacks are invoked.
+  // initialized. Once SetCredentials() has been called, this class is
+  // considered initialized and can these callbacks are invoked.
   std::vector<base::OnceClosure> pre_initialization_callbacks_;
   std::vector<UiEntriesCallback> get_saved_passwords_list_callbacks_;
   std::vector<ExceptionEntriesCallback> get_password_exception_list_callbacks_;
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 110fd6f..92e561b 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
@@ -171,7 +171,7 @@
   if (event.event_name != event_name_) {
     return;
   }
-  event_args_ = event.event_args->Clone();
+  event_args_ = base::Value(event.event_args.Clone());
 }
 
 std::unique_ptr<KeyedService> BuildPasswordsPrivateEventRouter(
@@ -458,8 +458,8 @@
                   base::UTF8ToUTF16(passwords[0].username));
       });
   delegate.GetSavedPasswordsList(callback.Get());
-  int sample_form_id = delegate.GetPasswordIdGeneratorForTesting().GenerateId(
-      password_manager::CreateSortKey(sample_form));
+  int sample_form_id = delegate.GetIdForCredential(
+      password_manager::CredentialUIEntry(sample_form));
 
   api::passwords_private::ChangeSavedPasswordParams params;
   params.password = "new_pass";
@@ -504,8 +504,8 @@
                   base::UTF8ToUTF16(passwords[0].password_note));
       });
   delegate.GetSavedPasswordsList(callback.Get());
-  int sample_form_id = delegate.GetPasswordIdGeneratorForTesting().GenerateId(
-      password_manager::CreateSortKey(sample_form));
+  int sample_form_id = delegate.GetIdForCredential(
+      password_manager::CredentialUIEntry(sample_form));
 
   api::passwords_private::ChangeSavedPasswordParams params;
   params.password = "new_pass";
@@ -865,10 +865,10 @@
 
   SetUpPasswordStores({form1, form2});
 
-  int first_id = delegate.GetPasswordIdGeneratorForTesting().GenerateId(
-      password_manager::CreateSortKey(form1));
-  int second_id = delegate.GetPasswordIdGeneratorForTesting().GenerateId(
-      password_manager::CreateSortKey(form2));
+  int first_id =
+      delegate.GetIdForCredential(password_manager::CredentialUIEntry(form1));
+  int second_id =
+      delegate.GetIdForCredential(password_manager::CredentialUIEntry(form2));
 
   delegate.MovePasswordsToAccount({first_id, second_id}, web_contents.get());
   base::RunLoop().RunUntilIdle();
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 e1e6ff3e..4cff619f 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
@@ -45,8 +45,7 @@
   auto extension_event = std::make_unique<Event>(
       events::PASSWORDS_PRIVATE_ON_SAVED_PASSWORDS_LIST_CHANGED,
       api::passwords_private::OnSavedPasswordsListChanged::kEventName,
-      base::Value(cached_saved_password_parameters_.value())
-          .TakeListDeprecated());
+      std::move(cached_saved_password_parameters_).value());
   event_router_->BroadcastEvent(std::move(extension_event));
 }
 
@@ -66,8 +65,7 @@
   auto extension_event = std::make_unique<Event>(
       events::PASSWORDS_PRIVATE_ON_PASSWORD_EXCEPTIONS_LIST_CHANGED,
       api::passwords_private::OnPasswordExceptionsListChanged::kEventName,
-      base::Value(cached_password_exception_parameters_.value())
-          .TakeListDeprecated());
+      std::move(cached_password_exception_parameters_).value());
   event_router_->BroadcastEvent(std::move(extension_event));
 }
 
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 ccfff3d..da0347e 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
@@ -91,9 +91,8 @@
 
   // Cached parameters which are saved so that when new listeners are added, the
   // most up-to-date lists can be sent to them immediately.
-  absl::optional<std::vector<base::Value>> cached_saved_password_parameters_;
-  absl::optional<std::vector<base::Value>>
-      cached_password_exception_parameters_;
+  absl::optional<base::Value::List> cached_saved_password_parameters_;
+  absl::optional<base::Value::List> cached_password_exception_parameters_;
 };
 
 }  // namespace extensions
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 ca14da0..83e8fe0d 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc
@@ -6,21 +6,25 @@
 
 #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"
 #include "url/gurl.h"
 
 namespace extensions {
 
-api::passwords_private::UrlCollection CreateUrlCollectionFromForm(
-    const password_manager::PasswordForm& form) {
+namespace {
+
+using password_manager::CredentialUIEntry;
+
+}  // namespace
+
+api::passwords_private::UrlCollection CreateUrlCollectionFromCredential(
+    const CredentialUIEntry& credential) {
   api::passwords_private::UrlCollection urls;
-  GURL link_url;
-  std::tie(urls.shown, link_url) =
-      password_manager::GetShownOriginAndLinkUrl(form);
-  urls.origin = form.signon_realm;
-  urls.link = link_url.spec();
+  urls.shown = GetShownOrigin(credential);
+  urls.origin = credential.signon_realm;
+  urls.link = GetShownUrl(credential).spec();
   return urls;
 }
 
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 2086ccd5..d26b4e6 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h
@@ -7,13 +7,16 @@
 
 #include <functional>
 #include <map>
+#include <string>
 
 #include "base/containers/flat_map.h"
 #include "chrome/common/extensions/api/passwords_private.h"
 #include "url/gurl.h"
 
+class Profile;
+
 namespace password_manager {
-struct PasswordForm;
+struct CredentialUIEntry;
 }  // namespace password_manager
 
 namespace extensions {
@@ -21,8 +24,8 @@
 // Obtains a collection of URLs from the passed in |form|. This includes an
 // origin URL used for internal logic, a human friendly string shown to the user
 // as well as a URL that is linked to.
-api::passwords_private::UrlCollection CreateUrlCollectionFromForm(
-    const password_manager::PasswordForm& form);
+api::passwords_private::UrlCollection CreateUrlCollectionFromCredential(
+    const password_manager::CredentialUIEntry& credential);
 
 // Obtains a collection of URLs from the passed in |url|. This includes an
 // origin URL used for internal logic, a human friendly string shown to the user
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc
index 44a0a6b..3d5ace4 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc
@@ -5,19 +5,26 @@
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_utils.h"
 
 #include "components/password_manager/core/browser/password_form.h"
+#include "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
 namespace extensions {
 
+namespace {
+
+using password_manager::CredentialUIEntry;
+
+}  // namespace
+
 TEST(CreateUrlCollectionFromFormTest, UrlsFromHtmlForm) {
   password_manager::PasswordForm html_form;
   html_form.url = GURL("http://example.com/LoginAuth");
   html_form.signon_realm = html_form.url.DeprecatedGetOriginAsURL().spec();
 
   api::passwords_private::UrlCollection html_urls =
-      CreateUrlCollectionFromForm(html_form);
+      CreateUrlCollectionFromCredential(CredentialUIEntry(html_form));
   EXPECT_EQ(html_urls.origin, "http://example.com/");
   EXPECT_EQ(html_urls.shown, "example.com");
   EXPECT_EQ(html_urls.link, "http://example.com/LoginAuth");
@@ -31,7 +38,7 @@
       url::Origin::Create(GURL("https://google.com/"));
 
   api::passwords_private::UrlCollection federated_urls =
-      CreateUrlCollectionFromForm(federated_form);
+      CreateUrlCollectionFromCredential(CredentialUIEntry(federated_form));
   EXPECT_EQ(federated_urls.origin, "federation://example.com/google.com");
   EXPECT_EQ(federated_urls.shown, "example.com");
   EXPECT_EQ(federated_urls.link, "https://example.com/");
@@ -43,7 +50,7 @@
   android_form.app_display_name.clear();
 
   api::passwords_private::UrlCollection android_urls =
-      CreateUrlCollectionFromForm(android_form);
+      CreateUrlCollectionFromCredential(CredentialUIEntry(android_form));
   EXPECT_EQ("android://example@com.example.android", android_urls.origin);
   EXPECT_EQ("android.example.com", android_urls.shown);
   EXPECT_EQ("https://play.google.com/store/apps/details?id=com.example.android",
@@ -56,7 +63,7 @@
   android_form.app_display_name = "Example Android App";
 
   api::passwords_private::UrlCollection android_urls =
-      CreateUrlCollectionFromForm(android_form);
+      CreateUrlCollectionFromCredential(CredentialUIEntry(android_form));
   EXPECT_EQ(android_urls.origin, "android://hash@com.example.android");
   EXPECT_EQ("Example Android App", android_urls.shown);
   EXPECT_EQ("https://play.google.com/store/apps/details?id=com.example.android",
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
index 5ec030b..6e73b96 100644
--- a/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
+++ b/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
@@ -100,11 +100,11 @@
 void PlatformKeysTestBase::SetUpInProcessBrowserTestFixture() {
   extensions::MixinBasedExtensionApiTest::SetUpInProcessBrowserTestFixture();
 
-  chromeos::SessionManagerClient::InitializeFakeInMemory();
+  ash::SessionManagerClient::InitializeFakeInMemory();
 
   policy::AffiliationTestHelper affiliation_helper =
       policy::AffiliationTestHelper::CreateForCloud(
-          chromeos::FakeSessionManagerClient::Get());
+          ash::FakeSessionManagerClient::Get());
 
   if (enrollment_status() == EnrollmentStatus::ENROLLED) {
     std::set<std::string> device_affiliation_ids;
diff --git a/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc b/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc
index ba3fe06..9904b81 100644
--- a/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc
+++ b/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc
@@ -82,7 +82,7 @@
                                   const Event& event) override {
     if (event.event_name == event_name_) {
       extension_id_ = extension_id;
-      event_args_ = event.event_args->Clone();
+      event_args_ = base::Value(event.event_args.Clone());
     }
   }
 
diff --git a/chrome/browser/extensions/api/processes/processes_api.cc b/chrome/browser/extensions/api/processes/processes_api.cc
index 3dcc627..2fbbbb6 100644
--- a/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chrome/browser/extensions/api/processes/processes_api.cc
@@ -338,10 +338,9 @@
                 api::processes::OnUnresponsive::Create(process));
 }
 
-void ProcessesEventRouter::DispatchEvent(
-    events::HistogramValue histogram_value,
-    const std::string& event_name,
-    std::vector<base::Value> event_args) const {
+void ProcessesEventRouter::DispatchEvent(events::HistogramValue histogram_value,
+                                         const std::string& event_name,
+                                         base::Value::List event_args) const {
   EventRouter* event_router = EventRouter::Get(browser_context_);
   if (event_router) {
     std::unique_ptr<Event> event(
diff --git a/chrome/browser/extensions/api/processes/processes_api.h b/chrome/browser/extensions/api/processes/processes_api.h
index 32096ed7..a1052d82 100644
--- a/chrome/browser/extensions/api/processes/processes_api.h
+++ b/chrome/browser/extensions/api/processes/processes_api.h
@@ -49,7 +49,7 @@
 
   void DispatchEvent(events::HistogramValue histogram_value,
                      const std::string& event_name,
-                     std::vector<base::Value> event_args) const;
+                     base::Value::List event_args) const;
 
   // Determines whether there is a registered listener for the specified event.
   // It helps to avoid collecting data if no one is interested in it.
diff --git a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc
index 267607d..12bf541 100644
--- a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -43,8 +43,8 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
diff --git a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
index 4e78881..de68a55c 100644
--- a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
+++ b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
@@ -96,7 +96,7 @@
   // extensions::TestEventRouter::EventObserver:
   void OnBroadcastEvent(const extensions::Event& event) override {
     if (event.event_name == event_name_) {
-      event_args_ = event.event_args->Clone();
+      event_args_ = base::Value(event.event_args.Clone());
     }
   }
 
diff --git a/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.cc b/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.cc
index efc4e7b..3d4942b 100644
--- a/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.cc
+++ b/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.cc
@@ -94,7 +94,7 @@
 
 void TabGroupsEventRouter::DispatchEvent(events::HistogramValue histogram_value,
                                          const std::string& event_name,
-                                         std::vector<base::Value> args) {
+                                         base::Value::List args) {
   // |event_router_| can be null in tests.
   if (!event_router_)
     return;
diff --git a/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.h b/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.h
index 45956ad4..f946ab60 100644
--- a/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.h
+++ b/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.h
@@ -48,7 +48,7 @@
 
   void DispatchEvent(events::HistogramValue histogram_value,
                      const std::string& event_name,
-                     std::vector<base::Value> args);
+                     base::Value::List args);
 
   const raw_ptr<Profile> profile_;
   const raw_ptr<EventRouter> event_router_ = nullptr;
diff --git a/chrome/browser/extensions/api/tabs/tabs_event_router.cc b/chrome/browser/extensions/api/tabs/tabs_event_router.cc
index 18c3467..82dbefe 100644
--- a/chrome/browser/extensions/api/tabs/tabs_event_router.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_event_router.cc
@@ -68,7 +68,7 @@
 
   *event_args_out = std::make_unique<base::Value::List>();
   (*event_args_out)->Append(ExtensionTabUtil::GetTabId(contents));
-  (*event_args_out)->Append(base::Value(std::move(changed_properties)));
+  (*event_args_out)->Append(std::move(changed_properties));
   (*event_args_out)->Append(std::move(tab_value));
   return true;
 }
@@ -297,8 +297,7 @@
       Profile::FromBrowserContext(data.web_contents->GetBrowserContext());
   DispatchEvent(profile, events::TABS_ON_ZOOM_CHANGE,
                 api::tabs::OnZoomChange::kEventName,
-                std::make_unique<base::ListValue>(
-                    api::tabs::OnZoomChange::Create(zoom_change_info)),
+                api::tabs::OnZoomChange::Create(zoom_change_info),
                 EventRouter::USER_GESTURE_UNKNOWN);
 }
 
@@ -352,14 +351,14 @@
   }
 
   int tab_id = ExtensionTabUtil::GetTabId(contents);
-  std::unique_ptr<base::ListValue> args(new base::ListValue);
-  args->Append(tab_id);
+  base::Value::List args;
+  args.Append(tab_id);
 
   base::Value::Dict object_args;
   object_args.Set(tabs_constants::kNewWindowIdKey,
                   Value(ExtensionTabUtil::GetWindowIdOfTab(contents)));
   object_args.Set(tabs_constants::kNewPositionKey, Value(index));
-  args->Append(base::Value(std::move(object_args)));
+  args.Append(std::move(object_args));
 
   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
   DispatchEvent(profile, events::TABS_ON_ATTACHED,
@@ -372,15 +371,15 @@
                                            int index) {
   int tab_id = ExtensionTabUtil::GetTabId(contents);
 
-  std::unique_ptr<base::ListValue> args(new base::ListValue);
-  args->Append(tab_id);
+  base::Value::List args;
+  args.Append(tab_id);
 
   base::Value::Dict object_args;
   object_args.Set(tabs_constants::kWindowIdKey,
                   ExtensionTabUtil::GetWindowIdOfTab(contents));
   object_args.Set(tabs_constants::kWindowClosing,
                   tab_strip_model->closing_all());
-  args->Append(base::Value(std::move(object_args)));
+  args.Append(std::move(object_args));
 
   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
   DispatchEvent(profile, events::TABS_ON_REMOVED,
@@ -398,14 +397,14 @@
     return;
   }
 
-  std::unique_ptr<base::ListValue> args(new base::ListValue);
-  args->Append(ExtensionTabUtil::GetTabId(contents));
+  base::Value::List args;
+  args.Append(ExtensionTabUtil::GetTabId(contents));
 
   base::Value::Dict object_args;
   object_args.Set(tabs_constants::kOldWindowIdKey,
                   ExtensionTabUtil::GetWindowIdOfTab(contents));
   object_args.Set(tabs_constants::kOldPositionKey, index);
-  args->Append(base::Value(std::move(object_args)));
+  args.Append(std::move(object_args));
 
   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
   DispatchEvent(profile, events::TABS_ON_DETACHED,
@@ -416,33 +415,31 @@
 void TabsEventRouter::DispatchActiveTabChanged(WebContents* old_contents,
                                                WebContents* new_contents,
                                                int index) {
-  auto args = std::make_unique<base::ListValue>();
+  base::Value::List args;
   int tab_id = ExtensionTabUtil::GetTabId(new_contents);
-  args->Append(tab_id);
+  args.Append(tab_id);
 
   base::Value::Dict object_args;
   object_args.Set(tabs_constants::kWindowIdKey,
                   ExtensionTabUtil::GetWindowIdOfTab(new_contents));
-  args->Append(base::Value(object_args.Clone()));
+  args.Append(object_args.Clone());
 
   // The onActivated event replaced onActiveChanged and onSelectionChanged. The
   // deprecated events take two arguments: tabId, {windowId}.
   Profile* profile =
       Profile::FromBrowserContext(new_contents->GetBrowserContext());
 
-  DispatchEvent(
-      profile, events::TABS_ON_SELECTION_CHANGED,
-      api::tabs::OnSelectionChanged::kEventName,
-      base::ListValue::From(base::Value::ToUniquePtrValue(args->Clone())),
-      EventRouter::USER_GESTURE_UNKNOWN);
+  DispatchEvent(profile, events::TABS_ON_SELECTION_CHANGED,
+                api::tabs::OnSelectionChanged::kEventName, args.Clone(),
+                EventRouter::USER_GESTURE_UNKNOWN);
   DispatchEvent(profile, events::TABS_ON_ACTIVE_CHANGED,
                 api::tabs::OnActiveChanged::kEventName, std::move(args),
                 EventRouter::USER_GESTURE_UNKNOWN);
 
   // The onActivated event takes one argument: {windowId, tabId}.
-  auto on_activated_args = std::make_unique<base::ListValue>();
+  base::Value::List on_activated_args;
   object_args.Set(tabs_constants::kTabIdKey, tab_id);
-  on_activated_args->Append(base::Value(std::move(object_args)));
+  on_activated_args.Append(std::move(object_args));
   DispatchEvent(
       profile, events::TABS_ON_ACTIVATED, api::tabs::OnActivated::kEventName,
       std::move(on_activated_args), EventRouter::USER_GESTURE_UNKNOWN);
@@ -463,7 +460,7 @@
     all_tabs.Append(tab_id);
   }
 
-  std::unique_ptr<base::ListValue> args(new base::ListValue);
+  base::Value::List args;
   base::Value::Dict select_info;
 
   select_info.Set(
@@ -471,15 +468,13 @@
       ExtensionTabUtil::GetWindowIdOfTabStripModel(tab_strip_model));
 
   select_info.Set(tabs_constants::kTabIdsKey, std::move(all_tabs));
-  args->Append(base::Value(std::move(select_info)));
+  args.Append(std::move(select_info));
 
   // The onHighlighted event replaced onHighlightChanged.
   Profile* profile = tab_strip_model->profile();
-  DispatchEvent(
-      profile, events::TABS_ON_HIGHLIGHT_CHANGED,
-      api::tabs::OnHighlightChanged::kEventName,
-      base::ListValue::From(base::Value::ToUniquePtrValue(args->Clone())),
-      EventRouter::USER_GESTURE_UNKNOWN);
+  DispatchEvent(profile, events::TABS_ON_HIGHLIGHT_CHANGED,
+                api::tabs::OnHighlightChanged::kEventName, args.Clone(),
+                EventRouter::USER_GESTURE_UNKNOWN);
   DispatchEvent(profile, events::TABS_ON_HIGHLIGHTED,
                 api::tabs::OnHighlighted::kEventName, std::move(args),
                 EventRouter::USER_GESTURE_UNKNOWN);
@@ -488,15 +483,15 @@
 void TabsEventRouter::DispatchTabMoved(WebContents* contents,
                                        int from_index,
                                        int to_index) {
-  std::unique_ptr<base::ListValue> args(new base::ListValue);
-  args->Append(ExtensionTabUtil::GetTabId(contents));
+  base::Value::List args;
+  args.Append(ExtensionTabUtil::GetTabId(contents));
 
   base::Value::Dict object_args;
   object_args.Set(tabs_constants::kWindowIdKey,
                   ExtensionTabUtil::GetWindowIdOfTab(contents));
   object_args.Set(tabs_constants::kFromIndexKey, from_index);
   object_args.Set(tabs_constants::kToIndexKey, to_index);
-  args->Append(base::Value(std::move(object_args)));
+  args.Append(std::move(object_args));
 
   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
   DispatchEvent(profile, events::TABS_ON_MOVED, api::tabs::OnMoved::kEventName,
@@ -510,9 +505,9 @@
   // WebContents being swapped.
   const int new_tab_id = ExtensionTabUtil::GetTabId(new_contents);
   const int old_tab_id = ExtensionTabUtil::GetTabId(old_contents);
-  std::unique_ptr<base::ListValue> args(new base::ListValue);
-  args->Append(new_tab_id);
-  args->Append(old_tab_id);
+  base::Value::List args;
+  args.Append(new_tab_id);
+  args.Append(old_tab_id);
 
   DispatchEvent(Profile::FromBrowserContext(new_contents->GetBrowserContext()),
                 events::TABS_ON_REPLACED, api::tabs::OnReplaced::kEventName,
@@ -572,15 +567,14 @@
     Profile* profile,
     events::HistogramValue histogram_value,
     const std::string& event_name,
-    std::unique_ptr<base::ListValue> args,
+    base::Value::List args,
     EventRouter::UserGestureState user_gesture) {
   EventRouter* event_router = EventRouter::Get(profile);
   if (!profile_->IsSameOrParent(profile) || !event_router)
     return;
 
-  auto event =
-      std::make_unique<Event>(histogram_value, event_name,
-                              std::move(*args).TakeListDeprecated(), profile);
+  auto event = std::make_unique<Event>(histogram_value, event_name,
+                                       std::move(args), profile);
   event->user_gesture = user_gesture;
   event_router->BroadcastEvent(std::move(event));
 }
diff --git a/chrome/browser/extensions/api/tabs/tabs_event_router.h b/chrome/browser/extensions/api/tabs/tabs_event_router.h
index e65c8ee1..72dc6649 100644
--- a/chrome/browser/extensions/api/tabs/tabs_event_router.h
+++ b/chrome/browser/extensions/api/tabs/tabs_event_router.h
@@ -132,7 +132,7 @@
   void DispatchEvent(Profile* profile,
                      events::HistogramValue histogram_value,
                      const std::string& event_name,
-                     std::unique_ptr<base::ListValue> args,
+                     base::Value::List args,
                      EventRouter::UserGestureState user_gesture);
 
   // Packages |changed_property_names| as a tab updated event for the tab
diff --git a/chrome/browser/extensions/browsertest_util.cc b/chrome/browser/extensions/browsertest_util.cc
index 1d2406f..edbe013 100644
--- a/chrome/browser/extensions/browsertest_util.cc
+++ b/chrome/browser/extensions/browsertest_util.cc
@@ -22,7 +22,6 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
-#include "chrome/test/base/interactive_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_utils.h"
@@ -53,10 +52,6 @@
 }
 
 Browser* LaunchAppBrowser(Profile* profile, const Extension* extension_app) {
-  ui_test_utils::BrowserChangeObserver browser_change_observer(
-      /*browser=*/nullptr,
-      ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
-
   EXPECT_TRUE(apps::AppServiceProxyFactory::GetForProfile(profile)
                   ->BrowserAppLauncher()
                   ->LaunchAppWithParamsForTesting(apps::AppLaunchParams(
@@ -65,12 +60,13 @@
                       WindowOpenDisposition::CURRENT_TAB,
                       apps::mojom::LaunchSource::kFromTest)));
 
-  Browser* const browser = browser_change_observer.Wait();
-  DCHECK(browser);
-  ui_test_utils::BrowserActivationWaiter(browser).WaitForActivation();
-  EXPECT_EQ(web_app::GetAppIdFromApplicationName(browser->app_name()),
-            extension_app->id());
-  return browser;
+  Browser* browser = chrome::FindLastActive();
+  bool is_correct_app_browser =
+      browser && web_app::GetAppIdFromApplicationName(browser->app_name()) ==
+                     extension_app->id();
+  EXPECT_TRUE(is_correct_app_browser);
+
+  return is_correct_app_browser ? browser : nullptr;
 }
 
 content::WebContents* AddTab(Browser* browser, const GURL& url) {
diff --git a/chrome/browser/extensions/extension_security_exploit_browsertest.cc b/chrome/browser/extensions/extension_security_exploit_browsertest.cc
index 19c9c52..ac0bb3d3 100644
--- a/chrome/browser/extensions/extension_security_exploit_browsertest.cc
+++ b/chrome/browser/extensions/extension_security_exploit_browsertest.cc
@@ -28,9 +28,14 @@
 #include "extensions/browser/api/storage/storage_api.h"
 #include "extensions/browser/bad_message.h"
 #include "extensions/browser/browsertest_util.h"
+#include "extensions/browser/extension_frame_host.h"
+#include "extensions/browser/extension_web_contents_observer.h"
+#include "extensions/browser/process_manager.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension_features.h"
 #include "extensions/common/extension_messages.h"
+#include "extensions/common/mojom/frame.mojom-test-utils.h"
+#include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/test_extension_dir.h"
 #include "ipc/ipc_security_test_util.h"
 #include "net/dns/mock_host_resolver.h"
@@ -42,6 +47,58 @@
 
 namespace extensions {
 
+// ExtensionFrameHostInterceptor is a helper for:
+// - Intercepting extensions::mojom::LocalFrameHost method calls (e.g. methods
+//   that would normally be handled / implemented by ExtensionFrameHost).
+// - Allowing the test to mutate the method arguments (e.g. to simulate a
+//   compromised renderer) before passing the method call to the usual handler.
+class ExtensionFrameHostInterceptor
+    : mojom::LocalFrameHostInterceptorForTesting {
+ public:
+  // The caller needs to ensure that `frame` stays alive longer than the
+  // constructed ExtensionFrameHostInterceptor.
+  using RequestMutator =
+      base::RepeatingCallback<void(mojom::RequestParams& request_params)>;
+  ExtensionFrameHostInterceptor(content::RenderFrameHost* frame,
+                                RequestMutator request_mutator)
+      : frame_(frame),
+        request_mutator_(std::move(request_mutator)),
+        extension_frame_host_(
+            ExtensionWebContentsObserver::GetForWebContents(
+                content::WebContents::FromRenderFrameHost(frame_))
+                ->extension_frame_host_for_testing()),
+        scoped_swap_impl_(extension_frame_host_->receivers_for_testing(),
+                          this) {}
+
+  ~ExtensionFrameHostInterceptor() override = default;
+
+ private:
+  mojom::LocalFrameHost* GetForwardingInterface() override {
+    return scoped_swap_impl_.old_impl();
+  }
+
+  void Request(mojom::RequestParamsPtr params,
+               RequestCallback callback) override {
+    // `//extensions/common/mojom/frame.mojom` specifies that `params` is
+    // non-optional.
+    CHECK(params);
+
+    content::RenderFrameHost* current_target_frame =
+        extension_frame_host_->receivers_for_testing().GetCurrentTargetFrame();
+    if (frame_ == current_target_frame)
+      request_mutator_.Run(*params);
+
+    GetForwardingInterface()->Request(std::move(params), std::move(callback));
+  }
+
+  content::RenderFrameHost* const frame_ = nullptr;
+  const RequestMutator request_mutator_;
+  ExtensionFrameHost* const extension_frame_host_ = nullptr;
+  const mojo::test::ScopedSwapImplForTesting<
+      content::RenderFrameHostReceiverSet<mojom::LocalFrameHost>>
+      scoped_swap_impl_;
+};
+
 // Waits for a kill of the given RenderProcessHost and returns the
 // BadMessageReason that caused an //extensions-triggerred kill.
 //
@@ -209,9 +266,9 @@
 
 // Test suite covering how mojo/IPC messages are verified after being received
 // from a (potentially compromised) renderer process.
-class OpenChannelToExtensionExploitTest : public ExtensionBrowserTest {
+class ExtensionSecurityExploitBrowserTest : public ExtensionBrowserTest {
  public:
-  OpenChannelToExtensionExploitTest() = default;
+  ExtensionSecurityExploitBrowserTest() = default;
 
   void SetUpOnMainThread() override {
     ExtensionBrowserTest::SetUpOnMainThread();
@@ -221,16 +278,6 @@
     ASSERT_TRUE(embedded_test_server()->Start());
 
     InstallTestExtensions();
-
-    GURL test_page_url =
-        embedded_test_server()->GetURL("foo.com", "/title1.html");
-    ipc_message_waiter_ = StartInterceptingIpcs(test_page_url);
-  }
-
-  // Waits for ExtensionHostMsg_OpenChannelToExtension IPC and returns its
-  // payload.
-  ExtensionHostMsg_OpenChannelToExtension::Param WaitForMessage() {
-    return ipc_message_waiter_->WaitForMessage();
   }
 
   // Asks the `extension_id` to inject `content_script` into `web_contents`.
@@ -247,7 +294,6 @@
   }
 
   const ExtensionId& active_extension_id() { return active_extension_->id(); }
-
   const ExtensionId& spoofed_extension_id() { return spoofed_extension_->id(); }
 
  private:
@@ -260,13 +306,14 @@
             "name": "ContentScriptTrackerBrowserTest - Programmatic",
             "version": "1.0",
             "manifest_version": 2,
-            "permissions": [ "tabs", "<all_urls>" ],
+            "permissions": [ "tabs", "<all_urls>", "storage" ],
             "background": {"scripts": ["background_script.js"]}
           } )";
       dir.WriteManifest(kManifestTemplate);
       dir.WriteFile(FILE_PATH_LITERAL("background_script.js"), "");
       return LoadExtension(dir.UnpackedPath());
     };
+
     TestExtensionDir active_dir;
     TestExtensionDir spoofed_dir;
     active_extension_ = install_extension(active_dir);
@@ -276,6 +323,31 @@
     ASSERT_NE(active_extension_id(), spoofed_extension_id());
   }
 
+  const Extension* active_extension_ = nullptr;
+  const Extension* spoofed_extension_ = nullptr;
+};
+
+// Test suite for covering ExtensionHostMsg_OpenChannelToExtension IPC.
+class OpenChannelToExtensionExploitTest
+    : public ExtensionSecurityExploitBrowserTest {
+ public:
+  OpenChannelToExtensionExploitTest() = default;
+
+  void SetUpOnMainThread() override {
+    ExtensionSecurityExploitBrowserTest::SetUpOnMainThread();
+
+    GURL test_page_url =
+        embedded_test_server()->GetURL("foo.com", "/title1.html");
+    ipc_message_waiter_ = StartInterceptingIpcs(test_page_url);
+  }
+
+  // Waits for ExtensionHostMsg_OpenChannelToExtension IPC and returns its
+  // payload.
+  ExtensionHostMsg_OpenChannelToExtension::Param WaitForMessage() {
+    return ipc_message_waiter_->WaitForMessage();
+  }
+
+ private:
   using OpenChannelMessageWaiter =
       ExtensionMessageWaiter<ExtensionHostMsg_OpenChannelToExtension>;
   std::unique_ptr<OpenChannelMessageWaiter> StartInterceptingIpcs(
@@ -300,7 +372,7 @@
 
     // Only intercept messages from `active_extension`'s content script running
     // in the main frame's process.
-    std::string matching_extension_id = active_extension_id();
+    ExtensionId matching_extension_id = active_extension_id();
     int matching_process_id = new_process_id;
     ipc_message_waiter->SetIpcMatcher(base::BindLambdaForTesting(
         [matching_extension_id, matching_process_id](
@@ -494,4 +566,53 @@
             kill_waiter.Wait());
 }
 
+IN_PROC_BROWSER_TEST_F(ExtensionSecurityExploitBrowserTest,
+                       SpoofedExtensionId_ExtensionFunctionDispatcher) {
+  // Navigate to a test page.
+  GURL test_page_url =
+      embedded_test_server()->GetURL("foo.com", "/title1.html");
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame();
+
+  // Verify the test setup by checking if the non-intercepted `chrome.storage`
+  // API call will succeed.
+  {
+    ExtensionTestMessageListener listener("Got chrome.storage response");
+    ExecuteProgrammaticContentScript(web_contents, active_extension_id(), R"(
+          chrome.storage.local.set(
+              { test_key: 'test value'},
+              () => {
+                  chrome.test.sendMessage('Got chrome.storage response');
+              }
+          ); )");
+    ASSERT_TRUE(listener.WaitUntilSatisfied());
+  }
+
+  // Prepare to mutate the extension id in the IPC associated with the
+  // `chrome.storage.local.set`.
+  auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
+      main_frame,
+      base::BindLambdaForTesting([this](mojom::RequestParams& request_params) {
+        if (request_params.name != "storage.set")
+          return;
+
+        EXPECT_EQ(active_extension_id(), request_params.extension_id);
+        request_params.extension_id = spoofed_extension_id();
+      }));
+
+  // Trigger an IPC associated with the `chrome.storage.local.set` API and
+  // verify that the mutated/spoofed extension id is detected and leads to
+  // terminating the misbehaving renderer process.
+  content::RenderProcessHostBadMojoMessageWaiter kill_waiter(
+      main_frame->GetProcess());
+  ExecuteProgrammaticContentScript(web_contents, active_extension_id(), R"(
+          chrome.storage.local.set({ test_key: 'test value2'}, () => {}); )");
+  EXPECT_EQ(
+      "Received bad user message: LocalFrameHost::Request: renderer never "
+      "hosted such extension",
+      kill_waiter.Wait());
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/menu_manager_unittest.cc b/chrome/browser/extensions/menu_manager_unittest.cc
index d6f4238..6bd7a08a 100644
--- a/chrome/browser/extensions/menu_manager_unittest.cc
+++ b/chrome/browser/extensions/menu_manager_unittest.cc
@@ -494,19 +494,18 @@
   MOCK_METHOD6(DispatchEventToExtensionMock,
                void(const std::string& extension_id,
                     const std::string& event_name,
-                    base::ListValue* event_args,
+                    base::Value::List* event_args,
                     content::BrowserContext* source_context,
                     const GURL& event_url,
                     EventRouter::UserGestureState state));
 
   void DispatchEventToExtension(const std::string& extension_id,
                                 std::unique_ptr<Event> event) override {
-    DispatchEventToExtensionMock(extension_id,
-                                 event->event_name,
-                                 event->event_args.release(),
-                                 event->restrict_to_browser_context,
-                                 event->event_url,
-                                 event->user_gesture);
+    DispatchEventToExtensionMock(
+        extension_id, event->event_name,
+        new base::Value::List(std::move(event->event_args)),
+        event->restrict_to_browser_context, event->event_url,
+        event->user_gesture);
   }
 };
 
@@ -600,7 +599,7 @@
 
   // Use the magic of googlemock to save a parameter to our mock's
   // DispatchEventToExtension method into event_args.
-  base::ListValue* list = NULL;
+  base::Value::List* list = nullptr;
   {
     InSequence s;
     EXPECT_CALL(*mock_event_router,
@@ -620,9 +619,9 @@
   manager_.ExecuteCommand(&profile, nullptr /* web_contents */,
                           nullptr /* render_frame_host */, params, id);
 
-  ASSERT_EQ(2u, list->GetListDeprecated().size());
+  ASSERT_EQ(2u, list->size());
 
-  const base::Value& info = list->GetListDeprecated()[0];
+  const base::Value& info = (*list)[0];
   ASSERT_TRUE(info.is_dict());
 
   ASSERT_EQ(id.uid, info.FindIntKey("menuItemId"));
diff --git a/chrome/browser/fast_checkout/fast_checkout_client.cc b/chrome/browser/fast_checkout/fast_checkout_client.cc
new file mode 100644
index 0000000..9f439a96
--- /dev/null
+++ b/chrome/browser/fast_checkout/fast_checkout_client.cc
@@ -0,0 +1,14 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/fast_checkout/fast_checkout_client.h"
+
+#include "chrome/browser/fast_checkout/fast_checkout_client_impl.h"
+
+// static
+FastCheckoutClient* FastCheckoutClient::GetOrCreateForWebContents(
+    content::WebContents* web_contents) {
+  FastCheckoutClientImpl::CreateForWebContents(web_contents);
+  return FastCheckoutClientImpl::FromWebContents(web_contents);
+}
diff --git a/chrome/browser/fast_checkout/fast_checkout_client.h b/chrome/browser/fast_checkout/fast_checkout_client.h
new file mode 100644
index 0000000..906b7be
--- /dev/null
+++ b/chrome/browser/fast_checkout/fast_checkout_client.h
@@ -0,0 +1,38 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_FAST_CHECKOUT_FAST_CHECKOUT_CLIENT_H_
+#define CHROME_BROWSER_FAST_CHECKOUT_FAST_CHECKOUT_CLIENT_H_
+
+class GURL;
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+// Abstract interface for handling a fast checkout run.
+class FastCheckoutClient {
+ public:
+  FastCheckoutClient(const FastCheckoutClient&) = delete;
+  FastCheckoutClient& operator=(const FastCheckoutClient&) = delete;
+
+  // Factory method for creating a `FastCheckoutClient` instance.
+  static FastCheckoutClient* GetOrCreateForWebContents(
+      content::WebContents* web_contents);
+
+  // Starts the fast checkout run. Returns true if the run was successful.
+  virtual bool Start(const GURL& url) = 0;
+
+  // Stops the fast checkout run.
+  virtual void Stop() = 0;
+
+  // Returns true if a fast checkout run is ongoing.
+  virtual bool IsRunning() const = 0;
+
+ protected:
+  FastCheckoutClient() = default;
+  virtual ~FastCheckoutClient() = default;
+};
+
+#endif  // CHROME_BROWSER_FAST_CHECKOUT_FAST_CHECKOUT_CLIENT_H_
diff --git a/chrome/browser/fast_checkout/fast_checkout_client_impl.cc b/chrome/browser/fast_checkout/fast_checkout_client_impl.cc
new file mode 100644
index 0000000..ecfb307e
--- /dev/null
+++ b/chrome/browser/fast_checkout/fast_checkout_client_impl.cc
@@ -0,0 +1,90 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/fast_checkout/fast_checkout_client_impl.h"
+#include "base/feature_list.h"
+#include "chrome/browser/autofill_assistant/common_dependencies_chrome.h"
+#include "chrome/browser/fast_checkout/fast_checkout_external_action_delegate.h"
+#include "chrome/browser/fast_checkout/fast_checkout_features.h"
+#include "components/autofill_assistant/browser/public/autofill_assistant_factory.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace {
+// TODO(crbug.com/1338820): Remove these values from here once exposed in
+// autofill_assistant/browser/public.
+constexpr char kIntent[] = "INTENT";
+constexpr char kOriginalDeeplinkParameterName[] = "ORIGINAL_DEEPLINK";
+constexpr char kEnabledParameterName[] = "ENABLED";
+constexpr char kStartImmediatelyParameterName[] = "START_IMMEDIATELY";
+constexpr char kCallerParameterName[] = "CALLER";
+constexpr char kSourceParameterName[] = "SOURCE";
+
+constexpr char kIntentValue[] = "FAST_CHECKOUT";
+constexpr char kTrue[] = "true";
+// TODO(crbug.com/1338521): Define and specify proper caller(s) and source(s).
+constexpr char kCaller[] = "7";  // run was started from within Chromium
+constexpr char kSource[] = "1";  // run was started organically
+}  // namespace
+
+FastCheckoutClientImpl::FastCheckoutClientImpl(
+    content::WebContents* web_contents)
+    : content::WebContentsUserData<FastCheckoutClientImpl>(*web_contents) {}
+
+FastCheckoutClientImpl::~FastCheckoutClientImpl() = default;
+
+bool FastCheckoutClientImpl::Start(const GURL& url) {
+  // TODO(crbug.com/1338507): Don't run if onboarding was not successful.
+
+  if (!base::FeatureList::IsEnabled(features::kFastCheckout))
+    return false;
+
+  if (is_running_)
+    return false;
+
+  is_running_ = true;
+
+  base::flat_map<std::string, std::string> params_map;
+  params_map[kIntent] = kIntentValue;
+  params_map[kOriginalDeeplinkParameterName] = url.spec();
+  params_map[kEnabledParameterName] = kTrue;
+  params_map[kStartImmediatelyParameterName] = kTrue;
+  params_map[kCallerParameterName] = kCaller;
+  params_map[kSourceParameterName] = kSource;
+
+  external_script_controller_ = CreateHeadlessScriptController();
+  external_script_controller_->StartScript(
+      params_map, base::BindOnce(&FastCheckoutClientImpl::OnRunComplete,
+                                 base::Unretained(this)));
+
+  return true;
+}
+
+void FastCheckoutClientImpl::OnRunComplete(
+    autofill_assistant::HeadlessScriptController::ScriptResult result) {
+  // TODO(crbug.com/1338522): Handle failed result.
+  Stop();
+}
+
+void FastCheckoutClientImpl::Stop() {
+  external_script_controller_.reset();
+  is_running_ = false;
+}
+
+bool FastCheckoutClientImpl::IsRunning() const {
+  return is_running_;
+}
+
+std::unique_ptr<autofill_assistant::HeadlessScriptController>
+FastCheckoutClientImpl::CreateHeadlessScriptController() {
+  fast_checkout_external_action_delegate_ =
+      std::make_unique<FastCheckoutExternalActionDelegate>();
+  std::unique_ptr<autofill_assistant::AutofillAssistant> autofill_assistant =
+      autofill_assistant::AutofillAssistantFactory::CreateForBrowserContext(
+          GetWebContents().GetBrowserContext(),
+          std::make_unique<autofill_assistant::CommonDependenciesChrome>());
+  return autofill_assistant->CreateHeadlessScriptController(
+      &GetWebContents(), fast_checkout_external_action_delegate_.get());
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(FastCheckoutClientImpl);
diff --git a/chrome/browser/fast_checkout/fast_checkout_client_impl.h b/chrome/browser/fast_checkout/fast_checkout_client_impl.h
new file mode 100644
index 0000000..060b6015
--- /dev/null
+++ b/chrome/browser/fast_checkout/fast_checkout_client_impl.h
@@ -0,0 +1,61 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_FAST_CHECKOUT_FAST_CHECKOUT_CLIENT_IMPL_H_
+#define CHROME_BROWSER_FAST_CHECKOUT_FAST_CHECKOUT_CLIENT_IMPL_H_
+
+#include "chrome/browser/fast_checkout/fast_checkout_client.h"
+#include "components/autofill_assistant/browser/public/headless_script_controller.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+class FastCheckoutExternalActionDelegate;
+
+// TODO(crbug.com/1338528): Add unit tests.
+class FastCheckoutClientImpl
+    : public content::WebContentsUserData<FastCheckoutClientImpl>,
+      public FastCheckoutClient {
+ public:
+  ~FastCheckoutClientImpl() override;
+
+  FastCheckoutClientImpl(const FastCheckoutClientImpl&) = delete;
+  FastCheckoutClientImpl& operator=(const FastCheckoutClientImpl&) = delete;
+
+  // FastCheckoutClient:
+  bool Start(const GURL& url) override;
+  void Stop() override;
+  bool IsRunning() const override;
+
+ private:
+  friend class content::WebContentsUserData<FastCheckoutClientImpl>;
+
+  explicit FastCheckoutClientImpl(content::WebContents* web_contents);
+
+  // Creates the external action deglegate and script controller.
+  std::unique_ptr<autofill_assistant::HeadlessScriptController>
+  CreateHeadlessScriptController();
+
+  // Registers when a run is complete. Used in callbacks.
+  void OnRunComplete(
+      autofill_assistant::HeadlessScriptController::ScriptResult result);
+
+  // The delegate is responsible for handling protos received from backend DSL
+  // actions.
+  std::unique_ptr<FastCheckoutExternalActionDelegate>
+      fast_checkout_external_action_delegate_;
+
+  // Controls a script run triggered by the headless API. This class is
+  // responsible for handling the forwarding of actions to
+  // `apc_external_action_delegate_` and managing the run lifetime.
+  std::unique_ptr<autofill_assistant::HeadlessScriptController>
+      external_script_controller_;
+
+  // True if a run is ongoing; used to avoid multiple runs in parallel.
+  bool is_running_ = false;
+
+  // content::WebContentsUserData:
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+};
+
+#endif  // CHROME_BROWSER_FAST_CHECKOUT_FAST_CHECKOUT_CLIENT_IMPL_H_
diff --git a/chrome/browser/fast_checkout/fast_checkout_external_action_delegate.cc b/chrome/browser/fast_checkout/fast_checkout_external_action_delegate.cc
new file mode 100644
index 0000000..cdc32db
--- /dev/null
+++ b/chrome/browser/fast_checkout/fast_checkout_external_action_delegate.cc
@@ -0,0 +1,24 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/fast_checkout/fast_checkout_external_action_delegate.h"
+
+FastCheckoutExternalActionDelegate::~FastCheckoutExternalActionDelegate() =
+    default;
+
+void FastCheckoutExternalActionDelegate::OnActionRequested(
+    const autofill_assistant::external::Action& action_info,
+    base::OnceCallback<void(DomUpdateCallback)> start_dom_checks_callback,
+    base::OnceCallback<void(const autofill_assistant::external::Result&)>
+        end_action_callback) {
+  // TODO(crbug.com/1338523): Implement.
+}
+
+void FastCheckoutExternalActionDelegate::OnInterruptStarted() {
+  // TODO(crbug.com/1338523): Implement.
+}
+
+void FastCheckoutExternalActionDelegate::OnInterruptFinished() {
+  // TODO(crbug.com/1338523): Implement.
+}
diff --git a/chrome/browser/fast_checkout/fast_checkout_external_action_delegate.h b/chrome/browser/fast_checkout/fast_checkout_external_action_delegate.h
new file mode 100644
index 0000000..b5a4cfd
--- /dev/null
+++ b/chrome/browser/fast_checkout/fast_checkout_external_action_delegate.h
@@ -0,0 +1,36 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_FAST_CHECKOUT_FAST_CHECKOUT_EXTERNAL_ACTION_DELEGATE_H_
+#define CHROME_BROWSER_FAST_CHECKOUT_FAST_CHECKOUT_EXTERNAL_ACTION_DELEGATE_H_
+
+#include "components/autofill_assistant/browser/public/autofill_assistant.h"
+#include "content/public/browser/web_contents.h"
+
+// TODO(crbug.com/1338529): Add unit tests.
+
+// Handles external actions defined for fast checkout.
+class FastCheckoutExternalActionDelegate
+    : public autofill_assistant::ExternalActionDelegate {
+ public:
+  FastCheckoutExternalActionDelegate() = default;
+  ~FastCheckoutExternalActionDelegate() override;
+
+  FastCheckoutExternalActionDelegate(
+      const FastCheckoutExternalActionDelegate&) = delete;
+  FastCheckoutExternalActionDelegate& operator=(
+      const FastCheckoutExternalActionDelegate&) = delete;
+
+  // ExternalActionDelegate:
+  void OnActionRequested(
+      const autofill_assistant::external::Action& action_info,
+      base::OnceCallback<void(DomUpdateCallback)> start_dom_checks_callback,
+      base::OnceCallback<void(const autofill_assistant::external::Result&)>
+          end_action_callback) override;
+
+  void OnInterruptStarted() override;
+  void OnInterruptFinished() override;
+};
+
+#endif  // CHROME_BROWSER_FAST_CHECKOUT_FAST_CHECKOUT_EXTERNAL_ACTION_DELEGATE_H_
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/CardMenuBottomSheetContent.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/CardMenuBottomSheetContent.java
index 61ae3756..e3454c6 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/CardMenuBottomSheetContent.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/CardMenuBottomSheetContent.java
@@ -60,11 +60,6 @@
     }
 
     @Override
-    public boolean handleBackPress() {
-        return false;
-    }
-
-    @Override
     public int getSheetContentDescriptionStringId() {
         return R.string.feed_card_menu_description;
     }
diff --git a/chrome/browser/feedback/android/BUILD.gn b/chrome/browser/feedback/android/BUILD.gn
index a6b260fbe..f6bff05e 100644
--- a/chrome/browser/feedback/android/BUILD.gn
+++ b/chrome/browser/feedback/android/BUILD.gn
@@ -6,6 +6,7 @@
 
 generate_jni("jni_headers") {
   sources = [
+    "java/src/org/chromium/chrome/browser/feedback/FamilyInfoFeedbackSource.java",
     "java/src/org/chromium/chrome/browser/feedback/ProcessIdFeedbackSource.java",
     "java/src/org/chromium/chrome/browser/feedback/SystemInfoFeedbackSource.java",
   ]
@@ -30,6 +31,7 @@
     "java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSource.java",
     "java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSourceAdapter.java",
     "java/src/org/chromium/chrome/browser/feedback/DeviceInfoFeedbackSource.java",
+    "java/src/org/chromium/chrome/browser/feedback/FamilyInfoFeedbackSource.java",
     "java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java",
     "java/src/org/chromium/chrome/browser/feedback/FeedbackContextFeedbackSource.java",
     "java/src/org/chromium/chrome/browser/feedback/FeedbackReporter.java",
@@ -54,9 +56,7 @@
     "//base:jni_java",
     "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
-    "//chrome/browser/signin/services/android:java",
     "//components/browser_ui/util/android:java",
-    "//components/signin/public/android:java",
     "//components/variations/android:variations_java",
     "//content/public/android:content_java",
     "//net/android:net_java",
diff --git a/chrome/browser/feedback/android/family_info_feedback_source.cc b/chrome/browser/feedback/android/family_info_feedback_source.cc
new file mode 100644
index 0000000..63d66c7
--- /dev/null
+++ b/chrome/browser/feedback/android/family_info_feedback_source.cc
@@ -0,0 +1,90 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/feedback/android/family_info_feedback_source.h"
+
+#include "base/android/jni_string.h"
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "chrome/browser/feedback/android/jni_headers/FamilyInfoFeedbackSource_jni.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_android.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
+#include "chrome/browser/supervised_user/child_accounts/child_account_service_factory.h"
+#include "content/public/browser/storage_partition.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+using FamilyMemberRole = FamilyInfoFetcher::FamilyMemberRole;
+
+namespace chrome::android {
+namespace {
+
+// User visible role name for FamilyMember::HEAD_OF_HOUSEHOLD.
+const char kFamilyManagerRole[] = "family_manager";
+
+}  // namespace
+
+void JNI_FamilyInfoFeedbackSource_Start(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jobject>& j_profile) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
+  FamilyInfoFeedbackSource* feedback_source =
+      new FamilyInfoFeedbackSource(obj, profile);
+  feedback_source->GetFamilyMembers();
+}
+
+FamilyInfoFeedbackSource::FamilyInfoFeedbackSource(
+    const JavaParamRef<jobject>& obj,
+    Profile* profile)
+    : identity_manager_(IdentityManagerFactory::GetForProfile(profile)),
+      url_loader_factory_(profile->GetDefaultStoragePartition()
+                              ->GetURLLoaderFactoryForBrowserProcess()),
+      java_ref_(obj) {}
+
+FamilyInfoFeedbackSource::~FamilyInfoFeedbackSource() = default;
+
+void FamilyInfoFeedbackSource::GetFamilyMembers() {
+  family_fetcher_ = std::make_unique<FamilyInfoFetcher>(this, identity_manager_,
+                                                        url_loader_factory_);
+  family_fetcher_->StartGetFamilyMembers();
+}
+
+void FamilyInfoFeedbackSource::OnGetFamilyMembersSuccess(
+    const std::vector<FamilyInfoFetcher::FamilyMember>& members) {
+  std::string primary_account_gaia =
+      identity_manager_->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)
+          .gaia;
+
+  JNIEnv* env = AttachCurrentThread();
+  for (const FamilyInfoFetcher::FamilyMember& member : members) {
+    // Store the family member role for the primary account of the profile.
+    if (primary_account_gaia == member.obfuscated_gaia_id) {
+      std::string role = member.role == FamilyMemberRole::HEAD_OF_HOUSEHOLD
+                             ? kFamilyManagerRole
+                             : FamilyInfoFetcher::RoleToString(member.role);
+      Java_FamilyInfoFeedbackSource_processFamilyMemberRole(
+          env, java_ref_, ConvertUTF8ToJavaString(env, role));
+    }
+  }
+  OnGetFamilyMembersCompletion();
+}
+
+void FamilyInfoFeedbackSource::OnFailure(FamilyInfoFetcher::ErrorCode error) {
+  DLOG(WARNING) << "GetFamilyMembers failed with code "
+                << static_cast<int>(error);
+  OnGetFamilyMembersCompletion();
+}
+
+void FamilyInfoFeedbackSource::OnGetFamilyMembersCompletion() {
+  // Object will delete itself following the fetch to GetFamilyMembers.
+  delete this;
+}
+
+}  // namespace chrome::android
diff --git a/chrome/browser/feedback/android/family_info_feedback_source.h b/chrome/browser/feedback/android/family_info_feedback_source.h
new file mode 100644
index 0000000..cd8ce0d
--- /dev/null
+++ b/chrome/browser/feedback/android/family_info_feedback_source.h
@@ -0,0 +1,56 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_FEEDBACK_ANDROID_FAMILY_INFO_FEEDBACK_SOURCE_H_
+#define CHROME_BROWSER_FEEDBACK_ANDROID_FAMILY_INFO_FEEDBACK_SOURCE_H_
+
+#include <map>
+#include <memory>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/raw_ptr.h"
+#include "base/process/process_handle.h"
+#include "chrome/browser/supervised_user/child_accounts/family_info_fetcher.h"
+
+class Profile;
+
+namespace network {
+class SharedURLLoaderFactory;
+}  // namespace network
+
+namespace chrome::android {
+
+// Native class for Java counterpart. Retrieves family information
+// asynchronously.
+class FamilyInfoFeedbackSource : public FamilyInfoFetcher::Consumer {
+ public:
+  FamilyInfoFeedbackSource(const base::android::JavaParamRef<jobject>& obj,
+                           Profile* profile);
+
+  FamilyInfoFeedbackSource(const FamilyInfoFeedbackSource&) = delete;
+  FamilyInfoFeedbackSource& operator=(const FamilyInfoFeedbackSource&) = delete;
+  ~FamilyInfoFeedbackSource() override;
+
+  // Retrieves a list of family members for the primary account.
+  void GetFamilyMembers();
+
+ private:
+  // FamilyInfoFetcher::Consumer implementation.
+  void OnGetFamilyMembersSuccess(
+      const std::vector<FamilyInfoFetcher::FamilyMember>& members) override;
+  void OnFailure(FamilyInfoFetcher::ErrorCode error) override;
+
+  // Performs completion following call to GetFamilyMembers.
+  void OnGetFamilyMembersCompletion();
+
+  std::unique_ptr<FamilyInfoFetcher> family_fetcher_;
+  raw_ptr<signin::IdentityManager> identity_manager_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+  base::android::ScopedJavaGlobalRef<jobject> java_ref_;
+};
+
+}  // namespace chrome::android
+
+#endif  // CHROME_BROWSER_FEEDBACK_ANDROID_FAMILY_INFO_FEEDBACK_SOURCE_H_
diff --git a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FamilyInfoFeedbackSource.java b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FamilyInfoFeedbackSource.java
new file mode 100644
index 0000000..0e19a55e
--- /dev/null
+++ b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FamilyInfoFeedbackSource.java
@@ -0,0 +1,61 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.feedback;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
+import org.chromium.chrome.browser.profiles.Profile;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** Reports profile settings for users in a family group. */
+@JNINamespace("chrome::android")
+public class FamilyInfoFeedbackSource implements AsyncFeedbackSource {
+    private static final String FAMILY_MEMBER_ROLE = "Family_Member_Role";
+
+    private final Profile mProfile;
+    private Map<String, String> mFeedbackMap;
+    private boolean mIsReady;
+    private Runnable mCallback;
+
+    FamilyInfoFeedbackSource(Profile profile) {
+        mProfile = profile;
+    }
+
+    // AsyncFeedbackSource implementation.
+    @Override
+    public void start(final Runnable callback) {
+        mCallback = callback;
+        mFeedbackMap = new HashMap<>();
+        FamilyInfoFeedbackSourceJni.get().start(this, mProfile);
+    }
+
+    @CalledByNative
+    private void processFamilyMemberRole(String familyRole) {
+        // Adds a family role only if the user is enrolled in a Family group.
+        if (!familyRole.isEmpty()) {
+            mFeedbackMap.put(FAMILY_MEMBER_ROLE, familyRole);
+        }
+        mIsReady = true;
+        mCallback.run();
+    }
+
+    @Override
+    public boolean isReady() {
+        return mIsReady;
+    }
+
+    @Override
+    public Map<String, String> getFeedback() {
+        return mFeedbackMap;
+    }
+
+    @NativeMethods
+    interface Natives {
+        void start(FamilyInfoFeedbackSource source, Profile profile);
+    }
+}
diff --git a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java
index 066a46b..b885734 100644
--- a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java
+++ b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java
@@ -18,10 +18,6 @@
 import org.chromium.base.CollectionUtil;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.task.PostTask;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
-import org.chromium.components.signin.base.CoreAccountInfo;
-import org.chromium.components.signin.identitymanager.ConsentLevel;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
 import java.util.HashMap;
@@ -40,7 +36,6 @@
 
     private final String mCategoryTag;
     private final String mDescription;
-    private String mAccountInUse;
 
     private List<FeedbackSource> mSynchronousSources;
     private List<AsyncFeedbackSource> mAsynchronousSources;
@@ -58,15 +53,11 @@
     }
 
     // Subclasses must invoke init() at construction time.
-    protected void init(Activity activity, @Nullable ScreenshotSource screenshotTask, T initParams,
-            Profile profile) {
-        // 1. Build all synchronous and asynchronous sources and determine the currently signed in
-        //    account.
+    protected void init(
+            Activity activity, @Nullable ScreenshotSource screenshotTask, T initParams) {
+        // 1. Build all synchronous and asynchronous sources.
         mSynchronousSources = buildSynchronousFeedbackSources(activity, initParams);
         mAsynchronousSources = buildAsynchronousFeedbackSources(initParams);
-        mAccountInUse = CoreAccountInfo.getEmailFrom(
-                IdentityServicesProvider.get().getIdentityManager(profile).getPrimaryAccountInfo(
-                        ConsentLevel.SIGNIN));
 
         // Sanity check in case a source is added to the wrong list.
         for (FeedbackSource source : mSynchronousSources) {
@@ -106,11 +97,6 @@
         return mDescription;
     }
 
-    /** @return The currently signed in account, or null if the user is not signed in. */
-    public @Nullable String getAccountInUse() {
-        return mAccountInUse;
-    }
-
     /**
      * Deprecated.  Please use {@link #getLogs()} instead for all potentially large feedback data.
      * @return Returns the histogram data from {@link #getLogs()}.
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index bc44710..937d5d14 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -380,6 +380,11 @@
     "expiry_milestone": 90
   },
   {
+    "name": "autocomplete-extended-suggestions",
+    "owners": [ "yulunwu", "etuck" ],
+    "expiry_milestone": 107
+  },
+  {
     "name": "autofill-address-save-prompt",
     "owners": [ "mamir", "koerber" ],
     "expiry_milestone": 106
@@ -2384,7 +2389,7 @@
     "owners": [
       "wicarr@microsoft.com"
     ],
-    "expiry_milestone": 103
+    "expiry_milestone": 110
   },
   {
     "name": "enable-media-foundation-video-capture",
@@ -3879,14 +3884,6 @@
     "expiry_milestone": 130
   },
   {
-    "name": "lacros-non-syncing-profiles",
-    "owners": [ "jkrcal", "droger", "chrome-signin@google.com" ],
-    // Once Lacros is launched, this flag can be removed. Until then, this
-    // absolutely must not expire. We do not yet have a launch milestone.
-    // TODO(https://crbug.com/1148474).
-    "expiry_milestone": 130
-  },
-  {
     "name": "lacros-only",
     "owners": [ "hidehiko", "erikchen", "lacros-team@google.com" ],
     // Once Lacros is launched, this flag can be removed. Until then, this
@@ -5202,6 +5199,11 @@
     "expiry_milestone": 106
   },
   {
+    "name": "quick-intensive-throttling-after-loading",
+    "owners": [ "jiahe.zhang@intel.com", "fdoray" ],
+    "expiry_milestone": 110
+  },
+  {
     "name": "quick-settings-network-revamp",
     "owners": [ "chadduffin", "khorimoto", "cros-connectivity@google.com" ],
     "expiry_milestone": 110
@@ -5535,12 +5537,7 @@
   {
     "name": "shelf-palm-rejection-swipe-offset",
     "owners": ["anasalazar", "//ash/shelf/OWNERS"],
-    "expiry_milestone": 105
-  },
-  {
-    "name": "shelf-palm-rejection-touch-area",
-    "owners": ["anasalazar", "//ash/shelf/OWNERS"],
-    "expiry_milestone": 105
+    "expiry_milestone": 107
   },
   {
     "name": "shimless-rma-disable-dark-mode",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 882748d..a006fc3 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2270,6 +2270,16 @@
     "enabled and disabled from the Smart privacy section of your device "
     "settings.";
 
+const char kQuickIntensiveWakeUpThrottlingAfterLoadingName[] =
+    "Quick intensive throttling after loading";
+const char kQuickIntensiveWakeUpThrottlingAfterLoadingDescription[] =
+    "For pages that are loaded when backgrounded, activates intensive "
+    "throttling after 10 seconds instead of the default 5 minutes. Intensive "
+    "throttling will limit wake ups, from setTimeout and setInterval tasks "
+    "with a high nesting level and delayed scheduler.postTask tasks, to 1 per "
+    "minute. See https://chromestatus.com/feature/5580139453743104 for more "
+    "info.";
+
 const char kSettingsAppNotificationSettingsName[] =
     "Split notification permission settings";
 const char kSettingsAppNotificationSettingsDescription[] =
@@ -2418,14 +2428,8 @@
     "Shelf Palm Rejection: Swipe Offset";
 const char kShelfPalmRejectionSwipeOffsetDescription[] =
     "Enables palm rejection in the shelf by setting an offset for the swipe "
-    "gesture that drags the hotseat to a extended state.";
-
-const char kShelfPalmRejectionTouchAreaName[] =
-    "Shelf Palm Rejection: Touch Area";
-const char kShelfPalmRejectionTouchAreaDescription[] =
-    "Enables palm rejection in the shelf by setting the touch area size within "
-    "the shelf for triggering the swipe gesture that drags the hotseat to a "
-    "extended state.";
+    "gesture that drags the hotseat to a extended state for certain stylus "
+    "apps.";
 
 const char kShowAutofillSignaturesName[] = "Show autofill signatures.";
 const char kShowAutofillSignaturesDescription[] =
@@ -4353,6 +4357,11 @@
     "Overrides the default to forcibly enable or disable the auto-framing "
     "feature";
 
+const char kAutocompleteExtendedSuggestionsName[] =
+    "Extended suggestions for CrOS autocomplete";
+const char kAutocompleteExtendedSuggestionsDescription[] =
+    "Enables extended autocomplete suggestions experiment on ChromeOS.";
+
 const char kAutocorrectParamsTuningName[] = "CrOS autocorrect params tuning";
 const char kAutocorrectParamsTuningDescription[] =
     "Enables params tuning experiment for autocorrect on ChromeOS.";
@@ -5688,11 +5697,6 @@
 const char kLacrosMergeIcuDataFileDescription[] =
     "Enables sharing common areas of icudtl.dat between Ash and Lacros.";
 
-const char kLacrosNonSyncingProfilesName[] =
-    "Enable non-syncing profiles on lacros";
-const char kLacrosNonSyncingProfilesDescription[] =
-    "Enables further types of profiles: (1) local, (2) signed-in non-syncing.";
-
 const char kLacrosScreenCoordinatesEnabledName[] =
     "Enable screen coordinates system in lacros-chrome";
 const char kLacrosScreenCoordinatesEnabledDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index d94828b..952a24e 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1273,6 +1273,9 @@
 extern const char kQuickDimName[];
 extern const char kQuickDimDescription[];
 
+extern const char kQuickIntensiveWakeUpThrottlingAfterLoadingName[];
+extern const char kQuickIntensiveWakeUpThrottlingAfterLoadingDescription[];
+
 extern const char kSettingsAppNotificationSettingsName[];
 extern const char kSettingsAppNotificationSettingsDescription[];
 
@@ -1363,9 +1366,6 @@
 extern const char kShelfPalmRejectionSwipeOffsetName[];
 extern const char kShelfPalmRejectionSwipeOffsetDescription[];
 
-extern const char kShelfPalmRejectionTouchAreaName[];
-extern const char kShelfPalmRejectionTouchAreaDescription[];
-
 extern const char kShowAutofillSignaturesName[];
 extern const char kShowAutofillSignaturesDescription[];
 
@@ -2492,6 +2492,9 @@
 extern const char kAutoFramingOverrideName[];
 extern const char kAutoFramingOverrideDescription[];
 
+extern const char kAutocompleteExtendedSuggestionsName[];
+extern const char kAutocompleteExtendedSuggestionsDescription[];
+
 extern const char kAutocorrectParamsTuningName[];
 extern const char kAutocorrectParamsTuningDescription[];
 
@@ -3263,9 +3266,6 @@
 extern const char kLacrosMergeIcuDataFileName[];
 extern const char kLacrosMergeIcuDataFileDescription[];
 
-extern const char kLacrosNonSyncingProfilesName[];
-extern const char kLacrosNonSyncingProfilesDescription[];
-
 extern const char kLacrosScreenCoordinatesEnabledName[];
 extern const char kLacrosScreenCoordinatesEnabledDescription[];
 #endif  // #if BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 293ce4a1..98cf3166 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -219,6 +219,7 @@
     &kContextualTriggersSelectionHandles,
     &kContextualTriggersSelectionMenu,
     &kContextualTriggersSelectionSize,
+    &kDelayToolbarUpdateOnLoadStarted,
     &kDirectActions,
     &kDisableCompositedProgressBar,
     &kDownloadFileProvider,
@@ -416,10 +417,10 @@
 
 const base::Feature kAdaptiveButtonInTopToolbarCustomizationV2{
     "AdaptiveButtonInTopToolbarCustomizationV2",
-    base::FEATURE_DISABLED_BY_DEFAULT};
+    base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kAddToHomescreenIPH{"AddToHomescreenIPH",
-                                        base::FEATURE_DISABLED_BY_DEFAULT};
+                                        base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kAllowNewIncognitoTabIntents{
     "AllowNewIncognitoTabIntents", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -618,6 +619,9 @@
 const base::Feature kContextualTriggersSelectionSize{
     "ContextualTriggersSelectionSize", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kDelayToolbarUpdateOnLoadStarted{
+    "DelayToolbarUpdateOnLoadStarted", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kDirectActions{"DirectActions",
                                    base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index b9326af..f8db579 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -79,6 +79,7 @@
 extern const base::Feature kContextualTriggersSelectionHandles;
 extern const base::Feature kContextualTriggersSelectionMenu;
 extern const base::Feature kContextualTriggersSelectionSize;
+extern const base::Feature kDelayToolbarUpdateOnLoadStarted;
 extern const base::Feature kDirectActions;
 extern const base::Feature kDisableCompositedProgressBar;
 extern const base::Feature kDontPrefetchLibraries;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
index 3fbd637..33684432 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
@@ -57,6 +57,7 @@
                     .put(ChromeFeatureList.CCT_RESIZABLE_90_MAXIMUM_HEIGHT, false)
                     .put(ChromeFeatureList.CCT_RESIZABLE_ALLOW_RESIZE_BY_USER_GESTURE, false)
                     .put(ChromeFeatureList.CCT_RESIZABLE_FOR_FIRST_PARTIES, true)
+                    .put(ChromeFeatureList.COMMERCE_COUPONS, false)
                     .put(ChromeFeatureList.CCT_RESIZABLE_FOR_THIRD_PARTIES, false)
                     .put(ChromeFeatureList.CCT_TOOLBAR_CUSTOMIZATIONS, true)
                     .put(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS, false)
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 6cf410e3..26b0de08 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -323,6 +323,8 @@
     public static final String CRITICAL_PERSISTED_TAB_DATA = "CriticalPersistedTabData";
     public static final String DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING =
             "DarkenWebsitesCheckboxInThemesSetting";
+    public static final String DELAY_TOOLBAR_UPDATE_ON_LOAD_STARTED =
+            "DelayToolbarUpdateOnLoadStarted";
     public static final String DETAILED_LANGUAGE_SETTINGS = "DetailedLanguageSettings";
     public static final String DIRECT_ACTIONS = "DirectActions";
     public static final String DISABLE_COMPOSITED_PROGRESS_BAR = "DisableCompositedProgressBar";
diff --git a/chrome/browser/lacros/account_manager/account_profile_mapper.cc b/chrome/browser/lacros/account_manager/account_profile_mapper.cc
index c187da5..7033db4 100644
--- a/chrome/browser/lacros/account_manager/account_profile_mapper.cc
+++ b/chrome/browser/lacros/account_manager/account_profile_mapper.cc
@@ -23,24 +23,10 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_metrics.h"
 #include "components/account_manager_core/account.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher_immediate_error.h"
 
-namespace {
-
-void DeleteProfile(const base::FilePath& profile_path,
-                   ProfileMetrics::ProfileDelete delete_metric) {
-  // Pass an empty callback because this should never delete the last profile.
-  // TODO(https://crbug.com/1257610): ensure that the user cannot cancel the
-  // profile deletion.
-  g_browser_process->profile_manager()->MaybeScheduleProfileForDeletion(
-      profile_path, base::DoNothing(), delete_metric);
-}
-
-}  // namespace
-
 AccountProfileMapper::AccountProfileMapper(
     account_manager::AccountManagerFacade* facade,
     ProfileAttributesStorage* storage,
@@ -474,8 +460,12 @@
     if (entry_needs_update)
       entry->SetGaiaIds(entry_ids);
     if (ShouldDeleteProfile(entry)) {
-      DeleteProfile(
-          entry->GetPath(),
+      // Pass an empty callback because this should never delete the last
+      // profile.
+      // TODO(https://crbug.com/1257610): ensure that the user cannot cancel the
+      // profile deletion.
+      g_browser_process->profile_manager()->MaybeScheduleProfileForDeletion(
+          entry->GetPath(), base::DoNothing(),
           ProfileMetrics::DELETE_PROFILE_PRIMARY_ACCOUNT_REMOVED_LACROS);
     }
   }
@@ -637,11 +627,6 @@
     return false;
   }
 
-  // Secondary profile.
-  if (!base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-    return primary_account_deleted;
-  }
-
   // If non syncing profiles enabled, only delete syncing managed profile.
   // For non managed profiles, the SigninManager will signout the profile if
   // there is no refresh token for the primary account as soon as the profile is
@@ -656,11 +641,10 @@
   for (ProfileAttributesEntry* entry :
        profile_attributes_storage_->GetAllProfilesAttributes()) {
     // Populate missing Gaia Ids.
-    // Note: If `kLacrosNonSyncingProfiles` is enabled, this code might
-    // re-insert the Gaia id of a profile that has not been loaded since its
-    // primary account removal from the OS (AuthInfo did not re-set).
-    // The account will be removed later if it does not exist in the OS in
-    // `RemoveStaleAccounts`.
+    // Note: this code might re-insert the Gaia id of a profile that has not
+    // been loaded since its primary account removal from the OS (AuthInfo did
+    // not re-set). The account will be removed later if it does not exist in
+    // the OS in `RemoveStaleAccounts`.
     std::string primary_gaia_id = entry->GetGAIAId();
     if (!primary_gaia_id.empty()) {
       base::flat_set<std::string> gaia_ids = entry->GetGaiaIds();
@@ -668,15 +652,6 @@
       if (inserted_result.second)
         entry->SetGaiaIds(gaia_ids);
     }
-
-    base::FilePath profile_path = entry->GetPath();
-    if (!base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles) &&
-        !entry->IsAuthenticated() &&
-        !Profile::IsMainProfilePath(profile_path)) {
-      DeleteProfile(
-          profile_path,
-          ProfileMetrics::DELETE_PROFILE_SIGNIN_REQUIRED_MIRROR_LACROS);
-    }
   }
 }
 
diff --git a/chrome/browser/lacros/account_manager/account_profile_mapper_unittest.cc b/chrome/browser/lacros/account_manager/account_profile_mapper_unittest.cc
index 3dcf1db..c96ae96b 100644
--- a/chrome/browser/lacros/account_manager/account_profile_mapper_unittest.cc
+++ b/chrome/browser/lacros/account_manager/account_profile_mapper_unittest.cc
@@ -28,7 +28,6 @@
 #include "components/account_manager_core/account_manager_facade.h"
 #include "components/account_manager_core/mock_account_manager_facade.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "content/public/test/browser_task_environment.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -822,29 +821,6 @@
   CompleteFacadeGetAccountsGaia({"A", "B"});
 }
 
-// Tests that a secondary profile gets deleted after its sync account is
-// removed from the system.
-// A secondary account of the deleted profile remains unassigned.
-TEST_F(AccountProfileMapperTest, RemovePrimaryAccountFromSecondaryProfile) {
-  // Delete this test after non syncing profiles full launch.
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndDisableFeature(
-      switches::kLacrosNonSyncingProfiles);
-  base::FilePath other_path = GetProfilePath("Other");
-  AccountProfileMapper* mapper =
-      CreateMapper({{main_path(), {"A"}}, {other_path, {"B", "C"}}});
-  SetPrimaryAccountForProfile(other_path, "B");
-  TestMapperUpdateGaia(
-      mapper,
-      /*accounts_in_facade=*/{"A", "C"},
-      /*expected_accounts_upserted=*/{{base::FilePath(), {"C"}}},
-      /*expected_accounts_removed=*/{{other_path, {"B"}}},
-      /*expected_accounts_in_prefs=*/
-      {{main_path(), {"A"}}, {base::FilePath(), {"C"}}});
-  ProfileAttributesStorageTestObserver(attributes_storage())
-      .WaitForProfileBeingDeleted(other_path);
-}
-
 // Tests that a managed syncing secondary profile gets deleted after its primary
 // account is removed from the system.
 // A secondary account of the deleted profile stays unassigned.
@@ -896,9 +872,6 @@
 // unassigned.
 TEST_F(AccountProfileMapperTest,
        RemovePrimaryAccount_ManagedSecondaryProfile_Syncing) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
-
   base::FilePath second_path = GetProfilePath("Second");
   AccountProfileMapper* mapper =
       CreateMapper({{main_path(), {"A"}}, {second_path, {"B"}}});
@@ -920,9 +893,6 @@
 // primary account is removed from the system.
 TEST_F(AccountProfileMapperTest,
        RemovePrimaryAccount_ManagedSecondaryProfile_NotSyncing) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
-
   base::FilePath second_path = GetProfilePath("Second");
   AccountProfileMapper* mapper =
       CreateMapper({{main_path(), {"A"}}, {second_path, {"B"}}});
@@ -945,9 +915,6 @@
 // is removed from the system.
 TEST_F(AccountProfileMapperTest,
        RemovePrimaryAccount_ConsumerSecondaryProfile) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
-
   base::FilePath second_path = GetProfilePath("Second");
   base::FilePath third_path = GetProfilePath("Third");
   AccountProfileMapper* mapper = CreateMapper(
@@ -978,8 +945,6 @@
 TEST_F(
     AccountProfileMapperTest,
     RemovePrimaryAccountFromSecondaryProfile_AtInitialization_EmptyLocalState) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
   base::FilePath other_path = GetProfilePath("Other");
   CreateMapperNonInitialized({{main_path(), {"A"}}, {other_path, {"B", "C"}}});
   // Clean local state.
@@ -998,8 +963,6 @@
 // A secondary account of the deleted profile remains unassigned.
 TEST_F(AccountProfileMapperTest,
        RemovePrimaryAccountFromSecondaryProfile_AtInitialization) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
   base::FilePath other_path = GetProfilePath("Other");
   CreateMapperNonInitialized({{main_path(), {"A"}}, {other_path, {"B", "C"}}});
   SetPrimaryAccountForProfile(other_path, "B",
@@ -1014,8 +977,6 @@
 // Tests that a managed syncing secondary profile doesn't get deleted after its
 // secondary account is removed from the system.
 TEST_F(AccountProfileMapperTest, RemoveSecondaryAccountFromSecondaryProfile) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
   base::FilePath other_path = GetProfilePath("Other");
   AccountProfileMapper* mapper =
       CreateMapper({{main_path(), {"A"}}, {other_path, {"B", "C"}}});
@@ -1033,8 +994,6 @@
 // Tests that the primary profile doesn't get deleted even after its primary
 // account is removed from the system.
 TEST_F(AccountProfileMapperTest, RemovePrimaryAccountFromPrimaryProfile) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
   AccountProfileMapper* mapper = CreateMapper({{main_path(), {"A", "B"}}});
   SetPrimaryAccountForProfile(main_path(), "A",
                               /*is_consented_primary_account=*/true,
@@ -1615,51 +1574,7 @@
   EXPECT_EQ(entry->GetSigninState(), SigninState::kNotSignedIn);
 }
 
-// Checks that profiles in unsupported state are deleted. If a profile has a
-// sync account, but this account is not in `GetGaiaIds()`, the account is added
-// there, which can allow keeping the profile if the account exists in the
-// facade.
-TEST_F(AccountProfileMapperTest, FixProfilesAtStartup) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndDisableFeature(
-      switches::kLacrosNonSyncingProfiles);
-
-  base::FilePath syncing_path = GetProfilePath("Syncing");
-  base::FilePath signed_out_path = GetProfilePath("SignedOut");
-  base::FilePath unconsented_path = GetProfilePath("Unconsented");
-
-  // Create profiles without gaia ids.
-  CreateProfilesAndSetAccountsInPrefs({{main_path(), {}},
-                                       {syncing_path, {}},
-                                       {unconsented_path, {}},
-                                       {signed_out_path, {}}});
-  // Set profiles in various signin states.
-  attributes_storage()
-      ->GetProfileAttributesWithPath(syncing_path)
-      ->SetAuthInfo(
-          /*gaia_id=*/"A", /*user_name=*/u"A",
-          /*is_consented_primary_account=*/true);
-  attributes_storage()
-      ->GetProfileAttributesWithPath(unconsented_path)
-      ->SetAuthInfo(
-          /*gaia_id=*/"B", /*user_name=*/u"B",
-          /*is_consented_primary_account=*/false);
-
-  auto mapper = std::make_unique<AccountProfileMapper>(
-      mock_facade(), attributes_storage(), local_state());
-
-  // TODO(https://crbug.com/1260291): Revisit this once non-syncing profiles are
-  // allowed.
-  // The main profile is not deleted, even though it does not have an account.
-  // The syncing profile was fixed, by adding the sync account in Gaia Ids.
-  // The other profiles (signed-out and non-syncing) were deleted.
-  VerifyAccountsInStorage({{main_path(), {}}, {syncing_path, {"A"}}});
-}
-
 TEST_F(AccountProfileMapperTest, FixProfilesAtStartupWithLocalProfiles) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
-
   base::FilePath syncing_path = GetProfilePath("Syncing");
   base::FilePath signed_out_path = GetProfilePath("SignedOut");
   base::FilePath unconsented_path = GetProfilePath("Unconsented");
diff --git a/chrome/browser/lacros/account_manager/signin_helper_lacros.cc b/chrome/browser/lacros/account_manager/signin_helper_lacros.cc
index fa2eebf..243f5dc 100644
--- a/chrome/browser/lacros/account_manager/signin_helper_lacros.cc
+++ b/chrome/browser/lacros/account_manager/signin_helper_lacros.cc
@@ -5,11 +5,9 @@
 #include "chrome/browser/lacros/account_manager/signin_helper_lacros.h"
 
 #include "base/callback.h"
-#include "base/feature_list.h"
 #include "base/ranges/algorithm.h"
 #include "chrome/browser/lacros/account_manager/account_manager_util.h"
 #include "chrome/browser/ui/profile_picker.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "google_apis/gaia/core_account_id.h"
 
@@ -25,12 +23,10 @@
       account_profile_mapper_(account_profile_mapper),
       source_(source),
       identity_manager_(identity_manager) {
-  if (base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-    DCHECK(consistency_cookie_manager);
-    scoped_account_update_ =
-        std::make_unique<signin::ConsistencyCookieManager::ScopedAccountUpdate>(
-            consistency_cookie_manager->CreateScopedAccountUpdate());
-  }
+  DCHECK(consistency_cookie_manager);
+  scoped_account_update_ =
+      std::make_unique<signin::ConsistencyCookieManager::ScopedAccountUpdate>(
+          consistency_cookie_manager->CreateScopedAccountUpdate());
 
   GetAllAvailableAccounts(
       account_profile_mapper, profile_path,
diff --git a/chrome/browser/lacros/account_manager/signin_helper_lacros_unittest.cc b/chrome/browser/lacros/account_manager/signin_helper_lacros_unittest.cc
index 4aa7aaae..b5cf0fd 100644
--- a/chrome/browser/lacros/account_manager/signin_helper_lacros_unittest.cc
+++ b/chrome/browser/lacros/account_manager/signin_helper_lacros_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "base/containers/flat_set.h"
 #include "base/test/mock_callback.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/lacros/account_manager/account_profile_mapper.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
@@ -25,7 +24,6 @@
 #include "components/signin/core/browser/account_reconcilor_delegate.h"
 #include "components/signin/core/browser/consistency_cookie_manager.h"
 #include "components/signin/core/browser/mirror_landing_account_reconcilor_delegate.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/base/test_signin_client.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "components/signin/public/identity_manager/identity_test_utils.h"
@@ -188,9 +186,6 @@
   }
 
  private:
-  base::test::ScopedFeatureList feature_list_{
-      switches::kLacrosNonSyncingProfiles};
-
   content::BrowserTaskEnvironment task_environment;
   account_manager::MockAccountManagerFacade mock_facade_;
   sync_preferences::TestingPrefServiceSyncable prefs_;
diff --git a/chrome/browser/lacros/browser_service_lacros_browsertest.cc b/chrome/browser/lacros/browser_service_lacros_browsertest.cc
index f6807ba..33465fcf 100644
--- a/chrome/browser/lacros/browser_service_lacros_browsertest.cc
+++ b/chrome/browser/lacros/browser_service_lacros_browsertest.cc
@@ -39,7 +39,6 @@
 #include "chromeos/startup/browser_init_params.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/window.h"
@@ -535,8 +534,7 @@
   EXPECT_FALSE(profile->IsOffTheRecord());
 }
 
-// Tests for lacros-chrome that require `LacrosNonSyncingProfiles` to be
-// enabled.
+// Tests for non-syncing profiles.
 class BrowserServiceLacrosNonSyncingProfilesBrowserTest
     : public BrowserServiceLacrosBrowserTest {
  public:
@@ -563,8 +561,6 @@
   // be triggered and completed before we enter the test body.
   base::HistogramTester histogram_tester_;
 
-  base::test::ScopedFeatureList feature_list_{
-      switches::kLacrosNonSyncingProfiles};
   profiles::testing::ScopedNonEnterpriseDomainSetterForTesting
       non_enterprise_domain_setter_;
 };
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/translate/FakeTranslateBridgeJni.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/translate/FakeTranslateBridgeJni.java
index e3e606a..d508e14 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/translate/FakeTranslateBridgeJni.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/translate/FakeTranslateBridgeJni.java
@@ -167,11 +167,6 @@
     }
 
     @Override
-    public String[] getModelLanguages() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public void moveAcceptLanguage(String language, int offset) {
         throw new UnsupportedOperationException();
     }
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
index 317fc49..9e2af3e 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
@@ -13,7 +13,6 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.LinkedHashSet;
 import java.util.List;
 
 /**
@@ -130,14 +129,6 @@
         TranslateBridgeJni.get().setDefaultTargetLanguage(targetLanguage);
     }
 
-    /**
-     * @return The ordered set of all languages that the user's knows, ordered by how well they know
-     *         them with the most familiar listed first.
-     */
-    public static LinkedHashSet<String> getModelLanguages() {
-        return new LinkedHashSet<>(Arrays.asList(TranslateBridgeJni.get().getModelLanguages()));
-    }
-
     @CalledByNative
     private static void addNewLanguageItemToList(List<LanguageItem> list, String code,
             String displayName, String nativeDisplayName, boolean supportTranslate) {
@@ -275,7 +266,6 @@
         String getCurrentLanguage(WebContents webContents);
         String getTargetLanguage();
         void setDefaultTargetLanguage(String targetLanguage);
-        String[] getModelLanguages();
         void resetAcceptLanguages(String defaultLocale);
         void getChromeAcceptLanguages(List<LanguageItem> list);
         String[] getUserAcceptLanguages();
diff --git a/chrome/browser/lifetime/application_lifetime_chromeos_browsertest.cc b/chrome/browser/lifetime/application_lifetime_chromeos_browsertest.cc
index bd9553c..389c23c 100644
--- a/chrome/browser/lifetime/application_lifetime_chromeos_browsertest.cc
+++ b/chrome/browser/lifetime/application_lifetime_chromeos_browsertest.cc
@@ -83,7 +83,7 @@
 
   // Session Manager is not going to stop session.
   EXPECT_FALSE(IsAttemptingShutdown());
-  auto* fake_session_manager_client = chromeos::FakeSessionManagerClient::Get();
+  auto* fake_session_manager_client = ash::FakeSessionManagerClient::Get();
   EXPECT_FALSE(fake_session_manager_client->session_stopped());
 
   // No reboot requested.
@@ -106,7 +106,7 @@
 
   // Session Manager is not going to stop session.
   EXPECT_FALSE(IsAttemptingShutdown());
-  auto* fake_session_manager_client = chromeos::FakeSessionManagerClient::Get();
+  auto* fake_session_manager_client = ash::FakeSessionManagerClient::Get();
   EXPECT_FALSE(fake_session_manager_client->session_stopped());
 
   // No reboot requested via power manager.
@@ -129,7 +129,7 @@
 
   // Session Manager is not going to stop session.
   EXPECT_FALSE(IsAttemptingShutdown());
-  auto* fake_session_manager_client = chromeos::FakeSessionManagerClient::Get();
+  auto* fake_session_manager_client = ash::FakeSessionManagerClient::Get();
   EXPECT_FALSE(fake_session_manager_client->session_stopped());
 
   // Reboot has been requested.
@@ -150,7 +150,7 @@
 
   // Session Manager has received stop session request.
   EXPECT_TRUE(IsAttemptingShutdown());
-  auto* fake_session_manager_client = chromeos::FakeSessionManagerClient::Get();
+  auto* fake_session_manager_client = ash::FakeSessionManagerClient::Get();
   EXPECT_TRUE(fake_session_manager_client->session_stopped());
 
   // No reboot requested.
diff --git a/chrome/browser/lifetime/browser_close_manager_browsertest.cc b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
index 3f931274..705dbbb 100644
--- a/chrome/browser/lifetime/browser_close_manager_browsertest.cc
+++ b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
@@ -223,20 +223,18 @@
     return true;
   }
 
-  static void SetDangerous(
-      content::DownloadTargetCallback callback,
-      const base::FilePath& target_path,
-      download::DownloadItem::TargetDisposition disp,
-      download::DownloadDangerType danger_type,
-      download::DownloadItem::MixedContentStatus mcs,
-      const base::FilePath& intermediate_path,
-      const base::FilePath& display_name,
-      const std::string& mime_type,
-      absl::optional<download::DownloadSchedule> download_schedule,
-      download::DownloadInterruptReason reason) {
-    std::move(callback).Run(
-        target_path, disp, download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, mcs,
-        intermediate_path, display_name, mime_type, download_schedule, reason);
+  static void SetDangerous(content::DownloadTargetCallback callback,
+                           const base::FilePath& target_path,
+                           download::DownloadItem::TargetDisposition disp,
+                           download::DownloadDangerType danger_type,
+                           download::DownloadItem::MixedContentStatus mcs,
+                           const base::FilePath& intermediate_path,
+                           const base::FilePath& display_name,
+                           const std::string& mime_type,
+                           download::DownloadInterruptReason reason) {
+    std::move(callback).Run(target_path, disp,
+                            download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, mcs,
+                            intermediate_path, display_name, mime_type, reason);
   }
 };
 
diff --git a/chrome/browser/mac/DEPS b/chrome/browser/mac/DEPS
new file mode 100644
index 0000000..a2e2fdd9
--- /dev/null
+++ b/chrome/browser/mac/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+chrome/updater",
+]
diff --git a/chrome/browser/mac/install_updater.mm b/chrome/browser/mac/install_updater.mm
index bc5ad16..744c8b8 100644
--- a/chrome/browser/mac/install_updater.mm
+++ b/chrome/browser/mac/install_updater.mm
@@ -21,6 +21,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/updater/browser_updater_client.h"
 #include "chrome/browser/updater/browser_updater_client_util.h"
+#include "chrome/updater/updater_scope.h"
 
 namespace {
 
@@ -76,5 +77,5 @@
 
             client->Register();
           },
-          BrowserUpdaterClient::Create()));
+          BrowserUpdaterClient::Create(updater::UpdaterScope::kUser)));
 }
diff --git a/chrome/browser/media/cast_mirroring_service_host_browsertest.cc b/chrome/browser/media/cast_mirroring_service_host_browsertest.cc
index 0ff7341..c12e83a 100644
--- a/chrome/browser/media/cast_mirroring_service_host_browsertest.cc
+++ b/chrome/browser/media/cast_mirroring_service_host_browsertest.cc
@@ -113,6 +113,8 @@
     OnBufferDestroyedCall(buffer_id);
   }
 
+  void OnNewCropVersion(uint32_t crop_version) override {}
+
   void OnStateChanged(media::mojom::VideoCaptureResultPtr result) override {
     if (result->which() == media::mojom::VideoCaptureResult::Tag::kState)
       OnStateChangedCall(result->get_state());
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
index 3c36463..8e334c34 100644
--- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
+++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -581,6 +581,8 @@
   picker_params.target_name = picker_params.app_name;
   picker_params.request_audio = pending_request.request.audio_type !=
                                 blink::mojom::MediaStreamType::NO_SERVICE;
+  picker_params.exclude_system_audio =
+      pending_request.request.exclude_system_audio;
   picker_params.restricted_by_policy =
       (capture_level != AllowedScreenCaptureLevel::kUnrestricted);
   pending_request.picker->Show(picker_params, std::move(source_lists),
diff --git a/chrome/browser/media/webrtc/desktop_media_picker.h b/chrome/browser/media/webrtc/desktop_media_picker.h
index f3d4d185..040ef8f 100644
--- a/chrome/browser/media/webrtc/desktop_media_picker.h
+++ b/chrome/browser/media/webrtc/desktop_media_picker.h
@@ -56,9 +56,14 @@
     std::u16string target_name;
     // Whether audio capture should be shown as an option in the picker.
     bool request_audio = false;
+    // If audio is requested, |exclude_system_audio| can indicate that
+    // system-audio should nevertheless not be offered to the user.
+    // Mutually exclusive with |force_audio_checkboxes_to_default_checked|.
+    bool exclude_system_audio = false;
     // Normally, the media-picker sets the default states for the audio
     // checkboxes. If |force_audio_checkboxes_to_default_checked| is |true|,
-    // it sets them all to |checked|.
+    // it sets them all to |checked|. This is used by Chromecasting.
+    // It is mutually exclusive with |exclude_system_audio|.
     bool force_audio_checkboxes_to_default_checked = false;
     // This flag controls the behvior in the case where the picker is invoked to
     // select a screen and there is only one screen available.  If true, the
diff --git a/chrome/browser/media/webrtc/display_media_access_handler.cc b/chrome/browser/media/webrtc/display_media_access_handler.cc
index 5119f34..ccebb72 100644
--- a/chrome/browser/media/webrtc/display_media_access_handler.cc
+++ b/chrome/browser/media/webrtc/display_media_access_handler.cc
@@ -332,6 +332,8 @@
   picker_params.request_audio =
       pending_request.request.audio_type ==
       blink::mojom::MediaStreamType::DISPLAY_AUDIO_CAPTURE;
+  picker_params.exclude_system_audio =
+      pending_request.request.exclude_system_audio;
   picker_params.restricted_by_policy =
       (capture_level != AllowedScreenCaptureLevel::kUnrestricted);
   pending_request.picker->Show(picker_params, std::move(source_lists),
diff --git a/chrome/browser/media/webrtc/region_capture_browsertest.cc b/chrome/browser/media/webrtc/region_capture_browsertest.cc
index 56cc406..b9471678 100644
--- a/chrome/browser/media/webrtc/region_capture_browsertest.cc
+++ b/chrome/browser/media/webrtc/region_capture_browsertest.cc
@@ -215,6 +215,17 @@
     return script_result == "deallocate-success";
   }
 
+  bool HideElement(const std::string& element_id) {
+    std::string script_result = "error-not-modified";
+    EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+        web_contents->GetPrimaryMainFrame(),
+        base::StringPrintf("hideElement('%s');", element_id.c_str()),
+        &script_result));
+    DCHECK(script_result == "hide-element-failure" ||
+           script_result == "hide-element-success");
+    return script_result == "hide-element-success";
+  }
+
   std::string CreateNewDivElement(Frame frame, const std::string& div_id) {
     DCHECK_NE(frame, Frame::kNone);
     std::string script_result = "error-not-modified";
@@ -431,6 +442,27 @@
             "top-level-crop-success");
 }
 
+// TODO(crbug.com/1336323): Re-enable.
+#if 0
+// The Promise resolves when it's guaranteed that no additional frames will
+// be issued with an earlier crop version. That an actual frame be issued
+// at all, let alone with the new crop version, is not actually required,
+// or else these promises could languish unfulfilled indefinitely.
+IN_PROC_BROWSER_TEST_F(RegionCaptureBrowserTest,
+                       CropToOfInvisibleElementResolvesInTimelyFashion) {
+  SetUpTest(Frame::kTopLevelDocument, /*self_capture=*/true);
+  TabInfo& tab = tabs_[kMainTab];
+
+  ASSERT_TRUE(tab.HideElement("div"));
+
+  const std::string crop_target =
+      tab.CropTargetFromElement(Frame::kTopLevelDocument, "div");
+  ASSERT_THAT(crop_target, IsExpectedCropTarget("0"));
+  EXPECT_EQ(tab.CropTo(crop_target, Frame::kTopLevelDocument),
+            "top-level-crop-success");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(RegionCaptureBrowserTest, MaxCropIdsInTopLevelDocument) {
   SetUpTest(Frame::kNone, /*self_capture=*/false);
   TabInfo& tab = tabs_[kMainTab];
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 4b6efee..c02ed8f 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -153,6 +153,7 @@
 #include "chrome/browser/ash/printing/printer_metrics_provider.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ash/settings/device_settings_service.h"
+#include "chrome/browser/ash/web_applications/personalization_app/keyboard_backlight_color_metrics_provider.h"
 #include "chrome/browser/metrics/ambient_mode_metrics_provider.h"
 #include "chrome/browser/metrics/assistant_service_metrics_provider.h"
 #include "chrome/browser/metrics/chromeos_family_link_user_metrics_provider.h"
@@ -840,6 +841,9 @@
     metrics_service_->RegisterMetricsProvider(
         std::make_unique<UserTypeByDeviceTypeMetricsProvider>());
   }
+
+  metrics_service_->RegisterMetricsProvider(
+      std::make_unique<KeyboardBacklightColorMetricsProvider>());
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
index fd55c37c..430bc576 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
@@ -190,10 +190,10 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // AmbientModeMetricsProvider, AssistantServiceMetricsProvider,
   // CrosHealthdMetricsProvider, ChromeOSMetricsProvider,
-  // PrinterMetricsProvider, HashedLoggingMetricsProvider,
-  // FamilyUserMetricsProvider, FamilyLinkUserMetricsProvider, and
-  // UserTypeByDeviceTypeMetricsProvider.
-  expected_providers += 9;
+  // KeyboardBacklightColorMetricsProvider, PrinterMetricsProvider,
+  // HashedLoggingMetricsProvider, FamilyUserMetricsProvider,
+  // FamilyLinkUserMetricsProvider, and UserTypeByDeviceTypeMetricsProvider.
+  expected_providers += 10;
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/metrics/cros_healthd_metrics_provider.cc b/chrome/browser/metrics/cros_healthd_metrics_provider.cc
index a38df17..f421ad0 100644
--- a/chrome/browser/metrics/cros_healthd_metrics_provider.cc
+++ b/chrome/browser/metrics/cros_healthd_metrics_provider.cc
@@ -13,9 +13,9 @@
 #include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "third_party/metrics_proto/system_profile.pb.h"
 
diff --git a/chrome/browser/metrics/cros_healthd_metrics_provider.h b/chrome/browser/metrics/cros_healthd_metrics_provider.h
index c3a409b4..19a3263a 100644
--- a/chrome/browser/metrics/cros_healthd_metrics_provider.h
+++ b/chrome/browser/metrics/cros_healthd_metrics_provider.h
@@ -9,7 +9,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "components/metrics/metrics_provider.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/metrics_proto/system_profile.pb.h"
diff --git a/chrome/browser/metrics/cros_healthd_metrics_provider_unittest.cc b/chrome/browser/metrics/cros_healthd_metrics_provider_unittest.cc
index bf209c8..d0a92c1b 100644
--- a/chrome/browser/metrics/cros_healthd_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/cros_healthd_metrics_provider_unittest.cc
@@ -12,9 +12,9 @@
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/metrics_proto/system_profile.pb.h"
 
diff --git a/chrome/browser/navigation_predictor/anchor_element_preloader.cc b/chrome/browser/navigation_predictor/anchor_element_preloader.cc
index 37c87627..87b38ee 100644
--- a/chrome/browser/navigation_predictor/anchor_element_preloader.cc
+++ b/chrome/browser/navigation_predictor/anchor_element_preloader.cc
@@ -5,10 +5,10 @@
 #include "chrome/browser/navigation_predictor/anchor_element_preloader.h"
 #include "base/callback.h"
 #include "base/metrics/histogram_functions.h"
-#include "chrome/browser/chrome_preloading.h"
 #include "chrome/browser/predictors/loading_predictor.h"
 #include "chrome/browser/predictors/loading_predictor_factory.h"
 #include "chrome/browser/prefetch/prefetch_prefs.h"
+#include "chrome/browser/preloading/chrome_preloading.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/preloading.h"
 #include "content/public/browser/preloading_data.h"
diff --git a/chrome/browser/navigation_predictor/anchor_element_preloader_browsertest.cc b/chrome/browser/navigation_predictor/anchor_element_preloader_browsertest.cc
index 35464f0..38be941 100644
--- a/chrome/browser/navigation_predictor/anchor_element_preloader_browsertest.cc
+++ b/chrome/browser/navigation_predictor/anchor_element_preloader_browsertest.cc
@@ -5,12 +5,12 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
-#include "chrome/browser/chrome_preloading.h"
 #include "chrome/browser/navigation_predictor/anchor_element_preloader.h"
 #include "chrome/browser/predictors/loading_predictor.h"
 #include "chrome/browser/predictors/loading_predictor_factory.h"
 #include "chrome/browser/predictors/preconnect_manager.h"
 #include "chrome/browser/prefetch/prefetch_prefs.h"
+#include "chrome/browser/preloading/chrome_preloading.h"
 #include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
diff --git a/chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler_unittest.cc b/chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler_unittest.cc
index 628aa11..7bcea560 100644
--- a/chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler_unittest.cc
+++ b/chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "chrome/browser/nearby_sharing/wifi_credentials_attachment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/services/network_config/cros_network_config.h"
 #include "chromeos/services/network_config/in_process_instance.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/net/nss_service_chromeos.cc b/chrome/browser/net/nss_service_chromeos.cc
index 9f307c6..ccb8eb89 100644
--- a/chrome/browser/net/nss_service_chromeos.cc
+++ b/chrome/browser/net/nss_service_chromeos.cc
@@ -25,8 +25,8 @@
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/notifications/notification_platform_bridge_lacros.cc b/chrome/browser/notifications/notification_platform_bridge_lacros.cc
index 9e9500f..36c9039 100644
--- a/chrome/browser/notifications/notification_platform_bridge_lacros.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_lacros.cc
@@ -184,10 +184,13 @@
   auto pending_notification = std::make_unique<RemoteNotificationDelegate>(
       notification.id(), bridge_delegate_, weak_factory_.GetWeakPtr());
   // Display the notification, or update an existing one with the same ID.
-  // `profile` may be null in tests.
+  // `profile` may be null for e.g. system notifications.
   const auto* const color_provider =
-      profile ? ThemeServiceFactory::GetForProfile(profile)->GetColorProvider()
-              : nullptr;
+      profile
+          ? ThemeServiceFactory::GetForProfile(profile)->GetColorProvider()
+          : ui::ColorProviderManager::Get().GetColorProviderFor(
+                ui::NativeTheme::GetInstanceForNativeUi()->GetColorProviderKey(
+                    nullptr));
   (*message_center_remote_)
       ->DisplayNotification(ToMojo(notification, color_provider),
                             pending_notification->BindNotificationDelegate());
diff --git a/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc b/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc
index 6bf0cbd..ab4afbf 100644
--- a/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc
+++ b/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc
@@ -456,8 +456,9 @@
   bool load_model_on_startup_ = true;
 };
 
+// Disabled. https://crbug.com/1338408
 IN_PROC_BROWSER_TEST_F(PageContentAnnotationsServiceBrowserTest,
-                       ModelExecutes) {
+                       DISABLED_ModelExecutes) {
   base::HistogramTester histogram_tester;
   ukm::TestAutoSetUkmRecorder ukm_recorder;
 
diff --git a/chrome/browser/os_crypt/DEPS b/chrome/browser/os_crypt/DEPS
new file mode 100644
index 0000000..1a0e207
--- /dev/null
+++ b/chrome/browser/os_crypt/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  '+chrome/elevation_service/elevation_service_idl.h',
+  '+chrome/elevation_service/elevator.h',
+]
diff --git a/chrome/browser/os_crypt/OWNERS b/chrome/browser/os_crypt/OWNERS
new file mode 100644
index 0000000..971354f1
--- /dev/null
+++ b/chrome/browser/os_crypt/OWNERS
@@ -0,0 +1,5 @@
+# Default sending any reviews to these owners:
+wfh@chromium.org
+
+# As a backup, a review can also be obtained from a reviewer in this file.
+file://chrome/elevation_service/OWNERS
diff --git a/chrome/browser/os_crypt/README.md b/chrome/browser/os_crypt/README.md
new file mode 100644
index 0000000..803cb68b4
--- /dev/null
+++ b/chrome/browser/os_crypt/README.md
@@ -0,0 +1,27 @@
+This directory contains the interface to the application-bound encryption
+primitives that are implemented by the elevation service in
+[src/chrome/elevation_service].
+
+`EncryptAppBoundString` and `DecryptAppBoundString` act like
+`OSCrypt::EncryptString` and `OSCrypt::DecryptString` implemented by
+[src/components/os_crypt] except that, unlike `OSCrypt`, which binds encrypted
+data to the current user using DPAPI, this API will bind the encrypted data
+with a `ProtectionLevel` specified by the caller.
+
+`ProtectionLevels` are defined by chrome/elevation_service and are currently:
+
+ - `ProtectionLevel::NONE`
+
+   This acts identically to DPAPI in that the protection level is user-bound.
+   Only a `DecryptAppBoundString` call that comes from the same user principle
+   as the original `EncryptAppBoundString` call with succeed.
+
+ - `ProtectionLevel::PATH_VALIDATION`
+
+   This adds an additional protection that the path of the calling application
+   will be validated. Only a `DecryptAppBoundString` call that comes from the
+   same user principle, calling from the same Application (with the same file
+   path) as the original `EncryptAppBoundString` call with succeed. It is only
+   safe to call this from an application that is installed into a 'Trusted
+   Path' such as `C:\Program Files`, otherwise protection can be trivially
+   bypassed by renaming/placing a file into the required location.
diff --git a/chrome/browser/os_crypt/app_bound_encryption_metrics_win.cc b/chrome/browser/os_crypt/app_bound_encryption_metrics_win.cc
new file mode 100644
index 0000000..b5d29b5
--- /dev/null
+++ b/chrome/browser/os_crypt/app_bound_encryption_metrics_win.cc
@@ -0,0 +1,134 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/os_crypt/app_bound_encryption_metrics_win.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_util.h"
+#include "base/task/single_thread_task_runner.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/win/com_init_util.h"
+#include "base/win/windows_types.h"
+#include "chrome/browser/os_crypt/app_bound_encryption_win.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace os_crypt {
+
+namespace prefs {
+
+const char kOsCryptAppBoundFixedDataPrefName[] =
+    "os_crypt.app_bound_fixed_data";
+
+}  // namespace prefs
+
+namespace {
+
+// Rather than generate a random key here, use fixed data here for the purposes
+// of measuring the performance, as the content itself does not matter.
+const char kFixedData[] = "Fixed data used for metrics";
+
+void DecryptAndRecordMetricsOnCOMThread(const std::string& encrypted_data) {
+  base::win::AssertComInitialized();
+
+  std::string decrypted_data;
+  DWORD last_error;
+  HRESULT hr;
+  {
+    SCOPED_UMA_HISTOGRAM_TIMER("OSCrypt.AppBoundEncryption.Decrypt.Time");
+    hr = DecryptAppBoundString(encrypted_data, decrypted_data, last_error);
+  }
+
+  if (FAILED(hr)) {
+    base::UmaHistogramSparse(
+        "OSCrypt.AppBoundEncryption.Decrypt.ResultLastError", last_error);
+  } else {
+    // Check if it returned success but the data was invalid. This should never
+    // happen. If it does, log a unique HRESULT to track it.
+    if (decrypted_data != kFixedData) {
+      const HRESULT kErrorWrongData =
+          MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA101);
+      hr = kErrorWrongData;
+    }
+  }
+
+  base::UmaHistogramSparse("OSCrypt.AppBoundEncryption.Decrypt.ResultCode", hr);
+}
+
+std::string EncryptAndRecordMetricsOnCOMThread() {
+  base::win::AssertComInitialized();
+
+  std::string encrypted_data;
+  DWORD last_error;
+  HRESULT hr;
+  {
+    SCOPED_UMA_HISTOGRAM_TIMER("OSCrypt.AppBoundEncryption.Encrypt.Time");
+    hr = EncryptAppBoundString(ProtectionLevel::PATH_VALIDATION, kFixedData,
+                               encrypted_data, last_error);
+  }
+
+  base::UmaHistogramSparse("OSCrypt.AppBoundEncryption.Encrypt.ResultCode", hr);
+
+  if (FAILED(hr)) {
+    base::UmaHistogramSparse(
+        "OSCrypt.AppBoundEncryption.Encrypt.ResultLastError", last_error);
+  }
+
+  return encrypted_data;
+}
+
+void StorePrefOnUiThread(PrefService* local_state,
+                         const std::string& encrypted_data) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (encrypted_data.empty())
+    return;
+  std::string base64_data;
+  base::Base64Encode(encrypted_data, &base64_data);
+
+  local_state->SetString(prefs::kOsCryptAppBoundFixedDataPrefName, base64_data);
+}
+
+}  // namespace
+
+void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterStringPref(prefs::kOsCryptAppBoundFixedDataPrefName, {});
+}
+
+bool MeasureAppBoundEncryptionStatus(PrefService* local_state) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  auto com_runner = base::ThreadPool::CreateCOMSTATaskRunner(
+      {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+      base::SingleThreadTaskRunnerThreadMode::SHARED);
+
+  if (local_state->HasPrefPath(prefs::kOsCryptAppBoundFixedDataPrefName)) {
+    const std::string base64_encrypted_data =
+        local_state->GetString(prefs::kOsCryptAppBoundFixedDataPrefName);
+
+    std::string encrypted_data;
+    // If this fails it will be caught later when trying to decrypt and logged
+    // above..
+    std::ignore = base::Base64Decode(base64_encrypted_data, &encrypted_data);
+
+    // Gather metrics for decrypt.
+    return com_runner->PostTask(
+        FROM_HERE,
+        base::BindOnce(&DecryptAndRecordMetricsOnCOMThread, encrypted_data));
+  }
+
+  return com_runner->PostTaskAndReplyWithResult(
+      FROM_HERE, base::BindOnce(&EncryptAndRecordMetricsOnCOMThread),
+      base::BindOnce(StorePrefOnUiThread, local_state));
+}
+
+}  // namespace os_crypt
diff --git a/chrome/browser/os_crypt/app_bound_encryption_metrics_win.h b/chrome/browser/os_crypt/app_bound_encryption_metrics_win.h
new file mode 100644
index 0000000..66c6507
--- /dev/null
+++ b/chrome/browser/os_crypt/app_bound_encryption_metrics_win.h
@@ -0,0 +1,22 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_OS_CRYPT_APP_BOUND_ENCRYPTION_METRICS_WIN_H_
+#define CHROME_BROWSER_OS_CRYPT_APP_BOUND_ENCRYPTION_METRICS_WIN_H_
+
+class PrefRegistrySimple;
+class PrefService;
+
+namespace os_crypt {
+
+// Register local state prefs required by the app bound encryption metrics.
+void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+
+// Posts background tasks to measure the app bound encryption metrics. This
+// should be called on the UI thread.
+bool MeasureAppBoundEncryptionStatus(PrefService* local_state);
+
+}  // namespace os_crypt
+
+#endif  // CHROME_BROWSER_OS_CRYPT_APP_BOUND_ENCRYPTION_METRICS_WIN_H_
diff --git a/chrome/browser/os_crypt/app_bound_encryption_win.cc b/chrome/browser/os_crypt/app_bound_encryption_win.cc
new file mode 100644
index 0000000..79a680af
--- /dev/null
+++ b/chrome/browser/os_crypt/app_bound_encryption_win.cc
@@ -0,0 +1,98 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/os_crypt/app_bound_encryption_win.h"
+
+#include <objbase.h>
+#include <string.h>
+#include <windows.h>
+#include <wrl/client.h>
+
+#include "base/logging.h"
+#include "base/win/com_init_util.h"
+#include "base/win/scoped_bstr.h"
+#include "chrome/elevation_service/elevation_service_idl.h"
+#include "chrome/install_static/install_util.h"
+
+namespace os_crypt {
+
+HRESULT EncryptAppBoundString(ProtectionLevel protection_level,
+                              const std::string& plaintext,
+                              std::string& ciphertext,
+                              DWORD& last_error) {
+  base::win::AssertComInitialized();
+  Microsoft::WRL::ComPtr<IElevator> elevator;
+  last_error = ERROR_GEN_FAILURE;
+  HRESULT hr = ::CoCreateInstance(
+      install_static::GetElevatorClsid(), nullptr, CLSCTX_LOCAL_SERVER,
+      install_static::GetElevatorIid(), IID_PPV_ARGS_Helper(&elevator));
+
+  if (FAILED(hr))
+    return hr;
+
+  hr = ::CoSetProxyBlanket(
+      elevator.Get(), RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT,
+      COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
+      RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DYNAMIC_CLOAKING);
+  if (FAILED(hr))
+    return hr;
+
+  base::win::ScopedBstr plaintext_data;
+  ::memcpy(plaintext_data.AllocateBytes(plaintext.length()), plaintext.data(),
+           plaintext.length());
+
+  base::win::ScopedBstr encrypted_data;
+  hr = elevator->EncryptData(protection_level, plaintext_data.Get(),
+                             encrypted_data.Receive(), &last_error);
+  if (FAILED(hr))
+    return hr;
+
+  ciphertext.assign(
+      reinterpret_cast<std::string::value_type*>(encrypted_data.Get()),
+      encrypted_data.ByteLength());
+
+  last_error = ERROR_SUCCESS;
+  return S_OK;
+}
+
+HRESULT DecryptAppBoundString(const std::string& ciphertext,
+                              std::string& plaintext,
+                              DWORD& last_error) {
+  DCHECK(!ciphertext.empty());
+  base::win::AssertComInitialized();
+  Microsoft::WRL::ComPtr<IElevator> elevator;
+  last_error = ERROR_GEN_FAILURE;
+  HRESULT hr = ::CoCreateInstance(
+      install_static::GetElevatorClsid(), nullptr, CLSCTX_LOCAL_SERVER,
+      install_static::GetElevatorIid(), IID_PPV_ARGS_Helper(&elevator));
+
+  if (FAILED(hr))
+    return hr;
+
+  hr = ::CoSetProxyBlanket(
+      elevator.Get(), RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT,
+      COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
+      RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DYNAMIC_CLOAKING);
+  if (FAILED(hr))
+    return hr;
+
+  base::win::ScopedBstr ciphertext_data;
+  ::memcpy(ciphertext_data.AllocateBytes(ciphertext.length()),
+           ciphertext.data(), ciphertext.length());
+
+  base::win::ScopedBstr plaintext_data;
+  hr = elevator->DecryptData(ciphertext_data.Get(), plaintext_data.Receive(),
+                             &last_error);
+  if (FAILED(hr))
+    return hr;
+
+  plaintext.assign(
+      reinterpret_cast<std::string::value_type*>(plaintext_data.Get()),
+      plaintext_data.ByteLength());
+
+  last_error = ERROR_SUCCESS;
+  return S_OK;
+}
+
+}  // namespace os_crypt
diff --git a/chrome/browser/os_crypt/app_bound_encryption_win.h b/chrome/browser/os_crypt/app_bound_encryption_win.h
new file mode 100644
index 0000000..e8f1372
--- /dev/null
+++ b/chrome/browser/os_crypt/app_bound_encryption_win.h
@@ -0,0 +1,44 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_OS_CRYPT_APP_BOUND_ENCRYPTION_WIN_H_
+#define CHROME_BROWSER_OS_CRYPT_APP_BOUND_ENCRYPTION_WIN_H_
+
+#include <string>
+
+#include "base/win/windows_types.h"
+#include "chrome/elevation_service/elevation_service_idl.h"
+
+namespace os_crypt {
+
+// Encrypts a string with a Protection level of `level`. See
+// `src/chrome/elevation_service/elevation-service_idl.idl` for the definition
+// of available protection levels.
+//
+// This returns an HRESULT as defined by src/chrome/elevation_service/elevator.h
+// or S_OK for success. If the call fails then `last_error` will be set to the
+// value returned from the most recent failing Windows API call or
+// ERROR_GEN_FAILURE.
+//
+// This should be called on a COM-enabled thread.
+HRESULT EncryptAppBoundString(ProtectionLevel level,
+                              const std::string& plaintext,
+                              std::string& ciphertext,
+                              DWORD& last_error);
+
+// Decrypts a string previously encrypted by a call to EncryptAppBoundString.
+//
+// This returns an HRESULT as defined by src/chrome/elevation_service/elevator.h
+// or S_OK for success. If the call fails then `last_error` will be set to the
+// value returned from the most recent failing Windows API call or
+// ERROR_GEN_FAILURE.
+//
+// This should be called on a COM-enabled thread.
+HRESULT DecryptAppBoundString(const std::string& ciphertext,
+                              std::string& plaintext,
+                              DWORD& last_error);
+
+}  // namespace os_crypt
+
+#endif  // CHROME_BROWSER_OS_CRYPT_APP_BOUND_ENCRYPTION_WIN_H_
diff --git a/chrome/browser/os_crypt/app_bound_encryption_win_browsertest.cc b/chrome/browser/os_crypt/app_bound_encryption_win_browsertest.cc
new file mode 100644
index 0000000..c21144c
--- /dev/null
+++ b/chrome/browser/os_crypt/app_bound_encryption_win_browsertest.cc
@@ -0,0 +1,221 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/os_crypt/app_bound_encryption_win.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/metrics/histogram_base.h"
+#include "base/metrics/histogram_samples.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/path_service.h"
+#include "base/process/process_info.h"
+#include "base/test/bind.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/browser_features.h"
+#include "chrome/elevation_service/elevator.h"
+#include "chrome/install_static/buildflags.h"
+#include "chrome/install_static/install_constants.h"
+#include "chrome/install_static/install_details.h"
+#include "chrome/install_static/install_util.h"
+#include "chrome/install_static/test/scoped_install_details.h"
+#include "chrome/installer/util/install_service_work_item.h"
+#include "chrome/installer/util/util_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "components/version_info/version_info_values.h"
+#include "content/public/test/browser_test.h"
+
+namespace {
+
+void WaitForHistogram(const std::string& histogram_name) {
+  // Continue if histogram was already recorded.
+  if (base::StatisticsRecorder::FindHistogram(histogram_name))
+    return;
+
+  // Else, wait until the histogram is recorded.
+  base::RunLoop run_loop;
+  auto histogram_observer =
+      std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
+          histogram_name,
+          base::BindLambdaForTesting(
+              [&](const char* histogram_name, uint64_t name_hash,
+                  base::HistogramBase::Sample sample) { run_loop.Quit(); }));
+  run_loop.Run();
+}
+
+}  // namespace
+
+// This class allows system-level tests to be carried out that do not interfere
+// with an existing system-level install.
+class FakeInstallDetails : public install_static::PrimaryInstallDetails {
+ public:
+  // Copy template from first mode from install modes. Some of the values will
+  // then be overridden.
+  FakeInstallDetails() : constants_(install_static::kInstallModes[0]) {
+    // AppGuid determines registry locations, so use a test one.
+#if BUILDFLAG(USE_GOOGLE_UPDATE_INTEGRATION)
+    constants_.app_guid = L"testguid";
+#endif
+
+    // This is the CLSID of the test interface, used if
+    // kElevatorClsIdForTestingSwitch is supplied on the command line of the
+    // elevation service.
+    constants_.elevator_clsid = {elevation_service::kTestElevatorClsid};
+
+    // This is the IID of the non-channel specific IElevator Interface. See
+    // chrome/elevation_service/elevation_service_idl.idl.
+    constants_.elevator_iid = {
+        0xA949CB4E,
+        0xC4F9,
+        0x44C4,
+        {0xB2, 0x13, 0x6B, 0xF8, 0xAA, 0x9A, 0xC6,
+         0x9C}};  // IElevator IID and TypeLib
+                  // {A949CB4E-C4F9-44C4-B213-6BF8AA9AC69C}
+
+    // These are used to generate the name of the service, so keep them
+    // different from any real installs.
+    constants_.base_app_name = L"testapp";
+    constants_.base_app_id = L"testapp";
+
+    // This is needed for shell_integration::GetDefaultBrowser which runs on
+    // startup.
+    constants_.prog_id_prefix = L"TestHTM";
+
+    set_mode(&constants_);
+    set_system_level(true);
+  }
+
+  FakeInstallDetails(const FakeInstallDetails&) = delete;
+  FakeInstallDetails& operator=(const FakeInstallDetails&) = delete;
+
+ private:
+  install_static::InstallConstants constants_;
+};
+
+class AppBoundEncryptionWinTest : public InProcessBrowserTest {
+ public:
+  AppBoundEncryptionWinTest()
+      : scoped_install_details_(std::make_unique<FakeInstallDetails>()) {}
+
+ protected:
+  void SetUp() override {
+    if (base::GetCurrentProcessIntegrityLevel() != base::HIGH_INTEGRITY)
+      GTEST_SKIP() << "Elevation is required for this test.";
+    enable_metrics_feature_.InitAndEnableFeature(
+        features::kAppBoundEncryptionMetrics);
+    InstallService();
+    InProcessBrowserTest::SetUp();
+  }
+
+  void TearDown() override {
+    if (base::GetCurrentProcessIntegrityLevel() != base::HIGH_INTEGRITY)
+      return;
+    InProcessBrowserTest::TearDown();
+    UnInstallService();
+  }
+
+  base::HistogramTester histogram_tester_;
+  base::test::ScopedFeatureList enable_metrics_feature_;
+
+ private:
+  static bool InstallService() {
+    base::FilePath exe_dir;
+    base::PathService::Get(base::DIR_EXE, &exe_dir);
+    base::CommandLine service_cmd(
+        exe_dir.Append(installer::kElevationServiceExe));
+    service_cmd.AppendSwitch(
+        elevation_service::switches::kElevatorClsIdForTestingSwitch);
+    installer::InstallServiceWorkItem install_service_work_item(
+        install_static::GetElevationServiceName(),
+        install_static::GetElevationServiceDisplayName(), SERVICE_DEMAND_START,
+        service_cmd, base::CommandLine(base::CommandLine::NO_PROGRAM),
+        install_static::GetClientStateKeyPath(),
+        {install_static::GetElevatorClsid()},
+        {install_static::GetElevatorIid()});
+    install_service_work_item.set_best_effort(true);
+    install_service_work_item.set_rollback_enabled(false);
+    return install_service_work_item.Do();
+  }
+
+  static bool UnInstallService() {
+    return installer::InstallServiceWorkItem::DeleteService(
+        install_static::GetElevationServiceName(),
+        install_static::GetClientStateKeyPath(),
+        {install_static::GetElevatorClsid()},
+        {install_static::GetElevatorIid()});
+  }
+
+  install_static::ScopedInstallDetails scoped_install_details_;
+};
+
+// Test the basic interface to Encrypt and Decrypt data.
+IN_PROC_BROWSER_TEST_F(AppBoundEncryptionWinTest, EncryptDecrypt) {
+  ASSERT_TRUE(install_static::IsSystemInstall());
+  const std::string plaintext("plaintext");
+  std::string ciphertext;
+  DWORD last_error;
+
+  HRESULT hr = os_crypt::EncryptAppBoundString(
+      ProtectionLevel::PATH_VALIDATION, plaintext, ciphertext, last_error);
+
+  ASSERT_HRESULT_SUCCEEDED(hr);
+
+  std::string returned_plaintext;
+  hr = os_crypt::DecryptAppBoundString(ciphertext, returned_plaintext,
+                                       last_error);
+
+  ASSERT_HRESULT_SUCCEEDED(hr);
+  EXPECT_EQ(plaintext, returned_plaintext);
+}
+
+// These tests verify that the metrics are recorded correctly. The first load of
+// browser in the PRE_ test stores the "Test Key" with app-bound encryption and
+// the second stage of the test verifies it can be retrieved successfully.
+IN_PROC_BROWSER_TEST_F(AppBoundEncryptionWinTest, PRE_MetricsTest) {
+  ASSERT_TRUE(install_static::IsSystemInstall());
+  // These histograms are recorded on a background worker thread, so the test
+  // needs to wait until this task completes and the histograms are recorded.
+  WaitForHistogram("OSCrypt.AppBoundEncryption.Encrypt.ResultCode");
+  histogram_tester_.ExpectBucketCount(
+      "OSCrypt.AppBoundEncryption.Encrypt.ResultCode", S_OK, 1);
+
+  WaitForHistogram("OSCrypt.AppBoundEncryption.Encrypt.Time");
+}
+
+IN_PROC_BROWSER_TEST_F(AppBoundEncryptionWinTest, MetricsTest) {
+  ASSERT_TRUE(install_static::IsSystemInstall());
+  // These histograms are recorded on a background worker thread, so the test
+  // needs to wait until this task completes and the histograms are recorded.
+  WaitForHistogram("OSCrypt.AppBoundEncryption.Decrypt.ResultCode");
+  histogram_tester_.ExpectBucketCount(
+      "OSCrypt.AppBoundEncryption.Decrypt.ResultCode", S_OK, 1);
+
+  WaitForHistogram("OSCrypt.AppBoundEncryption.Decrypt.Time");
+}
+
+// Run this test manually to force uninstall the service.
+IN_PROC_BROWSER_TEST_F(AppBoundEncryptionWinTest, MANUAL_Uninstall) {}
+
+class AppBoundEncryptionWinTestNoService : public InProcessBrowserTest {
+ public:
+  AppBoundEncryptionWinTestNoService()
+      : scoped_install_details_(std::make_unique<FakeInstallDetails>()) {}
+
+ private:
+  install_static::ScopedInstallDetails scoped_install_details_;
+};
+
+IN_PROC_BROWSER_TEST_F(AppBoundEncryptionWinTestNoService, NoService) {
+  const std::string plaintext("plaintext");
+  std::string ciphertext;
+  DWORD last_error;
+
+  HRESULT hr = os_crypt::EncryptAppBoundString(
+      ProtectionLevel::PATH_VALIDATION, plaintext, ciphertext, last_error);
+
+  EXPECT_EQ(REGDB_E_CLASSNOTREG, hr);
+  EXPECT_EQ(DWORD{ERROR_GEN_FAILURE}, last_error);
+}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index 53ad1f9c..309fab0b 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -2719,7 +2719,8 @@
 }
 
 // TODO(crbug.com/1242284): Flaky on Linux.
-#if BUILDFLAG(IS_LINUX)
+// TODO(crbug.com/1338490): Flaky on lacros.
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #define MAYBE_RestoreForeignSession DISABLED_RestoreForeignSession
 #else
 #define MAYBE_RestoreForeignSession RestoreForeignSession
diff --git a/chrome/browser/password_check/android/password_check_manager.cc b/chrome/browser/password_check/android/password_check_manager.cc
index 6ddaa9c6..e7784661 100644
--- a/chrome/browser/password_check/android/password_check_manager.cc
+++ b/chrome/browser/password_check/android/password_check_manager.cc
@@ -170,10 +170,11 @@
   bool is_using_account_store = form.IsUsingAccountStore();
 
   credential_edit_bridge_ = CredentialEditBridge::MaybeCreate(
-      std::move(form), CredentialEditBridge::IsInsecureCredential(true),
+      password_manager::CredentialUIEntry(form),
+      CredentialEditBridge::IsInsecureCredential(true),
       GetUsernamesForRealm(saved_passwords_presenter_.GetSavedCredentials(),
                            credential.signon_realm, is_using_account_store),
-      &saved_passwords_presenter_, nullptr,
+      &saved_passwords_presenter_,
       base::BindOnce(&PasswordCheckManager::OnEditUIDismissed,
                      base::Unretained(this)),
       context, settings_launcher);
diff --git a/chrome/browser/password_entry_edit/android/credential_edit_bridge.cc b/chrome/browser/password_entry_edit/android/credential_edit_bridge.cc
index 4dae119b..5dcd588 100644
--- a/chrome/browser/password_entry_edit/android/credential_edit_bridge.cc
+++ b/chrome/browser/password_entry_edit/android/credential_edit_bridge.cc
@@ -22,11 +22,10 @@
 #include "ui/base/l10n/l10n_util.h"
 
 std::unique_ptr<CredentialEditBridge> CredentialEditBridge::MaybeCreate(
-    const password_manager::PasswordForm credential,
+    const password_manager::CredentialUIEntry credential,
     IsInsecureCredential is_insecure_credential,
     std::vector<std::u16string> existing_usernames,
     password_manager::SavedPasswordsPresenter* saved_passwords_presenter,
-    PasswordManagerPresenter* password_manager_presenter,
     base::OnceClosure dismissal_callback,
     const base::android::JavaRef<jobject>& context,
     const base::android::JavaRef<jobject>& settings_launcher) {
@@ -39,16 +38,15 @@
   return base::WrapUnique(new CredentialEditBridge(
       std::move(credential), is_insecure_credential,
       std::move(existing_usernames), saved_passwords_presenter,
-      password_manager_presenter, std::move(dismissal_callback), context,
-      settings_launcher, std::move(java_bridge)));
+      std::move(dismissal_callback), context, settings_launcher,
+      std::move(java_bridge)));
 }
 
 CredentialEditBridge::CredentialEditBridge(
-    const password_manager::PasswordForm credential,
+    const password_manager::CredentialUIEntry credential,
     IsInsecureCredential is_insecure_credential,
     std::vector<std::u16string> existing_usernames,
     password_manager::SavedPasswordsPresenter* saved_passwords_presenter,
-    PasswordManagerPresenter* password_manager_presenter,
     base::OnceClosure dismissal_callback,
     const base::android::JavaRef<jobject>& context,
     const base::android::JavaRef<jobject>& settings_launcher,
@@ -57,7 +55,6 @@
       is_insecure_credential_(is_insecure_credential),
       existing_usernames_(std::move(existing_usernames)),
       saved_passwords_presenter_(saved_passwords_presenter),
-      password_manager_presenter_(password_manager_presenter),
       dismissal_callback_(std::move(dismissal_callback)),
       java_bridge_(java_bridge) {
   Java_CredentialEditBridge_initAndLaunchUi(
@@ -75,8 +72,8 @@
   Java_CredentialEditBridge_setCredential(
       env, java_bridge_,
       base::android::ConvertUTF16ToJavaString(env, GetDisplayURLOrAppName()),
-      base::android::ConvertUTF16ToJavaString(env, credential_.username_value),
-      base::android::ConvertUTF16ToJavaString(env, credential_.password_value),
+      base::android::ConvertUTF16ToJavaString(env, credential_.username),
+      base::android::ConvertUTF16ToJavaString(env, credential_.password),
       base::android::ConvertUTF16ToJavaString(env,
                                               GetDisplayFederationOrigin()),
       is_insecure_credential_.value());
@@ -92,23 +89,14 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jstring>& username,
     const base::android::JavaParamRef<jstring>& password) {
-  saved_passwords_presenter_->EditSavedPasswords(
-      credential_, base::android::ConvertJavaStringToUTF16(username),
-      base::android::ConvertJavaStringToUTF16(password));
+  password_manager::CredentialUIEntry to_edit = credential_;
+  to_edit.username = base::android::ConvertJavaStringToUTF16(username);
+  to_edit.password = base::android::ConvertJavaStringToUTF16(password);
+  saved_passwords_presenter_->EditSavedCredentials(to_edit);
 }
 
 void CredentialEditBridge::DeleteCredential(JNIEnv* env) {
-  if (credential_.blocked_by_user) {
-    std::vector<std::string> sort_keys = {
-        password_manager::CreateSortKey(credential_)};
-    password_manager_presenter_->RemovePasswordExceptions(sort_keys);
-  } else if (!credential_.federation_origin.opaque()) {
-    std::vector<std::string> sort_keys = {
-        password_manager::CreateSortKey(credential_)};
-    password_manager_presenter_->RemoveSavedPasswords(sort_keys);
-  } else {
-    saved_passwords_presenter_->RemovePassword(credential_);
-  }
+  saved_passwords_presenter_->RemoveCredential(credential_);
   std::move(dismissal_callback_).Run();
 }
 
@@ -142,7 +130,7 @@
 }
 
 std::u16string CredentialEditBridge::GetDisplayFederationOrigin() {
-  return credential_.IsFederatedCredential()
+  return !credential_.federation_origin.opaque()
              ? url_formatter::FormatUrl(
                    credential_.federation_origin.GetURL(),
                    url_formatter::kFormatUrlOmitDefaults |
diff --git a/chrome/browser/password_entry_edit/android/credential_edit_bridge.h b/chrome/browser/password_entry_edit/android/credential_edit_bridge.h
index 1cf4a32..e9658de5 100644
--- a/chrome/browser/password_entry_edit/android/credential_edit_bridge.h
+++ b/chrome/browser/password_entry_edit/android/credential_edit_bridge.h
@@ -11,7 +11,7 @@
 #include "base/callback_forward.h"
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/ui/passwords/settings/password_manager_presenter.h"
-#include "components/password_manager/core/browser/password_form.h"
+#include "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #include "components/password_manager/core/browser/ui/insecure_credentials_manager.h"
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 
@@ -25,11 +25,10 @@
   // null, since that means the edit UI is already open and it should not be
   // shared.
   static std::unique_ptr<CredentialEditBridge> MaybeCreate(
-      const password_manager::PasswordForm credential,
+      const password_manager::CredentialUIEntry credential,
       IsInsecureCredential is_insecure_credential,
       std::vector<std::u16string> existing_usernames,
       password_manager::SavedPasswordsPresenter* saved_passwords_presenter,
-      PasswordManagerPresenter* password_manager_presenter,
       base::OnceClosure dismissal_callback,
       const base::android::JavaRef<jobject>& context,
       const base::android::JavaRef<jobject>& settings_launcher);
@@ -57,11 +56,10 @@
 
  private:
   CredentialEditBridge(
-      const password_manager::PasswordForm credential,
+      const password_manager::CredentialUIEntry credential,
       IsInsecureCredential is_insecure_credential,
       std::vector<std::u16string> existing_usernames,
       password_manager::SavedPasswordsPresenter* saved_passwords_presenter,
-      PasswordManagerPresenter* password_manager_presenter,
       base::OnceClosure dismissal_callback,
       const base::android::JavaRef<jobject>& context,
       const base::android::JavaRef<jobject>& settings_launcher,
@@ -77,7 +75,7 @@
   std::u16string GetDisplayFederationOrigin();
 
   // The credential to be edited.
-  const password_manager::PasswordForm credential_;
+  const password_manager::CredentialUIEntry credential_;
 
   // Whether the credential being edited is an insecure credential. Used to
   // customize the deletion confirmation dialog string.
@@ -91,12 +89,6 @@
   raw_ptr<password_manager::SavedPasswordsPresenter>
       saved_passwords_presenter_ = nullptr;
 
-  // The backend to ask for blocked and federated credentials removal.
-  // Should be owned by the the owner of the bridge.
-  // TODO(crbug.com/1188678): Replace this once `SavedPasswordsPresnter`
-  // supports blocked and federated credentials.
-  raw_ptr<PasswordManagerPresenter> password_manager_presenter_ = nullptr;
-
   // Callback invoked when the UI is being dismissed from the Java side.
   base::OnceClosure dismissal_callback_;
 
diff --git a/chrome/browser/password_manager/android/password_ui_view_android.cc b/chrome/browser/password_manager/android/password_ui_view_android.cc
index 3ca5c1ba..e1f82bc 100644
--- a/chrome/browser/password_manager/android/password_ui_view_android.cc
+++ b/chrome/browser/password_manager/android/password_ui_view_android.cc
@@ -37,14 +37,56 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
+namespace {
+
 using base::android::ConvertUTF16ToJavaString;
 using base::android::ConvertUTF8ToJavaString;
 using base::android::JavaParamRef;
 using base::android::JavaRef;
 using base::android::ScopedJavaLocalRef;
-
 using IsInsecureCredential = CredentialEditBridge::IsInsecureCredential;
 
+PasswordUIViewAndroid::SerializationResult SerializePasswords(
+    const base::FilePath& target_directory,
+    std::vector<password_manager::CredentialUIEntry> credentials) {
+  // The UI should not trigger serialization if there are no passwords.
+  DCHECK(!credentials.empty());
+
+  // Creating a file will block the execution on I/O.
+  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                base::BlockingType::WILL_BLOCK);
+
+  // Ensure that the target directory exists.
+  base::File::Error error = base::File::FILE_OK;
+  if (!base::CreateDirectoryAndGetError(target_directory, &error)) {
+    return {0, std::string(), base::File::ErrorToString(error)};
+  }
+
+  // Create a temporary file in the target directory to hold the serialized
+  // passwords.
+  base::FilePath export_file;
+  if (!base::CreateTemporaryFileInDir(target_directory, &export_file)) {
+    return {
+        0, std::string(),
+        logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode())};
+  }
+
+  // Write the serialized data in CSV.
+  std::string data =
+      password_manager::PasswordCSVWriter::SerializePasswords(credentials);
+  int bytes_written = base::WriteFile(export_file, data.data(), data.size());
+  if (bytes_written != base::checked_cast<int>(data.size())) {
+    return {
+        0, std::string(),
+        logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode())};
+  }
+
+  return {static_cast<int>(credentials.size()), export_file.value(),
+          std::string()};
+}
+
+}  // namespace
+
 PasswordUIViewAndroid::PasswordUIViewAndroid(JNIEnv* env, jobject obj)
     : password_manager_presenter_(this), weak_java_ui_controller_(env, obj) {
   password_manager_presenter_.Initialize();
@@ -187,6 +229,12 @@
       NOTREACHED();
       return;
   }
+  std::vector<password_manager::CredentialUIEntry> credentials =
+      saved_passwords_presenter_.GetSavedCredentials();
+  base::EraseIf(credentials, [](const auto& credential) {
+    return credential.blocked_by_user;
+  });
+
   // The tasks are posted with base::Unretained, because deletion is postponed
   // until the reply arrives (look for the occurrences of DELETION_PENDING in
   // this file). The background processing is not expected to take very long,
@@ -196,9 +244,9 @@
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
       base::BindOnce(
-          &PasswordUIViewAndroid::ObtainAndSerializePasswords,
-          base::Unretained(this),
-          base::FilePath(ConvertJavaStringToUTF8(env, java_target_directory))),
+          &SerializePasswords,
+          base::FilePath(ConvertJavaStringToUTF8(env, java_target_directory)),
+          std::move(credentials)),
       base::BindOnce(&PasswordUIViewAndroid::PostSerializedPasswords,
                      base::Unretained(this),
                      base::android::ScopedJavaGlobalRef<jobject>(
@@ -217,9 +265,9 @@
       password_manager_presenter_.GetPassword(index);
   if (form && !credential_edit_bridge_) {
     credential_edit_bridge_ = CredentialEditBridge::MaybeCreate(
-        *form, IsInsecureCredential(false),
+        password_manager::CredentialUIEntry(*form), IsInsecureCredential(false),
         password_manager_presenter_.GetUsernamesForRealm(index),
-        &saved_passwords_presenter_, &password_manager_presenter_,
+        &saved_passwords_presenter_,
         base::BindOnce(&PasswordUIViewAndroid::OnEditUIDismissed,
                        base::Unretained(this)),
         context, settings_launcher);
@@ -236,8 +284,8 @@
       password_manager_presenter_.GetPasswordException(index);
   if (form && !credential_edit_bridge_) {
     credential_edit_bridge_ = CredentialEditBridge::MaybeCreate(
-        *form, IsInsecureCredential(false), std::vector<std::u16string>(),
-        &saved_passwords_presenter_, &password_manager_presenter_,
+        password_manager::CredentialUIEntry(*form), IsInsecureCredential(false),
+        std::vector<std::u16string>(), &saved_passwords_presenter_,
         base::BindOnce(&PasswordUIViewAndroid::OnEditUIDismissed,
                        base::Unretained(this)),
         context, settings_launcher);
@@ -274,51 +322,6 @@
   return reinterpret_cast<intptr_t>(controller);
 }
 
-PasswordUIViewAndroid::SerializationResult
-PasswordUIViewAndroid::ObtainAndSerializePasswords(
-    const base::FilePath& target_directory) {
-  std::vector<password_manager::CredentialUIEntry> credentials =
-      saved_passwords_presenter_.GetSavedCredentials();
-  base::EraseIf(credentials, [](const auto& credential) {
-    return credential.blocked_by_user;
-  });
-
-  // The UI should not trigger serialization if there are not passwords.
-  DCHECK(!credentials.empty());
-
-  // Creating a file will block the execution on I/O.
-  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
-                                                base::BlockingType::WILL_BLOCK);
-
-  // Ensure that the target directory exists.
-  base::File::Error error = base::File::FILE_OK;
-  if (!base::CreateDirectoryAndGetError(target_directory, &error)) {
-    return {0, std::string(), base::File::ErrorToString(error)};
-  }
-
-  // Create a temporary file in the target directory to hold the serialized
-  // passwords.
-  base::FilePath export_file;
-  if (!base::CreateTemporaryFileInDir(target_directory, &export_file)) {
-    return {
-        0, std::string(),
-        logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode())};
-  }
-
-  // Write the serialized data in CSV.
-  std::string data =
-      password_manager::PasswordCSVWriter::SerializePasswords(credentials);
-  int bytes_written = base::WriteFile(export_file, data.data(), data.size());
-  if (bytes_written != base::checked_cast<int>(data.size())) {
-    return {
-        0, std::string(),
-        logging::SystemErrorCodeToString(logging::GetLastSystemErrorCode())};
-  }
-
-  return {static_cast<int>(credentials.size()), export_file.value(),
-          std::string()};
-}
-
 void PasswordUIViewAndroid::PostSerializedPasswords(
     const base::android::JavaRef<jobject>& success_callback,
     const base::android::JavaRef<jobject>& error_callback,
diff --git a/chrome/browser/password_manager/android/password_ui_view_android.h b/chrome/browser/password_manager/android/password_ui_view_android.h
index 39f62c92..484a94c8 100644
--- a/chrome/browser/password_manager/android/password_ui_view_android.h
+++ b/chrome/browser/password_manager/android/password_ui_view_android.h
@@ -126,10 +126,6 @@
   // ALIVE_SERIALIZATION_PENDING:
   //   * Destroy was not called, password serialization task on another task
   //     runner is running.
-  //   * All data members can be used on the main task runner, except for
-  //     |password_manager_presenter_| which can only be used inside
-  //     ObtainAndSerializePasswords, which is being run on a backend task
-  //     runner.
   // DELETION_PENDING:
   //   * Destroy() was called, a background task is pending and |this| should
   //     be deleted once the tasks complete.
@@ -137,14 +133,6 @@
   //     of the pending task.
   enum class State { ALIVE, ALIVE_SERIALIZATION_PENDING, DELETION_PENDING };
 
-  // Calls |password_manager_presenter_| to retrieve cached PasswordForm
-  // objects, then PasswordCSVWriter to serialize them, and finally writes them
-  // to a temporary file in |target_directory|. The steps involve a lot of
-  // memory allocation and copying, as well as I/O operations, so this method
-  // should be executed on a suitable task runner.
-  SerializationResult ObtainAndSerializePasswords(
-      const base::FilePath& target_directory);
-
   // Sends |serialization_result| to Java via |success_callback| or
   // |error_callback|, depending on whether the result is a success or an error.
   void PostSerializedPasswords(
diff --git a/chrome/browser/pdf/pdf_extension_test_util.cc b/chrome/browser/pdf/pdf_extension_test_util.cc
index e2477512..92023740 100644
--- a/chrome/browser/pdf/pdf_extension_test_util.cc
+++ b/chrome/browser/pdf/pdf_extension_test_util.cc
@@ -15,11 +15,12 @@
 
 testing::AssertionResult EnsurePDFHasLoaded(
     const content::ToRenderFrameHost& frame,
-    bool wait_for_hit_test_data) {
+    bool wait_for_hit_test_data,
+    const std::string& pdf_element) {
   bool load_success = false;
   if (!content::ExecuteScriptAndExtractBool(
           frame,
-          R"(window.addEventListener('message', event => {
+          content::JsReplace(R"(window.addEventListener('message', event => {
             if (event.origin !==
                     'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai') {
               return;
@@ -31,8 +32,9 @@
               window.domAutomationController.send(true);
             }
           });
-          document.getElementsByTagName('embed')[0].postMessage(
+          document.getElementsByTagName($1)[0].postMessage(
               {type: 'initialize'});)",
+                             pdf_element),
           &load_success)) {
     return testing::AssertionFailure()
            << "Cannot communicate with PDF extension.";
diff --git a/chrome/browser/pdf/pdf_extension_test_util.h b/chrome/browser/pdf/pdf_extension_test_util.h
index 9f33adb4..0bb76f7c 100644
--- a/chrome/browser/pdf/pdf_extension_test_util.h
+++ b/chrome/browser/pdf/pdf_extension_test_util.h
@@ -29,7 +29,8 @@
 // since the delay should be small.)
 [[nodiscard]] testing::AssertionResult EnsurePDFHasLoaded(
     const content::ToRenderFrameHost& frame,
-    bool wait_for_hit_test_data = true);
+    bool wait_for_hit_test_data = true,
+    const std::string& pdf_element = "embed");
 
 gfx::Point ConvertPageCoordToScreenCoord(content::WebContents* contents,
                                          const gfx::Point& point);
diff --git a/chrome/browser/policy/BUILD.gn b/chrome/browser/policy/BUILD.gn
index 0469bcb8..a29521f 100644
--- a/chrome/browser/policy/BUILD.gn
+++ b/chrome/browser/policy/BUILD.gn
@@ -314,6 +314,7 @@
     sources += [ "extension_policy_browsertest.cc" ]
 
     deps += [
+      "//chrome/browser/ash/system_web_apps/test_support",
       "//chrome/browser/extensions:test_support",
       "//chrome/browser/web_applications:web_applications_test_support",
       "//components/webapps/browser:browser",
@@ -348,9 +349,9 @@
       "//ash/components/audio:audio",
       "//ash/components/cryptohome",
       "//chrome/browser/ash",
+      "//chromeos/ash/components/dbus/userdataauth",
       "//chromeos/ash/services/assistant/public/cpp",
       "//chromeos/dbus/constants",
-      "//chromeos/dbus/userdataauth",
       "//components/account_id",
     ]
   }
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.cc b/chrome/browser/policy/chrome_browser_policy_connector.cc
index d29b739..1e6cb56 100644
--- a/chrome/browser/policy/chrome_browser_policy_connector.cc
+++ b/chrome/browser/policy/chrome_browser_policy_connector.cc
@@ -258,8 +258,7 @@
   std::unique_ptr<AsyncPolicyLoader> loader(PolicyLoaderWin::Create(
       base::ThreadPool::CreateSequencedTaskRunner(
           {base::MayBlock(), base::TaskPriority::BEST_EFFORT}),
-      ManagementServiceFactory::GetForPlatform(), kRegistryChromePolicyKey,
-      IsCommandLineSwitchSupported()));
+      ManagementServiceFactory::GetForPlatform(), kRegistryChromePolicyKey));
   return std::make_unique<AsyncPolicyProvider>(GetSchemaRegistry(),
                                                std::move(loader));
 #elif BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
index 013afa6..dee1b11 100644
--- a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
@@ -62,8 +62,8 @@
 #include "base/files/file_util.h"
 #include "base/path_service.h"
 #include "chrome/browser/ash/policy/core/user_cloud_policy_manager_ash.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/constants/dbus_paths.h"  // nogncheck
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/user_names.h"
 #else
diff --git a/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.cc b/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.cc
index 49d4949..8ad6ff14 100644
--- a/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.cc
+++ b/chrome/browser/policy/messaging_layer/upload/event_upload_size_controller.cc
@@ -8,6 +8,7 @@
 #include <limits>
 #include <vector>
 
+#include "base/metrics/histogram_functions.h"
 #include "chrome/browser/policy/messaging_layer/upload/network_condition_service.h"
 #include "components/reporting/proto/synced/record.pb.h"
 
@@ -19,7 +20,18 @@
     uint64_t remaining_storage_capacity)
     : new_events_rate_(new_events_rate > 0 ? new_events_rate : 1),
       remaining_storage_capacity_(remaining_storage_capacity),
-      max_upload_size_(ComputeMaxUploadSize(network_condition_service)) {}
+      max_upload_size_(ComputeMaxUploadSize(network_condition_service)) {
+  base::UmaHistogramCounts10000(
+      "Browser.ERP.EventUploadSizeAdjustment.NewEventsRate", new_events_rate_);
+  base::UmaHistogramCustomCounts(
+      "Browser.ERP.EventUploadSizeAdjustment.RemainingStorageCapacity",
+      /*sample=*/remaining_storage_capacity_,
+      /*min=*/1,
+      /*exclusive_max=*/80'000'000,
+      /*buckets=*/50);
+  base::UmaHistogramCounts10M(
+      "Browser.ERP.EventUploadSizeAdjustment.MaxUploadSize", max_upload_size_);
+}
 
 bool EventUploadSizeController::IsMaximumUploadSizeReached() const {
   return Enabler::Get() && uploaded_size_ >= max_upload_size_;
diff --git a/chrome/browser/policy/networking/network_configuration_updater_ash_unittest.cc b/chrome/browser/policy/networking/network_configuration_updater_ash_unittest.cc
index ceb54d4..64de686 100644
--- a/chrome/browser/policy/networking/network_configuration_updater_ash_unittest.cc
+++ b/chrome/browser/policy/networking/network_configuration_updater_ash_unittest.cc
@@ -21,13 +21,13 @@
 #include "chrome/browser/policy/networking/user_network_configuration_updater_ash.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
+#include "chromeos/ash/components/network/fake_network_device_handler.h"
+#include "chromeos/ash/components/network/mock_managed_network_configuration_handler.h"
 #include "chromeos/ash/components/network/onc/onc_certificate_importer.h"
 #include "chromeos/components/onc/certificate_scope.h"
 #include "chromeos/components/onc/onc_parsed_certificates.h"
 #include "chromeos/components/onc/onc_test_utils.h"
 #include "chromeos/components/onc/onc_utils.h"
-#include "chromeos/network/fake_network_device_handler.h"
-#include "chromeos/network/mock_managed_network_configuration_handler.h"
 #include "chromeos/network/policy_certificate_provider.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "chromeos/system/statistics_provider.h"
@@ -448,7 +448,7 @@
  private:
   base::Value fake_network_configs_;
   base::Value fake_global_network_config_{base::Value::Type::DICTIONARY};
-  chromeos::ScopedFakeSessionManagerClient scoped_session_manager_client_;
+  ash::ScopedFakeSessionManagerClient scoped_session_manager_client_;
 };
 
 TEST_F(NetworkConfigurationUpdaterAshTest, CellularRoamingDefaults) {
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 8bfc3599..9c47d3c 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -423,6 +423,7 @@
 #include "chrome/browser/font_prewarmer_tab_helper.h"
 #include "chrome/browser/media/cdm_pref_service_helper.h"
 #include "chrome/browser/media/media_foundation_service_monitor.h"
+#include "chrome/browser/os_crypt/app_bound_encryption_metrics_win.h"
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
 #include "chrome/browser/win/conflicts/incompatible_applications_updater.h"
 #include "chrome/browser/win/conflicts/module_database.h"
@@ -744,6 +745,8 @@
 
 // Deprecated 06/2022.
 const char kBackgroundTracingLastUpload[] = "background_tracing.last_upload";
+const char kStabilityGpuCrashCount[] =
+    "user_experience_metrics.stability.gpu_crash_count";
 
 // Register local state used only for migration (clearing or moving to a new
 // key).
@@ -801,6 +804,7 @@
 
   // Deprecated 06/2022.
   registry->RegisterInt64Pref(kBackgroundTracingLastUpload, 0);
+  registry->RegisterIntegerPref(kStabilityGpuCrashCount, 0);
 }
 
 // Register prefs used only for migration (clearing or moving to a new key).
@@ -1181,6 +1185,7 @@
   component_updater::RegisterPrefsForSwReporter(registry);
   safe_browsing::RegisterChromeCleanerScanCompletionTimePref(registry);
   MediaFoundationServiceMonitor::RegisterPrefs(registry);
+  os_crypt::RegisterLocalStatePrefs(registry);
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
   IncompatibleApplicationsUpdater::RegisterLocalStatePrefs(registry);
   ModuleDatabase::RegisterLocalStatePrefs(registry);
@@ -1653,6 +1658,7 @@
 
   // Added 06/2022.
   local_state->ClearPref(kBackgroundTracingLastUpload);
+  local_state->ClearPref(kStabilityGpuCrashCount);
 
   // Please don't delete the following line. It is used by PRESUBMIT.py.
   // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS
diff --git a/chrome/browser/preloading/OWNERS b/chrome/browser/preloading/OWNERS
new file mode 100644
index 0000000..e04727b3
--- /dev/null
+++ b/chrome/browser/preloading/OWNERS
@@ -0,0 +1,3 @@
+nhiroki@chromium.org
+ryansturm@chromium.org
+spelchat@chromium.org
diff --git a/chrome/browser/chrome_preloading.cc b/chrome/browser/preloading/chrome_preloading.cc
similarity index 89%
rename from chrome/browser/chrome_preloading.cc
rename to chrome/browser/preloading/chrome_preloading.cc
index 788aa8d8..7237349 100644
--- a/chrome/browser/chrome_preloading.cc
+++ b/chrome/browser/preloading/chrome_preloading.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 "chrome/browser/chrome_preloading.h"
+#include "chrome/browser/preloading/chrome_preloading.h"
 
 content::PreloadingPredictor ToPreloadingPredictor(
     ChromePreloadingPredictor predictor) {
diff --git a/chrome/browser/chrome_preloading.h b/chrome/browser/preloading/chrome_preloading.h
similarity index 92%
rename from chrome/browser/chrome_preloading.h
rename to chrome/browser/preloading/chrome_preloading.h
index 0e8bce1c..17b2302 100644
--- a/chrome/browser/chrome_preloading.h
+++ b/chrome/browser/preloading/chrome_preloading.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROME_PRELOADING_H_
-#define CHROME_BROWSER_CHROME_PRELOADING_H_
+#ifndef CHROME_BROWSER_PRELOADING_CHROME_PRELOADING_H_
+#define CHROME_BROWSER_PRELOADING_CHROME_PRELOADING_H_
 
 #include "content/public/browser/preloading.h"
 
@@ -52,4 +52,4 @@
 content::PreloadingEligibility ToPreloadingEligibility(
     ChromePreloadingEligibility eligibility);
 
-#endif  // CHROME_BROWSER_CHROME_PRELOADING_H_
+#endif  // CHROME_BROWSER_PRELOADING_CHROME_PRELOADING_H_
diff --git a/chrome/browser/prerender/prerender_omnibox_ui_browsertest.cc b/chrome/browser/prerender/prerender_omnibox_ui_browsertest.cc
index c1aa04a..51c4c0b 100644
--- a/chrome/browser/prerender/prerender_omnibox_ui_browsertest.cc
+++ b/chrome/browser/prerender/prerender_omnibox_ui_browsertest.cc
@@ -14,6 +14,8 @@
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
 #include "chrome/browser/predictors/autocomplete_action_predictor.h"
 #include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h"
+#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service_factory.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_utils.h"
 #include "chrome/browser/profiles/profile.h"
@@ -679,6 +681,19 @@
   prerender_helper().WaitForPrerenderLoadCompletion(*GetActiveWebContents(),
                                                     expected_prerender_url);
 
+  // With the default setting, there should be no prefetches because the server
+  // does not respond a prefetch suggestion.
+  SearchPrefetchService* search_prefetch_service =
+      SearchPrefetchServiceFactory::GetForProfile(Profile::FromBrowserContext(
+          GetActiveWebContents()->GetBrowserContext()));
+  ASSERT_NE(search_prefetch_service, nullptr);
+  absl::optional<SearchPrefetchStatus> prefetch_status =
+      search_prefetch_service->GetSearchPrefetchStatusForTesting(
+          u"prerender222");
+  EXPECT_FALSE(prefetch_status.has_value());
+  histogram_tester.ExpectTotalCount(
+      "Omnibox.SearchPrefetch.PrefetchEligibilityReason.SuggestionPrefetch", 0);
+
   content::RenderFrameHost* prerender_rfh =
       prerender_helper().GetPrerenderedMainFrameHost(host_id);
   EXPECT_TRUE(
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogConsent.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogConsent.java
index 79732d6..6e97aa6 100644
--- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogConsent.java
+++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogConsent.java
@@ -127,14 +127,16 @@
     }
 
     private void updateDropdownControlContentDescription(View dropdownElement) {
-        // TODO(crbug.com/1286276): add CONCAT_TWO_STRINGS_WITH_PERIODS to Android strings and use
-        // that instead to avoid l10n issues.
-        String description = getContext().getResources().getString(
-                                     R.string.privacy_sandbox_consent_dropdown_button)
-                + ". "
-                + getContext().getResources().getString(mDropdownExpanded
-                                ? R.string.accessibility_expanded_group
-                                : R.string.accessibility_collapsed_group);
+        String dropdownButtonText = getContext().getResources().getString(
+                R.string.privacy_sandbox_consent_dropdown_button);
+
+        String collapseOrExpandedText = getContext().getResources().getString(mDropdownExpanded
+                        ? R.string.accessibility_expanded_group
+                        : R.string.accessibility_collapsed_group);
+
+        String description =
+                getContext().getResources().getString(R.string.concat_two_strings_with_periods,
+                        dropdownButtonText, collapseOrExpandedText);
         dropdownElement.setContentDescription(description);
     }
 
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
index e39f177c..a8bb01e82 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
@@ -39,6 +39,10 @@
 #include "chrome/browser/ui/hats/trust_safety_sentiment_service.h"
 #endif
 
+#if BUILDFLAG(IS_CHROMEOS)
+#include "chrome/browser/profiles/profiles_state.h"
+#endif
+
 namespace {
 
 constexpr char kBlockedTopicsTopicKey[] = "topic";
@@ -139,6 +143,22 @@
             });
 }
 
+// Returns whether |profile_type|, and the current browser session on CrOS,
+// represent a regular (e.g. non guest, non system, non kiosk) profile.
+bool IsRegularProfile(profile_metrics::BrowserProfileType profile_type) {
+  if (profile_type != profile_metrics::BrowserProfileType::kRegular)
+    return false;
+
+#if BUILDFLAG(IS_CHROMEOS)
+  // Any Device Local account, which is a CrOS concept powering things like
+  // Kiosks and Managed Guest Sessions, is not considered regular.
+  return !profiles::IsPublicSession() && !profiles::IsKioskSession() &&
+         !profiles::IsChromeAppKioskSession();
+#else
+  return true;
+#endif
+}
+
 }  // namespace
 
 PrivacySandboxService::PrivacySandboxService() = default;
@@ -751,7 +771,7 @@
 
 void PrivacySandboxService::LogPrivacySandboxState() {
   // Do not record metrics for non-regular profiles.
-  if (profile_type_ != profile_metrics::BrowserProfileType::kRegular)
+  if (!IsRegularProfile(profile_type_))
     return;
 
   // Start by recording any metrics for Privacy Sandbox 3.
@@ -932,7 +952,7 @@
     return PromptType::kNone;
 
   // If the profile isn't a regular profile, no prompt should ever be shown.
-  if (profile_type != profile_metrics::BrowserProfileType::kRegular)
+  if (!IsRegularProfile(profile_type))
     return PromptType::kNone;
 
   // If the release 3 feature is not enabled, no prompt is required.
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
index 03ef6a1..550a32d 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
@@ -48,6 +48,16 @@
 #include "chrome/browser/ui/hats/mock_trust_safety_sentiment_service.h"
 #endif
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
+#include "chromeos/login/login_state/login_state.h"
+#endif
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chromeos/crosapi/mojom/crosapi.mojom.h"
+#include "chromeos/startup/browser_init_params.h"
+#endif
+
 namespace {
 using browsing_topics::Topic;
 using privacy_sandbox::CanonicalTopic;
@@ -1839,6 +1849,60 @@
   EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxApisEnabledV2));
 }
 
+#if BUILDFLAG(IS_CHROMEOS)
+TEST_F(PrivacySandboxServiceTest, DeviceLocalAccountUser) {
+  // No prompt should be shown if the user is associated with a device local
+  // account on CrOS.
+  SetupDialogTestState(feature_list(), prefs(),
+                       {/*consent_required=*/true,
+                        /*old_api_pref=*/true,
+                        /*new_api_pref=*/false,
+                        /*notice_displayed=*/false,
+                        /*consent_decision_made=*/false,
+                        /*confirmation_not_shown=*/false});
+  // No prompt should be shown for a public session account.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  chromeos::LoginState::Initialize();
+  ash::LoginState::Get()->SetLoggedInState(
+      ash::LoginState::LoggedInState::LOGGED_IN_ACTIVE,
+      ash::LoginState::LoggedInUserType::LOGGED_IN_USER_PUBLIC_ACCOUNT);
+#elif BUILDFLAG(IS_CHROMEOS_LACROS)
+  crosapi::mojom::BrowserInitParamsPtr init_params =
+      crosapi::mojom::BrowserInitParams::New();
+  init_params->session_type = crosapi::mojom::SessionType::kPublicSession;
+  chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));
+#endif
+  EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
+            privacy_sandbox_service()->GetRequiredPromptType());
+
+  // No prompt should be shown for a web kiosk account.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  ash::LoginState::Get()->SetLoggedInState(
+      ash::LoginState::LoggedInState::LOGGED_IN_ACTIVE,
+      ash::LoginState::LoggedInUserType::LOGGED_IN_USER_KIOSK);
+#elif BUILDFLAG(IS_CHROMEOS_LACROS)
+  init_params = crosapi::mojom::BrowserInitParams::New();
+  init_params->session_type = crosapi::mojom::SessionType::kWebKioskSession;
+  chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));
+#endif
+  EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
+            privacy_sandbox_service()->GetRequiredPromptType());
+
+  // A prompt should be shown for a regular user.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  ash::LoginState::Get()->SetLoggedInState(
+      ash::LoginState::LoggedInState::LOGGED_IN_ACTIVE,
+      ash::LoginState::LoggedInUserType::LOGGED_IN_USER_REGULAR);
+#elif BUILDFLAG(IS_CHROMEOS_LACROS)
+  init_params = crosapi::mojom::BrowserInitParams::New();
+  init_params->session_type = crosapi::mojom::SessionType::kRegularSession;
+  chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));
+#endif
+  EXPECT_EQ(PrivacySandboxService::PromptType::kConsent,
+            privacy_sandbox_service()->GetRequiredPromptType());
+}
+#endif  // BUILDFLAG(IS_CHROMEOS)
+
 class PrivacySandboxPrefInitTest : public PrivacySandboxServiceTest {
   void InitializeBeforeStart() override {
     feature_list()->InitAndEnableFeatureWithParameters(
@@ -2633,6 +2697,10 @@
  public:
   PrivacySandboxServiceDialogTestBase() {
     privacy_sandbox::RegisterProfilePrefs(prefs()->registry());
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    if (!user_manager::UserManager::IsInitialized())
+      user_manager_.Initialize();
+#endif
   }
 
  protected:
@@ -2646,6 +2714,9 @@
 
  private:
   base::test::ScopedFeatureList feature_list_;
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  ash::FakeChromeUserManager user_manager_;
+#endif
   sync_preferences::TestingPrefServiceSyncable pref_service_;
   MockPrivacySandboxSettings privacy_sandbox_settings_;
 };
diff --git a/chrome/browser/resources/certificate_viewer/BUILD.gn b/chrome/browser/resources/certificate_viewer/BUILD.gn
index 461a6ffa..0986258 100644
--- a/chrome/browser/resources/certificate_viewer/BUILD.gn
+++ b/chrome/browser/resources/certificate_viewer/BUILD.gn
@@ -2,12 +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/ui.gni")
-import("//crypto/features.gni")
+import("//chrome/common/features.gni")
 import("//tools/typescript/ts_library.gni")
 
-assert(use_nss_certs)
-assert(use_aura)
+assert(enable_webui_certificate_viewer)
 
 ts_library("build_ts") {
   root_dir = "."
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
index c0cbeac..df5626e 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -3948,6 +3948,28 @@
       .replay();
 });
 
+// Make sure navigation with touch to ListBox lands on options.
+TEST_F(
+    'ChromeVoxBackgroundTest', 'TouchListBoxItemsNavigation', async function() {
+      const mockFeedback = this.createMockFeedback();
+      await this.runWithLoadedTree(this.listBoxDoc);
+      mockFeedback
+          .call(doGesture(chrome.accessibilityPrivate.Gesture.SWIPE_RIGHT1))
+          .expectSpeech('Start')
+          .call(doGesture(chrome.accessibilityPrivate.Gesture.SWIPE_RIGHT1))
+          .expectSpeech(
+              'Listbox item one', ' 1 of 3 ', 'Select an item', 'List box')
+          .call(doGesture(chrome.accessibilityPrivate.Gesture.SWIPE_RIGHT1))
+          .expectSpeech('Listbox item two', ' 2 of 3 ')
+          .call(doGesture(chrome.accessibilityPrivate.Gesture.SWIPE_LEFT1))
+          .expectSpeech('Listbox item one', ' 1 of 3 ')
+          .call(doGesture(chrome.accessibilityPrivate.Gesture.SWIPE_RIGHT1))
+          .expectSpeech('Listbox item two', ' 2 of 3 ')
+          .call(doGesture(chrome.accessibilityPrivate.Gesture.SWIPE_RIGHT1))
+          .expectSpeech('Listbox item three', ' 3 of 3 ')
+          .replay();
+    });
+
 TEST_F(
     'ChromeVoxBackgroundTest', 'CrossWindowNextPreviousFocus',
     async function() {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
index 09199d0a..2f7a9e40 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -648,8 +648,10 @@
       case 'nextObject':
         skipSettingSelection = true;
         didNavigate = true;
-        unit = cursors.Unit.NODE;
-        current = current.move(cursors.Unit.NODE, dir);
+        unit = (EventSourceState.get() === EventSourceType.TOUCH_GESTURE) ?
+            cursors.Unit.GESTURE_NODE :
+            cursors.Unit.NODE;
+        current = current.move(unit, dir);
         current = this.skipLabelOrDescriptionFor(current, dir);
         break;
       case 'previousGroup':
diff --git a/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js b/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js
index b6a10a68..68189ae 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js
@@ -395,6 +395,19 @@
   }
 
   /**
+   * Matches against nodes visited during object navigation with a gesture.
+   * @param {!AutomationNode} node
+   * @return {boolean}
+   */
+  static gestureObject(node) {
+    if (node.role === Role.LIST_BOX) {
+      return false;
+    }
+    return AutomationPredicate.object(node);
+  }
+
+
+  /**
    * @param {!AutomationNode} first
    * @param {!AutomationNode} second
    * @return {boolean}
diff --git a/chrome/browser/resources/chromeos/accessibility/common/automation_util.js b/chrome/browser/resources/chromeos/accessibility/common/automation_util.js
index 881be4b4..afc038e 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/automation_util.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/automation_util.js
@@ -99,10 +99,10 @@
    *     |skipInitialAncestry|, and |skipInitialSubtree| are valid restrictions
    *     used when finding the next node.
    *     By default:
-   *        the root predicate ges set to |AutomationPredicate.root|.
+   *        the root predicate gets set to |AutomationPredicate.root|.
    *        |skipInitialSubtree| is false if |cur| is a container or matches
    *        |pred|. This alleviates the caller from syncing forwards.
-   *        Leaves are nodes matched by |prred| which are not also containers.
+   *        Leaves are nodes matched by |pred| which are not also containers.
    *        This takes care of syncing backwards.
    * @return {AutomationNode}
    */
@@ -129,10 +129,10 @@
    *     |skipInitialAncestry|, and |skipInitialSubtree| are valid restrictions
    *     used when finding the next node.
    *     By default:
-   *        the root predicate ges set to |AutomationPredicate.root|.
+   *        the root predicate gets set to |AutomationPredicate.root|.
    *        |skipInitialSubtree| is false if |cur| is a container or matches
    *        |pred|. This alleviates the caller from syncing forwards.
-   *        Leaves are nodes matched by |prred| which are not also containers.
+   *        Leaves are nodes matched by |pred| which are not also containers.
    *        This takes care of syncing backwards.
    * @return {!Array<!AutomationNode>}
    */
diff --git a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js
index 2f0ea449..cc095be 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/cursors/cursor.js
@@ -48,6 +48,9 @@
   /** A leaf node. */
   NODE: 'node',
 
+  /** A leaf node for guesture navigation. */
+  GESTURE_NODE: 'gesture_node',
+
   /**
    * A node or in line textbox that immediately precedes or follows a visual
    *     line break.
@@ -126,6 +129,22 @@
   }
 
   /**
+   * Gives a function that returns true for leaf types for |unit| navigations.
+   * @param {!cursor.Unit} unit
+   * @return {function}
+   */
+  static getLeafPredForUnit(unit) {
+    switch (unit) {
+      case cursors.Unit.TEXT:
+        return AutomationPredicate.leaf;
+      case cursors.Unit.GESTURE_NODE:
+        return AutomationPredicate.gestureObject;
+      default:
+        return AutomationPredicate.object;
+    }
+  }
+
+  /**
    * Returns true if |rhs| is equal to this cursor.
    * Use this for strict equality between cursors.
    * @param {!cursors.Cursor} rhs
@@ -341,7 +360,7 @@
               newIndex = dir === Dir.FORWARD ? firstWordStart - 1 :
                                                this.getText().length;
             }
-            // fallthrough
+          // fallthrough
           case cursors.Movement.DIRECTIONAL: {
             let wordStarts, wordEnds;
             let start;
@@ -395,14 +414,13 @@
         break;
       case cursors.Unit.TEXT:
       case cursors.Unit.NODE:
+      case cursors.Unit.GESTURE_NODE:
         switch (movement) {
           case cursors.Movement.BOUND:
             newIndex = dir === Dir.FORWARD ? this.getText().length - 1 : 0;
             break;
           case cursors.Movement.DIRECTIONAL:
-            const pred = unit === cursors.Unit.TEXT ?
-                AutomationPredicate.leaf :
-                AutomationPredicate.object;
+            const pred = cursors.Cursor.getLeafPredForUnit(unit);
             newNode =
                 AutomationUtil.findNextNode(newNode, dir, pred) || originalNode;
             newIndex = cursors.NODE_INDEX;
@@ -646,8 +664,7 @@
     // For 2, place range on the root (if not already there). If at root,
     // try to descend to the first leaf-like object.
     if (movement === cursors.Movement.DIRECTIONAL && result.equals(this)) {
-      const pred = unit === cursors.Unit.NODE ? AutomationPredicate.object :
-                                                AutomationPredicate.leaf;
+      const pred = cursors.Cursor.getLeafPredForUnit(unit);
       let endpoint = this.node;
       if (!endpoint) {
         return this;
diff --git a/chrome/browser/resources/chromeos/accessibility/common/cursors/range.js b/chrome/browser/resources/chromeos/accessibility/common/cursors/range.js
index 6073f7e58..7b95583 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/cursors/range.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/cursors/range.js
@@ -204,6 +204,7 @@
         newEnd = newStart.move(unit, cursors.Movement.BOUND, Dir.FORWARD);
         break;
       case cursors.Unit.NODE:
+      case cursors.Unit.GESTURE_NODE:
         newStart = newStart.move(unit, cursors.Movement.DIRECTIONAL, dir);
         newEnd = newStart;
         break;
@@ -318,8 +319,8 @@
         return cursors.Range.fromNode(newNode);
       case cursors.Unit.TEXT:
       case cursors.Unit.NODE:
-        const pred = unit === cursors.Unit.TEXT ? AutomationPredicate.leaf :
-                                                  AutomationPredicate.object;
+      case cursors.Unit.GESTURE_NODE:
+        const pred = cursors.Cursor.getLeafPredForUnit(unit);
         let node;
         if (dir === Dir.FORWARD) {
           node = AutomationUtil.findNextNode(
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn
index b5deb8a..c80617d 100644
--- a/chrome/browser/resources/chromeos/login/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -126,6 +126,8 @@
     "images/2x/thumbnail-theme-dark-2x.png",
     "images/1x/thumbnail-theme-auto-1x.png",
     "images/2x/thumbnail-theme-auto-2x.png",
+    "images/blazey_dark.svg",
+    "images/blazey_light.svg",
   ]
   input_files_base_dir = rebase_path(".", "//")
   resource_path_rewrites = [
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_icons.html b/chrome/browser/resources/chromeos/login/components/oobe_icons.html
index c531a640..84e6c98a 100644
--- a/chrome/browser/resources/chromeos/login/components/oobe_icons.html
+++ b/chrome/browser/resources/chromeos/login/components/oobe_icons.html
@@ -108,6 +108,15 @@
           <use fill="#D93025" fill-rule="nonzero" xlink:href="#a"></use>
         </g>
       </g>
+      <g id="game-controller-dark">
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M28.8 6.39999H3.2C1.44 6.39999 0 7.83999 0 9.59999V22.4C0 24.16 1.44 25.6 3.2 25.6H28.8C30.56 25.6 32 24.16 32 22.4V9.59999C32 7.83999 30.56 6.39999 28.8 6.39999ZM28.8 22.4H3.2V9.59999H28.8V22.4ZM8 20.8H11.2V17.6H14.4V14.4H11.2V11.2H8V14.4H4.8V17.6H8V20.8ZM20 20.8C21.3255 20.8 22.4 19.7255 22.4 18.4C22.4 17.0745 21.3255 16 20 16C18.6745 16 17.6 17.0745 17.6 18.4C17.6 19.7255 18.6745 20.8 20 20.8ZM24.8 16C26.1255 16 27.2 14.9255 27.2 13.6C27.2 12.2745 26.1255 11.2 24.8 11.2C23.4745 11.2 22.4 12.2745 22.4 13.6C22.4 14.9255 23.4745 16 24.8 16Z" fill="#8AB4F8"></path>
+      </g>
+      <g id="game-controller-dark">
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M28.8 6.39999H3.2C1.44 6.39999 0 7.83999 0 9.59999V22.4C0 24.16 1.44 25.6 3.2 25.6H28.8C30.56 25.6 32 24.16 32 22.4V9.59999C32 7.83999 30.56 6.39999 28.8 6.39999ZM28.8 22.4H3.2V9.59999H28.8V22.4ZM8 20.8H11.2V17.6H14.4V14.4H11.2V11.2H8V14.4H4.8V17.6H8V20.8ZM20 20.8C21.3255 20.8 22.4 19.7255 22.4 18.4C22.4 17.0745 21.3255 16 20 16C18.6745 16 17.6 17.0745 17.6 18.4C17.6 19.7255 18.6745 20.8 20 20.8ZM24.8 16C26.1255 16 27.2 14.9255 27.2 13.6C27.2 12.2745 26.1255 11.2 24.8 11.2C23.4745 11.2 22.4 12.2745 22.4 13.6C22.4 14.9255 23.4745 16 24.8 16Z" fill="#8AB4F8"></path>
+      </g>
+      <g id="game-controller-light">
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M28.8 6.39999H3.2C1.44 6.39999 0 7.83999 0 9.59999V22.4C0 24.16 1.44 25.6 3.2 25.6H28.8C30.56 25.6 32 24.16 32 22.4V9.59999C32 7.83999 30.56 6.39999 28.8 6.39999ZM28.8 22.4H3.2V9.59999H28.8V22.4ZM8 20.8H11.2V17.6H14.4V14.4H11.2V11.2H8V14.4H4.8V17.6H8V20.8ZM20 20.8C21.3255 20.8 22.4 19.7255 22.4 18.4C22.4 17.0745 21.3255 16 20 16C18.6745 16 17.6 17.0745 17.6 18.4C17.6 19.7255 18.6745 20.8 20 20.8ZM24.8 16C26.1255 16 27.2 14.9255 27.2 13.6C27.2 12.2745 26.1255 11.2 24.8 11.2C23.4745 11.2 22.4 12.2745 22.4 13.6C22.4 14.9255 23.4745 16 24.8 16Z" fill="#1A73E8"></path>
+      </g>
       <g id="lock">
         <defs>
           <path id="a" d="M24 12h-1.333V9.333A6.67 6.67 0 0 0 16 2.667a6.67 6.67 0 0 0-6.667 6.666V12H8a2.675 2.675 0 0 0-2.667 2.667V28c0 1.467 1.2 2.667 2.667 2.667h16c1.467 0 2.667-1.2 2.667-2.667V14.667C26.667 13.2 25.467 12 24 12zM12 9.333c0-2.213 1.787-4 4-4s4 1.787 4 4V12h-8V9.333zM24 28H8V14.667h16V28zm-8-4c1.467 0 2.667-1.2 2.667-2.667 0-1.466-1.2-2.666-2.667-2.666a2.675 2.675 0 0 0-2.667 2.666C13.333 22.8 14.533 24 16 24z">
@@ -135,10 +144,14 @@
         <path fill="#1A73E8" fill-rule="nonzero"d="M29 20V0H3v20H0v3h32v-3h-3zm-10.333 0h-5.334v-1.333h5.334V20zM26 16H6V3h20v13z"></path>
         <path fill="#1A73E8" d="M16.97 8.129L16 5l-.97 3.129H12l2.47 1.836L13.53 13 16 11.123 18.47 13l-.94-3.035L20 8.129z"></path>
       </g>
-      <g id="checkmark" fill="none">
+      <g id="checkmark-light" fill="none">
         <path d="M21.9314 11.6686c-.6249-.6248-1.6379-.6248-2.2628 0L14.4 16.9373l-2.0686-2.0687c-.6249-.6248-1.6379-.6248-2.2628 0-.6248.6249-.6248 1.6379 0 2.2628l3.2 3.2c.6249.6248 1.6379.6248 2.2628 0l6.4-6.4c.6248-.6249.6248-1.6379 0-2.2628z" fill="#1A73E8"></path>
         <path fill-rule="evenodd" clip-rule="evenodd" d="M16 28.8c7.0693 0 12.8-5.7308 12.8-12.8 0-7.0693-5.7307-12.8-12.8-12.8C8.9308 3.2 3.2 8.9307 3.2 16c0 7.0692 5.7308 12.8 12.8 12.8zm0-3.2c5.3019 0 9.6-4.2981 9.6-9.6S21.3019 6.4 16 6.4 6.4 10.6981 6.4 16s4.2981 9.6 9.6 9.6z" fill="#1A73E8"></path>
       </g>
+      <g id="checkmark-dark" fill="none">
+        <path d="M21.9314 11.6686c-.6249-.6248-1.6379-.6248-2.2628 0L14.4 16.9373l-2.0686-2.0687c-.6249-.6248-1.6379-.6248-2.2628 0-.6248.6249-.6248 1.6379 0 2.2628l3.2 3.2c.6249.6248 1.6379.6248 2.2628 0l6.4-6.4c.6248-.6249.6248-1.6379 0-2.2628z" fill="#8AB4F8"></path>
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M16 28.8c7.0693 0 12.8-5.7308 12.8-12.8 0-7.0693-5.7307-12.8-12.8-12.8C8.9308 3.2 3.2 8.9307 3.2 16c0 7.0692 5.7308 12.8 12.8 12.8zm0-3.2c5.3019 0 9.6-4.2981 9.6-9.6S21.3019 6.4 16 6.4 6.4 10.6981 6.4 16s4.2981 9.6 9.6 9.6z" fill="#8AB4F8"></path>
+      </g>
       <g id="checkcircle" fill="none" fill-rule="evenodd">
         <path fill="#5BB974" fill-rule="nonzero"  d="M 16,2.6667 C 8.6400184,2.6667 2.6667,8.640018 2.6667,16 2.6667,23.359982 8.6400184,29.3333 16,29.3333 23.359982,29.3333 29.3333,23.359982 29.3333,16 29.3333,8.640018 23.359982,2.6667 16,2.6667 Z m 0,23.99994 C 10.120015,26.66664 5.33336,21.879985 5.33336,16 5.33336,10.120015 10.120015,5.33336 16,5.33336 c 5.879985,0 10.66664,4.786655 10.66664,10.66664 0,5.879985 -4.786655,10.66664 -10.66664,10.66664 z M 13.33334,18.933326 9.866682,15.466668 8.00002,17.33333 13.33334,22.66665 23.99998,12.00001 22.133318,10.133348 Z"></path>
         <path d="M 0,8 H 24 V 32 H 0 Z"></path>
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_types.js b/chrome/browser/resources/chromeos/login/components/oobe_types.js
index 8251835..d9fd050 100644
--- a/chrome/browser/resources/chromeos/login/components/oobe_types.js
+++ b/chrome/browser/resources/chromeos/login/components/oobe_types.js
@@ -171,6 +171,7 @@
  * @enum {string}
  */
 OobeTypes.EnrollmentStep = {
+  LOADING: 'loading',
   SIGNIN: 'signin',
   AD_JOIN: 'ad-join',
   WORKING: 'working',
diff --git a/chrome/browser/resources/chromeos/login/debug/debug.js b/chrome/browser/resources/chromeos/login/debug/debug.js
index b0d13e1..1e1f15b 100644
--- a/chrome/browser/resources/chromeos/login/debug/debug.js
+++ b/chrome/browser/resources/chromeos/login/debug/debug.js
@@ -1496,6 +1496,7 @@
             optInVisibility: true,
             optInDefaultState: true,
             legalFooterVisibility: false,
+            cloudGamingDevice: false,
           },
           trigger: (screen) => {
             screen.setUIStep('overview');
@@ -1508,6 +1509,7 @@
             optInVisibility: false,
             optInDefaultState: false,
             legalFooterVisibility: false,
+            cloudGamingDevice: false,
           },
           trigger: (screen) => {
             screen.setUIStep('overview');
@@ -1520,6 +1522,7 @@
             optInVisibility: true,
             optInDefaultState: true,
             legalFooterVisibility: true,
+            cloudGamingDevice: false,
           },
           trigger: (screen) => {
             screen.setUIStep('overview');
@@ -1532,6 +1535,7 @@
             optInVisibility: true,
             optInDefaultState: true,
             legalFooterVisibility: true,
+            cloudGamingDevice: false,
           },
           trigger: (screen) => {
             screen.setUIStep('overview');
@@ -1812,6 +1816,20 @@
       });
     }
 
+    toggleGameMode() {
+      KNOWN_SCREENS.forEach((screen, index) => {
+        if (screen.id == 'marketing-opt-in') {
+          for (const state of screen.states) {
+            if (state.data) {
+              state.data.cloudGamingDevice = !state.data.cloudGamingDevice;
+            }
+          }
+        }
+      });
+
+      this.triggerScreenState(this.currentScreenId_, this.lastScreenState_);
+    }
+
     createLanguagePanel(parent) {
       const langPanel = new ToolPanel(
           this.debuggerOverlay_, 'Language', 'DebuggerPanelLanguage');
@@ -1845,6 +1863,10 @@
       new DebugButton(panel.content, 'Toggle color mode', function() {
         chrome.send('debug.toggleColorMode');
       });
+      var button = new DebugButton(
+          panel.content, 'Toggle gaming mode', this.toggleGameMode.bind(this));
+
+      button.element.classList.add('gametoggle-button');
     }
 
     createScreensPanel(parent) {
@@ -1991,6 +2013,14 @@
         }
       }
 
+      if (this.currentScreenId_ == 'marketing-opt-in') {
+        document.getElementsByClassName('gametoggle-button')[0].removeAttribute(
+            'hidden');
+      } else {
+        document.getElementsByClassName('gametoggle-button')[0].setAttribute(
+            'hidden', true);
+      }
+
       this.statesPanel.show();
     }
 
diff --git a/chrome/browser/resources/chromeos/login/images/blazey_dark.svg b/chrome/browser/resources/chromeos/login/images/blazey_dark.svg
new file mode 100644
index 0000000..a4f8325b
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/images/blazey_dark.svg
@@ -0,0 +1 @@
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" viewBox="0 0 412 412" style="enable-background:new 0 0 412 412" xml:space="preserve"><style>.st1{fill:none;stroke:#669DF6;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st6{fill:none}.st7{fill:#FCC934}.st8{fill:none;stroke:#669DF6;stroke-width:2;stroke-miterlimit:10}.st9{fill:#D2E3FC;stroke:#4285F4;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st10{fill:none;stroke:#4285F4;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st11{fill:#FFFFFF;stroke:#4285F4;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st12{fill:#4285F4}.st13{fill:none;stroke:#2785FC;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st14{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st15{fill:#4285F4;stroke:#2785FC;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st16{fill:#4285F4;stroke:#4285F4;stroke-miterlimit:10}.st17{fill:#4285F4;stroke:#4285F4;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st18{fill-rule:evenodd;clip-rule:evenodd;fill:#E8EAED}.st19{fill-rule:evenodd;clip-rule:evenodd;fill:#EA4335}.st20{fill:none;stroke:#4285F4;stroke-width:1.2273;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st21{fill:#FBBC04}.st22{fill:#34A853}.st23{fill:#EE5FFA}.st24{fill:#FFFFFF}.st25{fill:#30E2EA}.st26{fill:none;stroke:#FFFFFF;stroke-width:1.2273;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st27{fill:#E5E5E5}.st28{clip-path:url(#SVGID_00000133491564554723634370000002966755918148432521_);fill:none}.st29{clip-path:url(#SVGID_00000133491564554723634370000002966755918148432521_);fill:#FFFFFF}.st30{fill:#CEE3FF}.st31{fill:#2785FC}.st32{clip-path:url(#SVGID_00000176727422327993439800000017387843910383703180_);fill:#FFBA00}.st33{fill:#EA4335}.st34{fill:#E8EAED}.st35{fill:none;stroke:#30E2EA;stroke-width:2;stroke-miterlimit:10}.st36{fill:none;stroke:#CEE3FF;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st37{fill:none;stroke:#2785FC;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st38{fill:#FFFFFF;stroke:#2785FC;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st39{fill:#D2E3FC}.st40{fill:none;stroke:#2785FC;stroke-width:1.2273;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st41{fill:none;stroke:#4285F4;stroke-width:0;stroke-miterlimit:10}.st42{fill:#608EF0}.st43{fill:#78B56F}.st44{fill:#EEBE59}.st45{fill:#DC6756}.st46{fill:none;stroke:#000000;stroke-miterlimit:10}.st47{fill:#FFFFFF;stroke:#000000;stroke-miterlimit:10}.st48{fill:none;stroke:#669DF6;stroke-width:3;stroke-linecap:round;stroke-miterlimit:10}.st51{fill:#669DF6}.st52{fill:#1E3A5F}.st53{fill:#5185EC}.st54{fill:none;stroke:#F6BC41;stroke-width:3;stroke-miterlimit:10}.st55{fill:#F2BE42}.st56{fill:none;stroke:#4384F4;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st57{fill:#D95140}.st58{clip-path:url(#SVGID_00000124877569633915262600000016228616283393373071_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st59{fill:#E989F7}.st60{fill:#D5E3FA}.st61{clip-path:url(#SVGID_00000052821559849791556170000017869095245677761723_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st62{clip-path:url(#SVGID_00000105423936643558746240000005216895768297366453_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st63{clip-path:url(#SVGID_00000148656175453761626640000013528327667357431969_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st64{fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st65{clip-path:url(#SVGID_00000145016022731792463730000006664994872335485627_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st66{clip-path:url(#SVGID_00000006674337015467843390000004453954338690879117_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st67{clip-path:url(#SVGID_00000151534868852971685400000015040158393129603509_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st68{clip-path:url(#SVGID_00000008865110143065187940000013261872280496950420_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st69{clip-path:url(#SVGID_00000173853507459523101430000004280240850251809178_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st70{clip-path:url(#SVGID_00000034805010896437253440000017213674346698446511_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st71{fill:#56A55C}.st72{fill:none;stroke:#5185EC;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st73{fill:none;stroke:#4384F4;stroke-width:3;stroke-miterlimit:10}.st74{clip-path:url(#SVGID_00000091000292501069936300000005885881750710103726_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-miterlimit:10}.st75{fill:none;stroke:#FFFFFF;stroke-width:3;stroke-miterlimit:10}.st76{clip-path:url(#SVGID_00000091698112136855419940000001711627631699324341_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-miterlimit:10}.st77{clip-path:url(#SVGID_00000111193025013305403660000011416064327313886873_);fill:none;stroke:#202124;stroke-width:2;stroke-miterlimit:10}.st79{clip-path:url(#SVGID_00000105405010441935847970000007889667106268327070_);fill:none;stroke:#202124;stroke-width:3;stroke-miterlimit:10}.st80{clip-path:url(#SVGID_00000008107448857502265730000017618395033669931911_);fill:none;stroke:#202124;stroke-width:2;stroke-miterlimit:10}.st81{fill:none;stroke:#5185EC;stroke-width:2;stroke-miterlimit:10}.st82{fill:none;stroke:#4285F4;stroke-width:3;stroke-linecap:round;stroke-miterlimit:10}.st83{fill:#8AB4F8}.st84{clip-path:url(#SVGID_00000171681084800801728420000001623578431063777432_);fill:none;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10}.st85{fill:none;stroke:#4285F4;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st86{fill:none;stroke:#D5E3FA;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st87{fill:#4384F4}.st88{fill:none;stroke:#7F9ACA;stroke-width:3.0418;stroke-miterlimit:10}.st89{clip-path:url(#SVGID_00000003081404327411965320000013938784376996913584_);fill:none;stroke:#202124;stroke-width:2;stroke-miterlimit:10}.st90{fill:none;stroke:#5BB974;stroke-width:3.6426;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st91{clip-path:url(#SVGID_00000147178951581951980180000004147771352251671435_);fill:none;stroke:#202124;stroke-width:3.6426;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st92{fill:none;stroke:#5184EB;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st93{fill:#FFFFFF;stroke:#5184EB;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st94{fill:#5184EB}.st95{fill:#D4E2F9}.st96{fill:#F1BD42}.st97{fill:#D4E2F9;stroke:#5184EB;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st98{fill:none;stroke:#E5E6E9;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st99{fill:none;stroke:#FFFFFF;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st100{fill:none;stroke:#D85140;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st101{fill:none;stroke:#5184EB;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:6}.st102{fill:#202124;stroke:#669DF6;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st103{clip-path:url(#SVGID_00000064327142495036121620000008870064415436873391_);fill:none;stroke:#202124;stroke-width:2;stroke-miterlimit:10}</style><path d="M326 302.8c-.5 1.2-2 1.8-3.2 1.1-10-5.5-14.4-17.8-9.9-28.6s16.4-16.3 27.3-13.1c1.3.4 2 1.8 1.5 3L326 302.8z" style="fill:none;stroke:#EA4335;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M122.7 143.1 117 136c-.3-.4-.8-.5-1.2-.5l-9 1.4c-.5.1-.9.4-1 .8l-3.3 8.5c-.2.4-.1.9.2 1.3l5.7 7.1c.3.4.8.5 1.2.5l9-1.4c.5-.1.9-.4 1-.8l3.3-8.5c.2-.4.1-.9-.2-1.3z" style="fill:#5C5D60"/><path d="m46.6 148.6 26 11c1.1.5 2.2-.4 2.1-1.6l-3.4-28c-.1-1.2-1.5-1.7-2.4-1l-22.6 17c-.9.7-.8 2.2.3 2.6z" style="fill:none;stroke:#669DF6;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="m61.7 173.8 5.1-23.4c.3-1.3 1.5-2.1 2.8-1.8l23.4 5.1c1.3.3 2.1 1.5 1.8 2.8l-5.1 23.4c-.3 1.3-1.5 2.1-2.8 1.8l-23.4-5.1c-1.3-.3-2.1-1.5-1.8-2.8z" style="fill:#F882FF"/><path class="st6" d="m47.2 147.2-.6 1.4.6-1.4 18.6 7.9 1.1-5.1c.2-1 1.2-1.7 2.3-1.5l3 .6-2.3-19-22.7 17.1z"/><path class="st6" d="m66.9 150-1.1 5.1 7.5 3.2-1.1-9.1-3-.6c-1.1-.3-2.1.4-2.3 1.4z"/><path d="M73.2 161.3c.6 0 1.3-.2 1.8-.6.9-.7 1.3-1.7 1.2-2.8l-1-8-3.1-.7 1.1 9.1-7.5-3.2-.7 3 6.9 2.9c.5.2.9.3 1.3.3z" style="fill:#202124"/><path class="st7" d="M268.6 291.1c-1-3.9 1.3-8 5.2-9l16.7-4.5c3.9-1 8 1.3 9 5.2 1 3.9-1.3 8-5.2 9l-16.7 4.5c-3.9 1-7.9-1.3-9-5.2z"/><path d="M197.9 189c-6.2 1.5-12.5-2.4-14-8.6l-6-25.2c-1.5-6.2 2.4-12.5 8.6-14 6.2-1.5 12.5 2.4 14 8.6l6 25.2c1.5 6.3-2.3 12.5-8.6 14z" style="fill:none;stroke:#669DF6;stroke-width:3;stroke-miterlimit:10"/><path d="m251.6 147.3-37.2 8.8-1.1-4.5c-.8-3.3 1.3-6.6 4.6-7.4l25.2-6c3.3-.8 6.6 1.3 7.4 4.6l1.1 4.5z" style="fill:#5BB974"/><path class="st7" d="m166.8 167.3-37.2 8.8-1.1-4.5c-.8-3.3 1.3-6.6 4.6-7.4l25.2-6c3.3-.8 6.6 1.3 7.4 4.6l1.1 4.5z"/><path d="m253.8 149-122.1 28.8v.1c-.7.1-1.4.3-2.1.4-30.7 7.3-49.7 38.3-41.9 69 7.5 29.7 37.6 48.2 67.5 41.5 15.9-3.6 28.7-13.5 36.4-26.5 3.7-6.3 9.8-10.8 16.9-12.4l5-1.2c7.1-1.7 14.5-.4 20.6 3.6 12.7 8.2 28.5 11.3 44.4 7.4 30.1-7.5 48.8-38.3 41.5-68.5-7.4-29.5-36.6-48-66.2-42.2z" style="fill:#404D64"/><path class="st51" d="m157.6 221.4-11.4 2.7c-1.2.3-2.3-.4-2.6-1.6l-2.7-11.5c-.3-1.2-1.5-1.9-2.6-1.6l-12.3 2.9c-1.2.3-1.9 1.5-1.6 2.6l2.7 11.5c.3 1.2-.4 2.3-1.6 2.6l-11.6 2.7c-1.2.3-1.9 1.5-1.6 2.6l2.9 12.3c.3 1.2 1.5 1.9 2.6 1.6l11.6-2.7c1.2-.3 2.3.4 2.6 1.6l2.7 11.5c.3 1.2 1.5 1.9 2.6 1.6l12.3-2.9c1.2-.3 1.9-1.5 1.6-2.6l-2.7-11.5c-.3-1.2.4-2.3 1.6-2.6l11.4-2.7c1.2-.3 1.9-1.5 1.6-2.6l-2.9-12.3c-.3-1.2-1.4-1.9-2.6-1.6z"/><circle class="st51" cx="254" cy="207.7" r="7.6"/><circle class="st51" cx="288" cy="199.7" r="7.6"/><circle class="st52" cx="275" cy="220.8" r="7.6"/><circle class="st52" cx="266.9" cy="186.7" r="7.6"/><defs><path id="SVGID_00000083809897178425021470000015519274425298373766_" d="m254 149.1-122 28.8v.1c-.7.1-1.4.3-2.1.4-30.7 7.3-49.7 38.3-41.9 69 7.5 29.7 37.6 48.2 67.5 41.5 15.9-3.6 28.7-13.5 36.4-26.5 3.7-6.3 9.8-10.8 16.9-12.4l5-1.2c7.1-1.7 14.5-.4 20.6 3.6 12.7 8.2 28.5 11.3 44.4 7.4 30.1-7.5 48.8-38.3 41.5-68.5-7.5-29.6-36.6-48.1-66.3-42.2z"/></defs><clipPath id="SVGID_00000108994955163549320600000014027561289717555373_"><use xlink:href="#SVGID_00000083809897178425021470000015519274425298373766_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_00000108994955163549320600000014027561289717555373_);fill:none;stroke:#202124;stroke-width:3;stroke-miterlimit:10" d="M197.9 189c-6.2 1.5-12.5-2.4-14-8.6l-5.7-24c-1.5-6.2 2.4-12.5 8.6-14 6.2-1.5 12.5 2.4 14 8.6l5.7 24c1.5 6.3-2.4 12.5-8.6 14z"/></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/images/blazey_light.svg b/chrome/browser/resources/chromeos/login/images/blazey_light.svg
new file mode 100644
index 0000000..5083e00
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/images/blazey_light.svg
@@ -0,0 +1 @@
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" viewBox="0 0 412 412" style="enable-background:new 0 0 412 412" xml:space="preserve"><style>.st0{fill:#202124}.st1{fill:none;stroke:#669DF6;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st3{fill:#5C5D60}.st4{fill:none;stroke:#669DF6;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st5{fill:#F882FF}.st7{fill:#FCC934}.st8{fill:none;stroke:#669DF6;stroke-width:2;stroke-miterlimit:10}.st9{fill:#D2E3FC;stroke:#4285F4;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st10{fill:none;stroke:#4285F4;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st11{fill:#FFFFFF;stroke:#4285F4;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st12{fill:#4285F4}.st13{fill:none;stroke:#2785FC;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st14{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st15{fill:#4285F4;stroke:#2785FC;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st16{fill:#4285F4;stroke:#4285F4;stroke-miterlimit:10}.st17{fill:#4285F4;stroke:#4285F4;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st18{fill-rule:evenodd;clip-rule:evenodd;fill:#E8EAED}.st19{fill-rule:evenodd;clip-rule:evenodd;fill:#EA4335}.st20{fill:none;stroke:#4285F4;stroke-width:1.2273;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st21{fill:#FBBC04}.st25{fill:#30E2EA}.st26{fill:none;stroke:#FFFFFF;stroke-width:1.2273;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st27{fill:#E5E5E5}.st28{clip-path:url(#SVGID_00000163075205882756248630000017012038083976820154_);fill:none}.st29{clip-path:url(#SVGID_00000163075205882756248630000017012038083976820154_);fill:#FFFFFF}.st30{fill:#CEE3FF}.st31{fill:#2785FC}.st32{clip-path:url(#SVGID_00000110465186774371835590000017340673820690895793_);fill:#FFBA00}.st33{fill:#EA4335}.st35{fill:none;stroke:#30E2EA;stroke-width:2;stroke-miterlimit:10}.st36{fill:none;stroke:#CEE3FF;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st37{fill:none;stroke:#2785FC;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st38{fill:#FFFFFF;stroke:#2785FC;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st40{fill:none;stroke:#2785FC;stroke-width:1.2273;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st41{fill:none;stroke:#4285F4;stroke-width:0;stroke-miterlimit:10}.st42{fill:#608EF0}.st43{fill:#78B56F}.st44{fill:#EEBE59}.st45{fill:#DC6756}.st46{fill:none;stroke:#000000;stroke-miterlimit:10}.st47{fill:#FFFFFF;stroke:#000000;stroke-miterlimit:10}.st48{fill:none;stroke:#669DF6;stroke-width:3;stroke-linecap:round;stroke-miterlimit:10}.st49{fill:#5BB974}.st50{fill:#404D64}.st51{fill:#669DF6}.st52{fill:#1E3A5F}.st53{fill:#5185EC}.st54{fill:none;stroke:#F6BC41;stroke-width:3;stroke-miterlimit:10}.st55{fill:#F2BE42}.st56{fill:none;stroke:#4384F4;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st57{fill:#D95140}.st58{clip-path:url(#SVGID_00000134935594067696444370000001168226520678543261_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st59{fill:#E989F7}.st60{fill:#D5E3FA}.st61{clip-path:url(#SVGID_00000027566522460972484220000016158537489704380344_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st62{clip-path:url(#SVGID_00000056402417241011302010000001280417210920492187_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st63{clip-path:url(#SVGID_00000129923525760861181590000006432960274583209119_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st64{fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st65{clip-path:url(#SVGID_00000073701531785664911930000012771081446386889132_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st66{clip-path:url(#SVGID_00000176029814269280195090000012621689906542222720_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st67{clip-path:url(#SVGID_00000010297086353311863180000017085975844895284914_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st68{clip-path:url(#SVGID_00000049216319121102628660000000342661494312323750_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st69{clip-path:url(#SVGID_00000115485472133055890970000016970615565567667885_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st70{clip-path:url(#SVGID_00000174576194331180712400000016037676759779594174_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st71{fill:#56A55C}.st72{fill:none;stroke:#5185EC;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st73{fill:none;stroke:#4384F4;stroke-width:3;stroke-miterlimit:10}.st74{clip-path:url(#SVGID_00000047773340462865362130000003671485881417554609_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-miterlimit:10}.st75{fill:none;stroke:#FFFFFF;stroke-width:3;stroke-miterlimit:10}.st76{clip-path:url(#SVGID_00000142884379414060036770000004985246898677384893_);fill:none;stroke:#FFFFFF;stroke-width:3;stroke-miterlimit:10}.st77{clip-path:url(#SVGID_00000048459519301919625980000011474711431615797660_);fill:none;stroke:#202124;stroke-width:2;stroke-miterlimit:10}.st80{fill:#8AB4F8}.st81{clip-path:url(#SVGID_00000060747388766136269120000014387247269977524106_);fill:none;stroke:#FCFCFC;stroke-width:3;stroke-miterlimit:10}.st82{fill:none;stroke:#669DF6;stroke-width:3;stroke-miterlimit:10}.st83{clip-path:url(#SVGID_00000022541611396087391170000016996430648947512732_);fill:none;stroke:#202124;stroke-width:3;stroke-miterlimit:10}.st84{clip-path:url(#SVGID_00000074407978199149437860000005521620952119901865_);fill:none;stroke:#202124;stroke-width:2;stroke-miterlimit:10}.st85{fill:none;stroke:#5185EC;stroke-width:2;stroke-miterlimit:10}.st86{fill:none;stroke:#4285F4;stroke-width:3;stroke-linecap:round;stroke-miterlimit:10}.st87{clip-path:url(#SVGID_00000100367726845058041600000000964789361760875425_);fill:none;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10}.st88{fill:none;stroke:#D5E3FA;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st89{fill:#4384F4}.st90{fill:none;stroke:#7F9ACA;stroke-width:3.0418;stroke-miterlimit:10}.st91{clip-path:url(#SVGID_00000103240832521866745410000011840992166509288880_);fill:none;stroke:#202124;stroke-width:2;stroke-miterlimit:10}.st92{fill:none;stroke:#5BB974;stroke-width:3.6426;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st93{clip-path:url(#SVGID_00000133506752722735225590000005980706198074380160_);fill:none;stroke:#202124;stroke-width:3.6426;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}.st94{fill:none;stroke:#5184EB;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st95{fill:#FFFFFF;stroke:#5184EB;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st96{fill:#5184EB}.st97{fill:#D4E2F9}.st98{fill:#F1BD42}.st99{fill:#D4E2F9;stroke:#5184EB;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st100{fill:none;stroke:#E5E6E9;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st101{fill:none;stroke:#FFFFFF;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st102{fill:none;stroke:#D85140;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st103{fill:none;stroke:#5184EB;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:6}.st104{fill:#202124;stroke:#669DF6;stroke-width:4;stroke-linecap:round;stroke-linejoin:round}.st105{clip-path:url(#SVGID_00000124130734427729222280000007357201234149350022_);fill:none;stroke:#202124;stroke-width:2;stroke-miterlimit:10}</style><path d="M326 302.8c-.5 1.2-2 1.8-3.2 1.1-10-5.5-14.4-17.8-9.9-28.6s16.4-16.3 27.3-13.1c1.3.4 2 1.8 1.5 3L326 302.8z" style="fill:none;stroke:#EA4335;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="M122.7 143.1 117 136c-.3-.4-.8-.5-1.2-.5l-9 1.4c-.5.1-.9.4-1 .8l-3.3 8.5c-.2.4-.1.9.2 1.3l5.7 7.1c.3.4.8.5 1.2.5l9-1.4c.5-.1.9-.4 1-.8l3.3-8.5c.2-.4.1-.9-.2-1.3z" style="fill:#E8EAED"/><path d="m46.6 148.6 26 11c1.1.5 2.2-.4 2.1-1.6l-3.4-28c-.1-1.2-1.5-1.7-2.4-1l-22.6 17c-.9.7-.8 2.2.3 2.6z" style="fill:none;stroke:#4285F4;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"/><path d="m61.7 173.8 5.1-23.4c.3-1.3 1.5-2.1 2.8-1.8l23.4 5.1c1.3.3 2.1 1.5 1.8 2.8l-5.1 23.4c-.3 1.3-1.5 2.1-2.8 1.8l-23.4-5.1c-1.3-.3-2.1-1.5-1.8-2.8z" style="fill:#EE5FFA"/><path d="m66.9 150-1.1 5.1 7.5 3.2-1.1-9.1-3-.6c-1.1-.3-2.1.4-2.3 1.4z" style="fill:none"/><path d="M73.2 161.3c.6 0 1.3-.2 1.8-.6.9-.7 1.3-1.7 1.2-2.8l-1-8-3.1-.7 1.1 9.1-7.5-3.2-.7 3 6.9 2.9c.5.2.9.3 1.3.3z" style="fill:#FFFFFF"/><path class="st21" d="M268.6 291.1c-1-3.9 1.3-8 5.2-9l16.7-4.5c3.9-1 8 1.3 9 5.2 1 3.9-1.3 8-5.2 9l-16.7 4.5c-3.9 1-7.9-1.3-9-5.2z"/><path d="M197.9 189c-6.2 1.5-12.5-2.4-14-8.6l-6-25.2c-1.5-6.2 2.4-12.5 8.6-14 6.2-1.5 12.5 2.4 14 8.6l6 25.2c1.5 6.3-2.3 12.5-8.6 14z" style="fill:none;stroke:#4285F4;stroke-width:3;stroke-miterlimit:10"/><path d="m251.6 147.3-37.2 8.8-1.1-4.5c-.8-3.3 1.3-6.6 4.6-7.4l25.2-6c3.3-.8 6.6 1.3 7.4 4.6l1.1 4.5z" style="fill:#34A853"/><path class="st21" d="m166.8 167.3-37.2 8.8-1.1-4.5c-.8-3.3 1.3-6.6 4.6-7.4l25.2-6c3.3-.8 6.6 1.3 7.4 4.6l1.1 4.5z"/><path d="m253.8 149-122.1 28.8v.1c-.7.1-1.4.3-2.1.4-30.7 7.3-49.7 38.3-41.9 69 7.5 29.7 37.6 48.2 67.5 41.5 15.9-3.6 28.7-13.5 36.4-26.5 3.7-6.3 9.8-10.8 16.9-12.4l5-1.2c7.1-1.7 14.5-.4 20.6 3.6 12.7 8.2 28.5 11.3 44.4 7.4 30.1-7.5 48.8-38.3 41.5-68.5-7.4-29.5-36.6-48-66.2-42.2z" style="fill:#D2E3FC"/><path class="st12" d="m157.6 221.4-11.4 2.7c-1.2.3-2.3-.4-2.6-1.6l-2.7-11.5c-.3-1.2-1.5-1.9-2.6-1.6l-12.3 2.9c-1.2.3-1.9 1.5-1.6 2.6l2.7 11.5c.3 1.2-.4 2.3-1.6 2.6l-11.6 2.7c-1.2.3-1.9 1.5-1.6 2.6l2.9 12.3c.3 1.2 1.5 1.9 2.6 1.6l11.6-2.7c1.2-.3 2.3.4 2.6 1.6l2.7 11.5c.3 1.2 1.5 1.9 2.6 1.6l12.3-2.9c1.2-.3 1.9-1.5 1.6-2.6l-2.7-11.5c-.3-1.2.4-2.3 1.6-2.6l11.4-2.7c1.2-.3 1.9-1.5 1.6-2.6l-2.9-12.3c-.3-1.2-1.4-1.9-2.6-1.6z"/><circle class="st12" cx="254" cy="207.7" r="7.6"/><circle class="st12" cx="288" cy="199.7" r="7.6"/><circle class="st80" cx="275" cy="220.8" r="7.6"/><circle class="st80" cx="266.9" cy="186.7" r="7.6"/><defs><path id="SVGID_00000157274559590167270570000011537451651073975445_" d="m254 149.1-122 28.8v.1c-.7.1-1.4.3-2.1.4-30.7 7.3-49.7 38.3-41.9 69 7.5 29.7 37.6 48.2 67.5 41.5 15.9-3.6 28.7-13.5 36.4-26.5 3.7-6.3 9.8-10.8 16.9-12.4l5-1.2c7.1-1.7 14.5-.4 20.6 3.6 12.7 8.2 28.5 11.3 44.4 7.4 30.1-7.5 48.8-38.3 41.5-68.5-7.5-29.6-36.6-48.1-66.3-42.2z"/></defs><clipPath id="SVGID_00000096780124617305643720000014631975753030279081_"><use xlink:href="#SVGID_00000157274559590167270570000011537451651073975445_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_00000096780124617305643720000014631975753030279081_);fill:none;stroke:#FCFCFC;stroke-width:3;stroke-miterlimit:10" d="M197.9 189c-6.2 1.5-12.5-2.4-14-8.6l-5.7-24c-1.5-6.2 2.4-12.5 8.6-14 6.2-1.5 12.5 2.4 14 8.6l5.7 24c1.5 6.3-2.4 12.5-8.6 14z"/></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/screens/common/error_message.js b/chrome/browser/resources/chromeos/login/screens/common/error_message.js
index 81de920..0c5be7b 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/error_message.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/error_message.js
@@ -259,7 +259,7 @@
   }
 
   continueButtonClicked() {
-    chrome.send('continueAppLaunch');
+    this.userActed('continue-app-launch');
   }
 
   okButtonClicked() {
@@ -336,7 +336,7 @@
         'auto-enrollment-learn-more');
     this.shadowRoot.querySelector('#auto-enrollment-learn-more').onclick =
         () => {
-          chrome.send('launchHelpApp', [HELP_TOPIC_AUTO_ENROLLMENT]);
+          this.userActed(['launch-help-app', HELP_TOPIC_AUTO_ENROLLMENT]);
         };
 
     this.updateElementWithStringAndAnchorTag_(
diff --git a/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.html b/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.html
index 1d23fd3c..06e02867 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.html
+++ b/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.html
@@ -53,8 +53,7 @@
       }
     </style>
     <gaia-dialog id="signin-frame-dialog"
-        transparent$="[[isLoadingUiShown_]]" class="flex"
-        for-step="online-gaia, gaia-loading"
+        for-step="online-gaia"
         is-saml-sso-visible="[[isSamlSsoVisible_]]"
         is-default-sso-provider="[[isDefaultSsoProvider_]]"
         is-closable="[[isClosable_]]"
@@ -119,10 +118,10 @@
         </div>
       </oobe-adaptive-dialog>
     </div>
-    <div id="gaia-loading" class="layout center center-justified vertical fit"
-        for-step="loading, gaia-loading">
-      <throbber-notice text-key="gaiaLoading"></throbber-notice>
-    </div>
+    <oobe-loading-dialog title-key="gaiaLoading"
+        id="step-loading" for-step="loading">
+      <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon>
+    </oobe-loading-dialog>
     <notification-card id="gaia-allowlist-error" class="fit"
         for-step="allowlist-error"
         on-buttonclick="onAllowlistErrorTryAgainClick_"
diff --git a/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.js b/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.js
index e61f09ea..fd2eaa0 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/gaia_signin.js
@@ -39,7 +39,6 @@
  */
 const DialogMode = {
   GAIA: 'online-gaia',
-  GAIA_LOADING: 'gaia-loading',
   LOADING: 'loading',
   PIN_DIALOG: 'pin',
   GAIA_ALLOWLIST_ERROR: 'allowlist-error',
@@ -50,7 +49,7 @@
  * Steps that could be the first one in the flow.
  */
 const POSSIBLE_FIRST_SIGNIN_STEPS =
-    [DialogMode.GAIA, DialogMode.GAIA_LOADING, DialogMode.SAML_INTERSTITIAL];
+    [DialogMode.GAIA, DialogMode.LOADING, DialogMode.SAML_INTERSTITIAL];
 
 /**
  * @constructor
@@ -579,6 +578,7 @@
    */
   onBeforeHide() {
     this.isShown_ = false;
+    this.authenticator_.resetWebview();
   }
 
   /**
@@ -1090,11 +1090,7 @@
       return;
     }
     if (isLoading) {
-      if (mode == ScreenAuthMode.DEFAULT) {
-        this.setUIStep(DialogMode.GAIA_LOADING);
-      } else {
-        this.setUIStep(DialogMode.LOADING);
-      }
+      this.setUIStep(DialogMode.LOADING);
       return;
     }
     if (isAllowlistError) {
diff --git a/chrome/browser/resources/chromeos/login/screens/common/marketing_opt_in.html b/chrome/browser/resources/chromeos/login/screens/common/marketing_opt_in.html
index 687b45c8..5609643 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/marketing_opt_in.html
+++ b/chrome/browser/resources/chromeos/login/screens/common/marketing_opt_in.html
@@ -29,15 +29,16 @@
       #legalFooter {
         margin-top: 20px;
       }
+
       :host-context([orientation=vertical ]) #contentArea {
         justify-content: center;
       }
 
       :host {
         --marketing-opt-in-dialog-list-item-border:
-          1px solid var(--cros-color-primary);
+          1px solid var(--cros-separator-color);
         --oobe-a11y-dialog-list-item-border:
-          1px solid var(--cros-color-primary);
+          1px solid var(--cros-separator-color);
         --marketing-opt-in-row-height: 50px;
         --marketing-opt-in-line-height: 20px;
       }
@@ -54,6 +55,10 @@
         color: var(--cros-text-color-secondary);
       }
 
+      .toggle-title {
+        color: var(--cros-text-color-primary);
+      }
+
       #toggleRow {
         border-bottom: var(--marketing-opt-in-dialog-list-item-border);
         border-top: var(--marketing-opt-in-dialog-list-item-border);
@@ -99,6 +104,7 @@
         color: var(--cros-text-color-primary);
       }
 
+      #marketingOptInGameDeviceSubtitle,
       #marketingOptInSubtitleWithDeviceName,
       #marketingOptInSubtitle,
       #chromebookUpdatesOptionLabel {
@@ -110,32 +116,55 @@
         for-step="overview"
         aria-label$="[[i18nDynamic(locale, 'marketingOptInScreenTitle')]]"
         aria-describedby="marketing-opt-in-subtitle">
-      <iron-icon slot="icon" icon="oobe-32:checkmark">
+      <iron-icon slot="icon"
+          icon="[[getIcon_(isDarkModeActive_, isCloudGamingDevice_)]]">
       </iron-icon>
-      <h1 slot="title">
+
+      <h1 hidden="[[isCloudGamingDevice_]]" slot="title">
         [[i18nDynamic(locale, 'marketingOptInScreenTitle')]]
       </h1>
+      <h1 id ="marketingOptInGameDeviceTitle"
+          hidden="[[!isCloudGamingDevice_]]" slot="title">
+        [[i18nDynamic(locale, 'marketingOptInScreenGameDeviceTitle')]]
+      </h1>
+      <h1 hidden="[[!isCloudGamingDevice_]]" slot="title">
+        [[i18nDynamic(locale, 'marketingOptInScreenGameDeviceTitle2')]]
+      </h1>
       <div slot="subtitle">
         <!-- No marketing opt in -->
-        <div hidden="[[marketingOptInVisible_]]"
-          id="marketingOptInSubtitleWithDeviceName">
-          [[i18nDynamic(locale, 'marketingOptInScreenSubtitleWithDeviceName')]]
+        <div hidden="[[isCloudGamingDevice_]]">
+          <div hidden="[[marketingOptInVisible_]]"
+            id="marketingOptInSubtitleWithDeviceName">
+            [[i18nDynamic(locale,
+                  'marketingOptInScreenSubtitleWithDeviceName')]]
+          </div>
+          <!-- Marketing opt in -->
+          <div hidden="[[!marketingOptInVisible_]]" id="marketingOptInSubtitle">
+            [[i18nDynamic(locale,
+                    'marketingOptInScreenSubtitle')]]
+          </div>
         </div>
-        <!-- Marketing opt in -->
-        <div hidden="[[!marketingOptInVisible_]]" id="marketingOptInSubtitle">
-          [[i18nDynamic(locale, 'marketingOptInScreenSubtitle')]]
+        <div hidden="[[!isCloudGamingDevice_]]"
+             id="marketingOptInGameDeviceSubtitle">
+          [[i18nDynamic(locale,
+                  'marketingOptInScreenGameDeviceSubtitle')]]
         </div>
-
         <!-- Toggle row -->
         <div class="layout horizontal center"
             hidden="[[!marketingOptInVisible_]]"
-            id="toggleRow">
+            id="toggleRow" style="[[getMarginTop_(isCloudGamingDevice_)]]">
           <iron-icon id="toggleRowIcon" icon="oobe-32:chromebook"></iron-icon>
           <div id="chromebookUpdatesOptionLabel" class="flex layout vertical"
               aria-hidden="true">
-            <div>
+            <div class="toggle-title" hidden="[[!isCloudGamingDevice_]]">
               [[i18nDynamic(locale, 'marketingOptInGetChromebookUpdates')]]
             </div>
+            <div class="toggle-title" hidden="[[!isCloudGamingDevice_]]">
+              [[i18nDynamic(locale, 'marketingOptInGameDeviceUpdates')]]
+            </div>
+            <div class="legal-info" hidden="[[!isCloudGamingDevice_]]">
+              [[i18nDynamic(locale, 'marketingOptInScreenSubtitle')]]
+            </div>
             <div class="legal-info">
               [[i18nDynamic(locale, 'marketingOptInScreenUnsubscribeLong')]]
             </div>
@@ -154,9 +183,10 @@
         </div>
       </div>
 
-      <div id="contentArea" slot="content" class="layout flex vertical">
+      <div hidden="[[isCloudGamingDevice_]]" id="contentArea"
+           slot="content" class="layout flex vertical">
         <!-- Animation -->
-        <div class="marketing-animation-content">
+        <div  class="marketing-animation-content">
           <iron-media-query query="(prefers-color-scheme: dark)"
               query-matches="{{isDarkModeActive_}}">
           </iron-media-query>
@@ -166,6 +196,11 @@
           </oobe-cr-lottie>
         </div>
       </div>
+      <div hidden="[[!isCloudGamingDevice_]]" slot="content"
+           class="flex layout vertical center-justified center">
+        <img class="oobe-illustration"
+            srcset="[[getImageSource_(isDarkModeActive_)]]" aria-hidden="true">
+      </div>
       <oobe-icon-button slot="bottom-buttons"
           hidden="[[!isA11ySettingsButtonVisible_]]"
           id="marketing-opt-in-accessibility-button"
diff --git a/chrome/browser/resources/chromeos/login/screens/common/marketing_opt_in.js b/chrome/browser/resources/chromeos/login/screens/common/marketing_opt_in.js
index b355efef..22837ab 100644
--- a/chrome/browser/resources/chromeos/login/screens/common/marketing_opt_in.js
+++ b/chrome/browser/resources/chromeos/login/screens/common/marketing_opt_in.js
@@ -99,6 +99,15 @@
         type: Boolean,
         value: false,
       },
+
+      /**
+       * Whether the device is cloud gaming device, which will
+       * alternate different title, subtitle and animation.
+       */
+      isCloudGamingDevice_: {
+        type: Boolean,
+        value: false,
+      },
     };
   }
 
@@ -141,6 +150,8 @@
         'optInDefaultState' in data && data.optInDefaultState;
     this.hasLegalFooter_ =
         'legalFooterVisibility' in data && data.legalFooterVisibility;
+    this.isCloudGamingDevice_ =
+        'cloudGamingDevice' in data && data.cloudGamingDevice;
     this.setAnimationPlay_(true);
     this.$.marketingOptInOverviewDialog.show();
   }
@@ -202,6 +213,45 @@
   }
 
   /**
+   * Returns the src of the icon.
+   * @private
+   */
+  getIcon_() {
+    if (this.isDarkModeActive_ && this.isCloudGamingDevice_) {
+      return 'oobe-32:game-controller-dark';
+    }
+    if (!this.isDarkModeActive_ && this.isCloudGamingDevice_) {
+      return 'oobe-32:game-controller-light';
+    }
+    if (!this.isDarkModeActive_ && !this.isCloudGamingDevice_) {
+      return 'oobe-32:checkmark-light';
+    }
+    if (this.isDarkModeActive_ && !this.isCloudGamingDevice_) {
+      return 'oobe-32:checkmark-dark';
+    }
+  }
+
+  /**
+   * Returns the src of the illustration.
+   * @private
+   */
+  getImageSource_() {
+    return this.isDarkModeActive_ ? 'images/blazey_dark.svg' :
+                                    'images/blazey_light.svg';
+  }
+
+  /**
+   * Returns the src of the margin for the toggle.
+   * @private
+   */
+  getMarginTop_() {
+    return this.isCloudGamingDevice_ ? 'margin-top: 65px;' :
+                                       'margin-top: 20px;';
+  }
+
+
+
+  /**
    * Returns the url of the animation asset.
    * @private
    */
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/enterprise_enrollment.html b/chrome/browser/resources/chromeos/login/screens/oobe/enterprise_enrollment.html
index 0a03f0c..5af7cfd 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/enterprise_enrollment.html
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/enterprise_enrollment.html
@@ -80,6 +80,10 @@
         on-ready="onReady"
         on-licensetypeselected="onLicenseTypeSelected">
     </gaia-dialog>
+    <oobe-loading-dialog title-key="gaiaLoading"
+        id="step-loading" for-step="loading">
+      <iron-icon slot="icon" icon="oobe-32:enterprise"></iron-icon>
+    </oobe-loading-dialog>
 
     <!-- ENROLLMENT IN PROGRESS (SPINNER) DIALOG -->
     <oobe-loading-dialog title-key="[[getWorkingTitleKey_(licenseType_)]]"
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/enterprise_enrollment.js b/chrome/browser/resources/chromeos/login/screens/oobe/enterprise_enrollment.js
index 7f5ceae5..12d87a1 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/enterprise_enrollment.js
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/enterprise_enrollment.js
@@ -177,7 +177,7 @@
   }
 
   defaultUIStep() {
-    return OobeTypes.EnrollmentStep.SIGNIN;
+    return OobeTypes.EnrollmentStep.LOADING;
   }
 
   get UI_STEPS() {
@@ -299,7 +299,7 @@
     cr.ui.login.invokePolymerMethod(this.$['step-ad-join'], 'onBeforeShow');
     this.showStep(
         this.isAutoEnroll_ ? OobeTypes.EnrollmentStep.WORKING :
-                             OobeTypes.EnrollmentStep.SIGNIN);
+                             OobeTypes.EnrollmentStep.LOADING);
   }
 
   /**
@@ -373,7 +373,8 @@
         step === OobeTypes.EnrollmentStep.AD_JOIN ||
         step === OobeTypes.EnrollmentStep.WORKING ||
         step === OobeTypes.EnrollmentStep.CHECKING ||
-        step == OobeTypes.EnrollmentStep.TPM_CHECKING;
+        step === OobeTypes.EnrollmentStep.TPM_CHECKING ||
+        step === OobeTypes.EnrollmentStep.LOADING;
     if (this.isCancelDisabled) {
       Oobe.getInstance().setOobeUIState(OOBE_UI_STATE.ENROLLMENT);
     } else {
@@ -496,6 +497,9 @@
   }
 
   onReady() {
+    if (this.uiStep == OobeTypes.EnrollmentStep.LOADING) {
+      this.showStep(OobeTypes.EnrollmentStep.SIGNIN);
+    }
     if (this.uiStep != OobeTypes.EnrollmentStep.SIGNIN) {
       return;
     }
diff --git a/chrome/browser/resources/chromeos/notification_tester/BUILD.gn b/chrome/browser/resources/chromeos/notification_tester/BUILD.gn
index 1c26ded..61ec361 100644
--- a/chrome/browser/resources/chromeos/notification_tester/BUILD.gn
+++ b/chrome/browser/resources/chromeos/notification_tester/BUILD.gn
@@ -13,7 +13,11 @@
 generate_grd("build_grd") {
   grd_prefix = "notification_tester"
   out_grd = resources_grd_file
-  input_files = [ "index.html" ]
+  input_files = [
+    "index.html",
+    "form_constants.js",
+    "types.js",
+  ]
   input_files_base_dir = rebase_path(".", "//")
 
   grdp_files = [ generated_grdp_file ]
@@ -25,7 +29,10 @@
   grd_prefix = "notification_tester"
   out_grd = generated_grdp_file
   input_files_base_dir = rebase_path(target_gen_dir, root_build_dir)
-  input_files = [ "notification_tester.js" ]
+  input_files = [
+    "notification_tester.js",
+    "select_custom.js",
+  ]
 }
 
 grit("resources") {
@@ -46,16 +53,38 @@
 
 js_type_check("closure_compile") {
   is_polymer3 = true
-  deps = [ ":notification_tester" ]
+  deps = [
+    ":form_constants",
+    ":notification_tester",
+    ":select_custom",
+    ":types",
+  ]
 }
 
 js_library("notification_tester") {
   deps = [
+    ":form_constants",
+    ":types",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js:cr.m",
   ]
 }
 
+js_library("select_custom") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
+js_library("types") {
+}
+
+js_library("form_constants") {
+}
+
 html_to_js("web_components") {
-  js_files = [ "notification_tester.js" ]
+  js_files = [
+    "notification_tester.js",
+    "select_custom.js",
+  ]
 }
diff --git a/chrome/browser/resources/chromeos/notification_tester/form_constants.js b/chrome/browser/resources/chromeos/notification_tester/form_constants.js
new file mode 100644
index 0000000..381eb633
--- /dev/null
+++ b/chrome/browser/resources/chromeos/notification_tester/form_constants.js
@@ -0,0 +1,80 @@
+// 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.
+
+/*
+ * @fileoverview Stores the content of the notification tester form select
+ * elements.
+ * @externs
+ */
+
+/*
+ * Stores the content of the notification tester form select
+ * elements. Options correspond to the naming scheme defined in
+ * ui/message_center/public/cpp/notification.h.
+ * @enum {Array}
+ */
+export const FormSelectOptions = {
+  TITLE_OPTIONS: [
+    {displayText: 'Short Sentence (LTR)', value: 'Notification Title'},
+    {displayText: 'Short Sentence (RTL)', value: 'כותרת הודעה'}, {
+      displayText: 'Long Sentence (LTR)',
+      value:
+          'Hamburgers: the cornerstone of any nutritious breakfast. Ch-cheeseburgers'
+    },
+    {
+      displayText: 'Long Sentence (RTL)',
+      value: 'המבורגרים: אבן הפינה של כל ארוחת בוקר מזינה. ציזבורגר'
+    },
+    {
+      displayText: 'Repetitive Characters (LTR)',
+      value: 'sshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh'
+    },
+    {
+      displayText: 'Repetitive Characters (RTL)',
+      value: 'שששששששששששששששששששששששששששששששששששששששששששששששששששש'
+    }
+  ],
+  MESSAGE_OPTIONS: [
+    {displayText: 'One Sentence (LTR)', value: 'Notification content'},
+    {displayText: 'One Sentence (RTL)', value: 'תוכן הודעה'},
+    {
+      displayText: 'Multiple Sentences (LTR)',
+      value:
+          'This is the notification\'s message.It may be able to stretch over multiple lines, or become visible when the notification is expanded by the user, depending on the notification center that\'s being used.'
+    },
+    {
+      displayText: 'Multiple Sentences (RTL)',
+      value:
+          'זהו המסר של ההודעה. זה עשוי להיות מסוגל למתוח על קווים מרובים, או להיות גלוי, כאשר ההודעה מורחבת על ידי המשתמש, בהתאם להודעה שהמרכז נמצא בשימוש'
+    },
+    {
+      displayText: 'Repetitive Characters (LTR)',
+      value:
+          'sshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh'
+    },
+    {
+      displayText: 'Repetitive Characters (RTL)',
+      value:
+          'ששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששש'
+    },
+    {displayText: 'Unicode Emojis', value: '🌇😃🍈😆🍜🍻😋⛅⛳😚ඞ'},
+    {displayText: 'Empty', value: ''},
+  ],
+  BADGE_OPTIONS: [
+    {displayText: 'Cat Badge', value: 'cat'},
+    {displayText: 'No Badge', value: 'none'}
+  ],
+  IMAGE_OPTIONS: [
+    {displayText: 'No Image', value: 'none'},
+    {displayText: 'Cat Image (JPEG, 3072x1728)', value: 'cat'},
+  ],
+  ICON_OPTIONS: [
+    {displayText: 'No Icon', value: 'none'},
+    {displayText: 'Normal PNG Icon (256x256)', value: 'normal_png'},
+    {displayText: 'Static GIF Icon (256x256)', value: 'static_gif'},
+    {displayText: 'Animated GIF Icon (256x256)', value: 'animated_gif'},
+    {displayText: 'Tiny Icon (PNG, 32x32)', value: 'tiny_icon'},
+    {displayText: 'Huge Icon (PNG, 3333x5230)', value: 'huge_icon'},
+  ],
+};
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/notification_tester/notification_tester.html b/chrome/browser/resources/chromeos/notification_tester/notification_tester.html
index bf0950eb..45e0307 100644
--- a/chrome/browser/resources/chromeos/notification_tester/notification_tester.html
+++ b/chrome/browser/resources/chromeos/notification_tester/notification_tester.html
@@ -14,88 +14,87 @@
     text-align: center;
   }
 
-  .input-field {
-    margin: 2.5% 5%;
+  *,
+  *::before,
+  *::after {
+    box-sizing: border-box;
+    font-family: inherit;
   }
 
-  .input-field ol {
-    margin: 0 0 8px 0;
-    padding: 0 16px;
+  .page-container {
+    align-items: flex-start;
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    line-height: 1.5;
   }
 
-  .input-field ol>li {
+  .config-form {
+    flex: 1;
+    margin: 0 auto;
+    max-width: 24rem;
+    width: 100%;
+  }
+
+  .form-item {
     align-items: center;
     border-bottom: none;
     display: flex;
+    font-size: 1rem;
     padding: 0 0 8px 0;
   }
 
-  .label {
-    margin: 2px;
+  .form-item>label {
+    flex: 1;
+    font-size: 1;
+  }
+
+  .form-item>select {
+    background: inherit;
+    border: 2px solid #666;
+    border-radius: .25rem;
+    flex: 2;
+    padding: .1rem;
+  }
+
+  #generateNotifBtn {
+    background: rgb(0, 134, 179);
+    border-radius: 0.25rem;
+    color: #f8f8f8;
+    font-size: 1rem;
+    font-weight: bold;
+    margin-top: 1em;
+    padding: 0.25em 0.5em;
+    width: max-content;
   }
 </style>
 <app-header>
   <app-toolbar>Notification Tester</app-toolbar>
 </app-header>
-<div class="input-field">
-  <ol>
-    <h2> Visual Configuration </h2>
-    <li>
-      <label> Title
-        <select id="title">
-          <option data-id="0" value="Sample Notification Title">Short sentence
-            (LTR)</option>
-          <option data-id="1" value="כותרת הודעה">Short sentence (RTL)</option>
-          <option data-id="2"
-            value="This is a very long notification title which is unncessarily long in order to increase it">
-            Long sentence (LTR) </option>
-          <option data-id="3"
-            value="המבורגרים: אבן הפינה של כל ארוחת בוקר מזינה. צ'יזבורגר">
-            Long sentence (RTL)
-          </option>
-          <option data-id="4"
-            value="sshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh">
-            Repetitive characters (LTR)
-          </option>
-          <option data-id="5"
-            value="שששששששששששששששששששששששששששששששששששששששששששששששששששש">
-            Repetitive characters (RTL)
-          </option>
-          <option data-id="6" value="😁🚒❤😹🙋⌛❇🚅☎☺">Unicode smileys</option>
-          <option data-id="7" value="">Empty</option>
-          <option data-custom value="custom">Custom</option>
-        </select>
-      </label>
-    </li>
-    <li>
-      <label> Body
-        <select id="body">
-          <option data-id="0" value="Notification content">One sentence (LTR)
-          </option>
-          <option data-id="1" value="תוכן הודעה">One sentence (RTL)</option>
-          <option data-id="2"
-            value="This is the notification's message. It may be able to stretch over multiple lines, or become visible when the notification is expanded by the user, depending on the notification center that's being used.">
-            Multiple sentences (LTR)</option>
-          <option data-id="3"
-            value="זהו המסר של ההודעה. זה עשוי להיות מסוגל למתוח על קווים מרובים, או להיות גלוי, כאשר ההודעה מורחבת על ידי המשתמש, בהתאם להודעה שהמרכז נמצא בשימוש">
-            Multiple sentences (RTL)</option>
-          <option data-id="4"
-            value="sshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh">
-            Repetitive characters (LTR)</option>
-          <option data-id="5"
-            value="ששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששש">
-            Repetitive characters (RTL)</option>
-          <option data-id="6" value="🌇😃🍈😆🍜🍻😋⛅⛳😚">Unicode smileys
-          </option>
-          <option data-id="7" value="">Empty</option>
-          <option data-custom value="custom">Custom</option>
-        </select>
-      </label>
-    </li>
-    <li>
-      <button type="button" id="generateBtn" on-click="onClickGenerate_">
-        Generate </button>
-      <button type="button" id="resetBtn"> Reset </button>
-    </li>
-  </ol>
+<div class="page-container">
+  <div class="config-form">
+    <h2> Visual Settings </h2>
+
+    <select-custom select-value="{{notifMetadata.title}}" display-label="Title"
+      select-elements="[[titleSelectList]]" selectid="title"></select-custom>
+
+    <select-custom select-value="{{notifMetadata.message}}"
+      display-label="Message" select-elements="[[messageSelectList]]"
+      selectid="message"></select-custom>
+
+    <select-custom select-value="{{notifMetadata.badge}}" display-label="Badge"
+      select-elements="[[badgeSelectList]]" selectid="badge""
+      no-custom-input=" true"></select-custom>
+
+    <select-custom select-value="{{notifMetadata.richDataSmallImage}}"
+      display-label="Icon" select-elements="[[iconSelectList]]" selectid="icon"
+      no-custom-input="true"></select-custom>
+
+    <select-custom select-value="{{notifMetadata.richDataImage}}"
+      display-label="Image" select-elements="[[imageSelectList]]"
+      selectid="image" no-custom-input="true"></select-custom>
+
+    <button type="button" id="generateNotifBtn" on-click="onClickGenerate">
+      Generate </button>
+  </div>
 </div>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/notification_tester/notification_tester.js b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js
index 3590c1b..1ddacea7 100644
--- a/chrome/browser/resources/chromeos/notification_tester/notification_tester.js
+++ b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js
@@ -2,8 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import './select_custom.js';
+
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {FormSelectOptions} from './form_constants.js';
+import {Notification} from './types.js';
+
+// Web component housing the form for chrome://notification-tester.
 export class NotificationTester extends PolymerElement {
   static get is() {
     return 'notification-tester';
@@ -14,18 +20,57 @@
   }
 
   static get properties() {
-    return {};
+    return {
+      /*
+       @type {!Notification}
+       */
+      notifMetadata: {
+        type: Object,
+        value: function() {
+          return {};
+        },
+      },
+      /*
+       * @private
+       */
+      titleSelectList: {
+        type: Array,
+        value: FormSelectOptions.TITLE_OPTIONS,
+      },
+      /*
+       * @private
+       */
+      messageSelectList: {
+        type: Array,
+        value: FormSelectOptions.MESSAGE_OPTIONS,
+      },
+      /*
+       * @private
+       */
+      badgeSelectList: {
+        type: Array,
+        value: FormSelectOptions.BADGE_OPTIONS,
+      },
+      /*
+       * @private
+       */
+      imageSelectList: {
+        type: Array,
+        value: FormSelectOptions.IMAGE_OPTIONS,
+      },
+      /*
+       * @private
+       */
+      iconSelectList: {
+        type: Array,
+        value: FormSelectOptions.ICON_OPTIONS,
+      },
+    };
   }
 
-  onClickGenerate_() {
-    // Extract arguments from user selections.
-    const notifTitleElem = this.$.title;
-    const notifBodyElem = this.$.body;
-    const notifTitleValue =
-        notifTitleElem.options[notifTitleElem.selectedIndex].value;
-    const notifBodyValue =
-        notifBodyElem.options[notifBodyElem.selectedIndex].value;
-    chrome.send('generateNotificationForm', [notifTitleValue, notifBodyValue]);
+  onClickGenerate() {
+    // Send notification data to C++
+    chrome.send('generateNotificationForm', [this.notifMetadata]);
   }
 }
 
diff --git a/chrome/browser/resources/chromeos/notification_tester/select_custom.html b/chrome/browser/resources/chromeos/notification_tester/select_custom.html
new file mode 100644
index 0000000..3baf131
--- /dev/null
+++ b/chrome/browser/resources/chromeos/notification_tester/select_custom.html
@@ -0,0 +1,57 @@
+<style>
+  .form-item,
+  .form-item-custom {
+    align-items: center;
+    border-bottom: none;
+    display: flex;
+    font-size: 1rem;
+    padding: 0 0 8px 0;
+  }
+
+  .form-item>label {
+    flex: 1;
+    font-size: 1;
+  }
+
+  .form-item>select {
+    background: inherit;
+    border: 2px solid #666;
+    border-radius: .25rem;
+    flex: 2;
+    padding: .1rem;
+  }
+
+  .form-item-custom>label {
+    flex: 3;
+    font-size: 1;
+  }
+
+  .form-item-custom>select {
+    background: inherit;
+    border: 2px solid #666;
+    border-radius: .25rem;
+    flex: 2;
+    min-width: 0;
+    padding: .1rem;
+  }
+
+  .form-item-custom>input {
+    background: inherit;
+    border: 2px solid #666;
+    border-radius: .25rem;
+    flex: 4;
+    padding: .1rem;
+  }
+</style>
+<div class$="[[formItemStyle]]">
+  <label for="[[selectid]]">[[displayLabel]]</label>
+  <select id="[[selectid]]" on-change="onSelectChange">
+    <template is="dom-repeat" items="[[selectElements]]">
+      <option value="[[item.value]]"> [[item.displayText]] </option>
+    </template>
+    <template is="dom-if" if="[[!noCustomInput]]">
+      <option value="custom">Custom</option>
+    </template>
+  </select>
+  <input class="hidden-input" type="text" on-change="onInputChange">
+</div>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/notification_tester/select_custom.js b/chrome/browser/resources/chromeos/notification_tester/select_custom.js
new file mode 100644
index 0000000..90e642fc
--- /dev/null
+++ b/chrome/browser/resources/chromeos/notification_tester/select_custom.js
@@ -0,0 +1,77 @@
+// 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.
+
+import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+// A <select> element that shows a text input when the "custom" field is
+// selected.
+export class SelectCustom extends PolymerElement {
+  ready() {
+    super.ready();
+    // Hide custom input.
+    this.shadowRoot.querySelector('.hidden-input').hidden = true;
+
+    // Set default value of select to the first option.
+    this.shadowRoot.querySelector('#' + this.selectid).selectedIndex = 1;
+  }
+
+  static get is() {
+    return 'select-custom';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+      selectElements: {type: Array},
+      selectValue:
+          {type: String, notify: true, computed: 'getSelectValue(selectIndex)'},
+      selectIndex: {type: Number, value: 0},
+      formItemStyle: {type: String, value: 'form-item'},
+      displayLabel: {type: String},
+      selectid: {type: String},
+      noCustomInput: {type: Boolean, value: false},
+      customSelected:
+          {type: Boolean, value: false, notify: true, reflectToAttribute: true},
+    };
+  }
+
+  // Shows a hidden input element when the "custom" option is chosen from the
+  // select. The function is triggered by the on-change event for the
+  // <select> element.
+  onSelectChange(event) {
+    const customInput = this.shadowRoot.querySelector('.hidden-input');
+    if (event.target.value == 'custom' && !this.noCustomInput) {
+      this.customSelected = true;
+      this.formItemStyle = 'form-item-custom';
+      customInput.hidden = false;
+    } else {
+      this.customSelected = false;
+      this.formItemStyle = 'form-item';
+      customInput.hidden = true;
+      const select = this.shadowRoot.querySelector('#' + this.selectid);
+      this.selectIndex = select.selectedIndex;
+    }
+  }
+
+  // Computed property callback. Returns the value of an element in
+  // selectElements using its index.
+  getSelectValue(selectIndex) {
+    return this.selectElements[selectIndex].value;
+  }
+
+  // When the custom input field changes (on-change event), store the value in a
+  // property.
+  onInputChange() {
+    if (this.customSelected) {
+      const customInput = this.shadowRoot.querySelector('.hidden-input');
+      this.selectValue = customInput.value;
+    }
+  }
+}
+customElements.define(SelectCustom.is, SelectCustom);
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/notification_tester/types.js b/chrome/browser/resources/chromeos/notification_tester/types.js
new file mode 100644
index 0000000..cf8f7ef7
--- /dev/null
+++ b/chrome/browser/resources/chromeos/notification_tester/types.js
@@ -0,0 +1,17 @@
+// 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.
+
+/**
+ * Will eventually match Notification from
+ * ui/message_center/public/cpp/notification.h.
+ * Items prefixed with "richData" are from RichNotificationData.
+ * @typedef {{
+ *   title: string,
+ *   message: string,
+ *   icon: string,
+ *   richDataImage: string,
+ *   richDataSmallImage: string,
+ * }}
+ */
+export let Notification;
\ No newline at end of file
diff --git a/chrome/browser/resources/new_tab_page/BUILD.gn b/chrome/browser/resources/new_tab_page/BUILD.gn
index 6fb97f01..0c181fc0 100644
--- a/chrome/browser/resources/new_tab_page/BUILD.gn
+++ b/chrome/browser/resources/new_tab_page/BUILD.gn
@@ -29,7 +29,7 @@
   in_folder = "."
   out_folder = "$target_gen_dir/$preprocess_folder"
   in_files = ts_files
-  enable_removal_comments = true
+  enable_removal_comments = enable_webui_inline_sourcemaps
 }
 
 preprocess_if_expr("preprocess_gen") {
@@ -38,7 +38,7 @@
   in_folder = target_gen_dir
   out_folder = "$target_gen_dir/$preprocess_folder"
   in_files = html_wrapper_files
-  enable_removal_comments = true
+  enable_removal_comments = enable_webui_inline_sourcemaps
 }
 
 # Copy all Mojom generated JS files used by the NTP to a common location so that
@@ -196,7 +196,11 @@
   root_dir = "$target_gen_dir/$preprocess_folder"
   out_dir = "$target_gen_dir/tsc"
   composite = true
-  tsconfig_base = "tsconfig_base.json"
+  if (enable_webui_inline_sourcemaps) {
+    tsconfig_base = "tsconfig_base_sourcemaps.json"
+  } else {
+    tsconfig_base = "tsconfig_base.json"
+  }
   in_files = ts_files + html_wrapper_files + mojo_js_files
 
   deps = [
@@ -216,11 +220,17 @@
     ":preprocess",
     ":preprocess_gen",
   ]
+
+  if (enable_webui_inline_sourcemaps) {
+    extra_deps += [ ":sourcemaps" ]
+  }
 }
 
-create_js_source_maps("sourcemaps") {
-  deps = [
-    ":preprocess",
-    ":preprocess_gen",
-  ]
+if (enable_webui_inline_sourcemaps) {
+  create_js_source_maps("sourcemaps") {
+    deps = [
+      ":preprocess",
+      ":preprocess_gen",
+    ]
+  }
 }
diff --git a/chrome/browser/resources/new_tab_page/realbox/OWNERS b/chrome/browser/resources/new_tab_page/realbox/OWNERS
index 810ee8d..c84a283 100644
--- a/chrome/browser/resources/new_tab_page/realbox/OWNERS
+++ b/chrome/browser/resources/new_tab_page/realbox/OWNERS
@@ -1,3 +1,3 @@
 mahmadi@chromium.org
-tommycli@chromium.org
+mfacey@chromium.org
 file://components/omnibox/OWNERS
diff --git a/chrome/browser/resources/new_tab_page/tsconfig_base_sourcemaps.json b/chrome/browser/resources/new_tab_page/tsconfig_base_sourcemaps.json
new file mode 100644
index 0000000..b0374bd
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/tsconfig_base_sourcemaps.json
@@ -0,0 +1,6 @@
+{
+  "extends": "./tsconfig_base.json",
+  "compilerOptions": {
+    "inlineSourceMap": true
+  }
+}
diff --git a/chrome/browser/resources/profile_internals/profile_internals_app.html b/chrome/browser/resources/profile_internals/profile_internals_app.html
index 9484f35..99b98a1 100644
--- a/chrome/browser/resources/profile_internals/profile_internals_app.html
+++ b/chrome/browser/resources/profile_internals/profile_internals_app.html
@@ -8,10 +8,26 @@
     margin: 0;
     padding: 0;
   }
+
+   cr-expand-button {
+     padding-inline-start: 1em;
+   }
+
+   cr-expand-button:hover {
+     filter: contrast(1.1);
+     text-decoration: underline;
+   }
+
+  .unloaded {
+    opacity: 50%;
+  }
 </style>
-<h2>Profiles</h2>\
+<h2>Profiles</h2>
 <template is="dom-repeat" items="[[profilesList_]]">
-  <cr-expand-button expanded="{{item.expanded}}">
+  <cr-expand-button expanded="{{item.expanded}}"
+      class$="[[item.className]]"
+      style$="color: [[item.profileState.foregroundColor]];
+              background-color: [[item.profileState.backgroundColor]];">
     [[item.profileState.localProfileName]]
   </cr-expand-button>
   <iron-collapse opened="[[item.expanded]]">
diff --git a/chrome/browser/resources/profile_internals/profile_internals_app.ts b/chrome/browser/resources/profile_internals/profile_internals_app.ts
index f488ca1..00ee7da 100644
--- a/chrome/browser/resources/profile_internals/profile_internals_app.ts
+++ b/chrome/browser/resources/profile_internals/profile_internals_app.ts
@@ -54,6 +54,7 @@
     this.profilesList_ = profilesList.map(
         profile => ({
           profileState: profile,
+          className: profile.isLoaded ? 'loaded' : 'unloaded',
           expanded: profilesExpanded.get(profile.profilePath) ?? false,
         }));
   }
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index 4ef4d9c..3bdf27a3 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -571,6 +571,7 @@
     "chromeos/os_bluetooth_page/os_bluetooth_change_device_name_dialog.js",
     "chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js",
     "chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js",
+    "chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.js",
     "chromeos/os_bluetooth_page/os_bluetooth_page.js",
     "chromeos/os_bluetooth_page/os_bluetooth_pairing_dialog.js",
     "chromeos/os_bluetooth_page/os_bluetooth_summary.js",
diff --git a/chrome/browser/resources/settings/chromeos/PRESUBMIT.py b/chrome/browser/resources/settings/chromeos/PRESUBMIT.py
index bae42af3..2471515 100644
--- a/chrome/browser/resources/settings/chromeos/PRESUBMIT.py
+++ b/chrome/browser/resources/settings/chromeos/PRESUBMIT.py
@@ -21,13 +21,13 @@
         sys.path = original_sys_path
 
 
-def _CheckTypescriptPreparation(input_api, output_api):
+def _CheckOSSettings(input_api, output_api):
     original_sys_path = sys.path
     try:
         cwd = input_api.PresubmitLocalPath()
         sys.path.append(cwd)
-        from typescript_preparation_checker import TypescriptPreparationChecker
-        return TypescriptPreparationChecker.RunChecks(input_api, output_api)
+        from os_settings_presubmit_checker import OSSettingsPresubmitChecker
+        return OSSettingsPresubmitChecker.RunChecks(input_api, output_api)
     finally:
         sys.path = original_sys_path
 
@@ -36,7 +36,7 @@
     """Checks common to both upload and commit."""
     results = []
     results.extend(_CheckSemanticCssColors(input_api, output_api))
-    results.extend(_CheckTypescriptPreparation(input_api, output_api))
+    results.extend(_CheckOSSettings(input_api, output_api))
     return results
 
 
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn
index e9183ef6..c87bd39 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn
@@ -16,6 +16,7 @@
     ":os_bluetooth_devices_subpage_browser_proxy",
     ":os_bluetooth_page",
     ":os_bluetooth_pairing_dialog",
+    ":os_bluetooth_saved_devices_subpage",
     ":os_bluetooth_summary",
     ":os_bluetooth_true_wireless_images",
     ":os_paired_bluetooth_list",
@@ -123,6 +124,23 @@
   ]
 }
 
+js_library("os_bluetooth_saved_devices_subpage") {
+  deps = [
+    ":os_bluetooth_change_device_name_dialog",
+    ":os_bluetooth_true_wireless_images",
+    "..:os_route",
+    "..:route_observer_behavior",
+    "..:route_origin_behavior",
+    "../..:router",
+    "//chromeos/services/bluetooth_config/public/mojom:mojom_webui_js",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_device_battery_info",
+    "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_metrics_utils",
+    "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_utils",
+    "//ui/webui/resources/js:i18n_behavior.m",
+  ]
+}
+
 js_library("os_bluetooth_change_device_name_dialog") {
   deps = [
     "//chromeos/services/bluetooth_config/public/mojom:mojom_webui_js",
@@ -153,6 +171,7 @@
     "os_paired_bluetooth_list_item.js",
     "os_paired_bluetooth_list.js",
     "os_bluetooth_devices_subpage.js",
+    "os_bluetooth_saved_devices_subpage.js",
     "os_bluetooth_page.js",
     "os_bluetooth_summary.js",
     "os_bluetooth_device_detail_subpage.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.html
index 3073e5db..c52c00c 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.html
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.html
@@ -77,7 +77,8 @@
       class="hr two-line"
       id="savedDevicesRowLink"
       label="$i18n{savedDevicesLabel}"
-      sub-label="[[savedDevicesSublabel_]]">
+      sub-label="[[savedDevicesSublabel_]]"
+      on-click="onClicked_">
   </cr-link-row>
 </template>
 <div class="device-lists-separator"></div>
@@ -88,4 +89,4 @@
       id="enableFastPairToggle"
       deep-link-focus-id$="[[Setting.kFastPairOnOff]]">
   </settings-fast-pair-toggle>
-</template>
\ No newline at end of file
+</template>
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js
index cc8dbc4..ff14d71 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js
@@ -318,6 +318,15 @@
     return this.isFastPairSupportedByDevice_ &&
         loadTimeData.getBoolean('enableSavedDevicesFlag');
   }
+
+  /**
+   * @param {!Event} event
+   * @private
+   */
+  onClicked_(event) {
+    Router.getInstance().navigateTo(routes.BLUETOOTH_SAVED_DEVICES);
+    event.stopPropagation();
+  }
 }
 
 customElements.define(
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_page.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_page.html
index f3cefac..37077dd 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_page.html
@@ -38,6 +38,12 @@
       </os-settings-bluetooth-device-detail-subpage>
     </settings-subpage>
   </template>
+  <div route-path="/bluetoothSavedDevices">
+    <settings-subpage>
+      <os-settings-bluetooth-saved-devices-subpage>
+      </os-settings-bluetooth-saved-devices-subpage>
+    </settings-subpage>
+  </div>
 </settings-animated-pages>
 
 <template is="dom-if" if="[[shouldShowPairingDialog_]]" restamp>
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.html
new file mode 100644
index 0000000..b8f5801f
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.html
@@ -0,0 +1,2 @@
+<style include="settings-shared"></style>
+<div id="container"></div>
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.js
new file mode 100644
index 0000000..df615d7
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_saved_devices_subpage.js
@@ -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.
+
+/**
+ * @fileoverview
+ * Settings subpage for managing Bluetooth saved devices.
+ */
+
+import '../../settings_shared_css.js';
+
+import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+
+/** @polymer */
+class SettingsBluetoothSavedDevicesSubpageElement extends PolymerElement {
+  static get is() {
+    return 'os-settings-bluetooth-saved-devices-subpage';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {};
+  }
+
+  constructor() {
+    super();
+    this.parentNode.pageTitle = loadTimeData.getString('savedDevicesPageName');
+  }
+}
+
+customElements.define(
+    SettingsBluetoothSavedDevicesSubpageElement.is,
+    SettingsBluetoothSavedDevicesSubpageElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_route.js b/chrome/browser/resources/settings/chromeos/os_route.js
index 690202de..28c37fa 100644
--- a/chrome/browser/resources/settings/chromeos/os_route.js
+++ b/chrome/browser/resources/settings/chromeos/os_route.js
@@ -76,6 +76,11 @@
         r.BLUETOOTH, mojom.BLUETOOTH_DEVICE_DETAIL_SUBPAGE_PATH,
         Subpage.kBluetoothDeviceDetail);
   }
+  if (loadTimeData.getBoolean('enableSavedDevicesFlag')) {
+    r.BLUETOOTH_SAVED_DEVICES = createSubpage(
+        r.BLUETOOTH, mojom.BLUETOOTH_SAVED_DEVICES_SUBPAGE_PATH,
+        Subpage.kBluetoothSavedDevices);
+  }
 
   // MultiDevice section.
   if (!loadTimeData.getBoolean('isGuest')) {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js
index e33d3074..cdb10472 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -71,6 +71,7 @@
 import './os_apps_page/os_apps_page.js';
 import './os_bluetooth_page/os_bluetooth_devices_subpage.js';
 import './os_bluetooth_page/os_bluetooth_device_detail_subpage.js';
+import './os_bluetooth_page/os_bluetooth_saved_devices_subpage.js';
 import './os_bluetooth_page/os_bluetooth_true_wireless_images.js';
 import './os_bluetooth_page/os_bluetooth_change_device_name_dialog.js';
 import './os_bluetooth_page/os_bluetooth_pairing_dialog.js';
diff --git a/chrome/browser/resources/settings/chromeos/typescript_preparation_checker.py b/chrome/browser/resources/settings/chromeos/os_settings_presubmit_checker.py
similarity index 65%
rename from chrome/browser/resources/settings/chromeos/typescript_preparation_checker.py
rename to chrome/browser/resources/settings/chromeos/os_settings_presubmit_checker.py
index 31f90b7a..f8db36653 100644
--- a/chrome/browser/resources/settings/chromeos/typescript_preparation_checker.py
+++ b/chrome/browser/resources/settings/chromeos/os_settings_presubmit_checker.py
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 
-def _CheckNoAddSingletonGetter(file):
+def _TypeScriptPrepCheckNoAddSingletonGetter(file):
     """Checks that there are no uses of addSingletonGetter()
 
     Args:
@@ -27,7 +27,7 @@
     return error_messages
 
 
-def _CheckNoLegacyPolymerSyntax(file):
+def _TypeScriptPrepCheckNoLegacyPolymerSyntax(file):
     """Checks that there are no uses of the legacy Polymer element syntax
 
     Args:
@@ -52,17 +52,40 @@
     return error_messages
 
 
-class TypescriptPreparationChecker(object):
-    """Checks that the changes are in line with the upcoming TypeScript
-    migrationfor ChromeOS Settings.
+def _EnforceSchemeSpecificURLs(file):
+    """Checks that only scheme-specific URLs are used and scheme relative URLs
+      are avoided. (i.e. 'chrome://' is preferred over '//')
+
+    Args:
+        file: A changed file
+
+    Returns:
+        A list of error messages (strings)
+    """
+
+    error_messages = []
+    if file.LocalPath().endswith('js'):
+        for line_num, line in file.ChangedContents():
+            if '\'//' in line:
+                error_messages.append(
+                    "%s:%d:\n%s\n\n"
+                    "Prefer using scheme-specific URLs (i.e. 'chrome://')" %
+                    (file.LocalPath(), line_num, line.strip()))
+
+    return error_messages
+
+
+class OSSettingsPresubmitChecker(object):
+    """Checks that the changes comply with ChromeOS Settings code style.
 
     Checks:
       - addSingletonGetter() is not used
+      - No legacy Polymer syntax (1.x, 2.x) is used
     """
 
     @staticmethod
     def RunChecks(input_api, output_api):
-        """Runs checks for compatibility with the upcoming TypeScript migration
+        """Runs checks for ChromeOS Settings
 
         Args:
             input_api: presubmit.InputApi containing information of the files
@@ -76,8 +99,9 @@
 
         error_messages = []
         for file in input_api.AffectedFiles():
-            error_messages += _CheckNoAddSingletonGetter(file)
-            error_messages += _CheckNoLegacyPolymerSyntax(file)
+            error_messages += _TypeScriptPrepCheckNoAddSingletonGetter(file)
+            error_messages += _TypeScriptPrepCheckNoLegacyPolymerSyntax(file)
+            error_messages += _EnforceSchemeSpecificURLs(file)
 
         errors = list(map(output_api.PresubmitPromptWarning, error_messages))
         return errors
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_presubmit_checker_test.py b/chrome/browser/resources/settings/chromeos/os_settings_presubmit_checker_test.py
new file mode 100755
index 0000000..56c1343
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_settings_presubmit_checker_test.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python3
+# 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.
+
+import os
+import sys
+import unittest
+
+from os_settings_presubmit_checker import OSSettingsPresubmitChecker
+
+# Update system path to src/ so we can access src/PRESUBMIT_test_mocks.py.
+sys.path.append(
+    os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', '..',
+                 '..', '..'))
+
+from PRESUBMIT_test_mocks import (MockInputApi, MockOutputApi,
+                                  MockAffectedFile)
+
+
+class OSSettingsPresubmitCheckerTest(unittest.TestCase):
+    def testAddSingletonGetterUsed(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/example_browser_proxy.js', [
+                "import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';",
+                '',
+                'addSingletonGetter(ExampleBrowserProxyImpl);',
+            ]),
+        ]
+        mock_output_api = MockOutputApi()
+
+        errors = OSSettingsPresubmitChecker.RunChecks(mock_input_api,
+                                                      mock_output_api)
+        self.assertEqual(2, len(errors))
+
+    def testAddSingletonGetterNotUsed(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/example_browser_proxy.js', [
+                'static getInstance() {',
+                '  return instance || (instance = new ExampleBrowserProxyImpl());',
+                '}',
+                'static setInstanceForTesting(obj) {',
+                '  instance = obj;',
+                '}',
+            ]),
+        ]
+        mock_output_api = MockOutputApi()
+
+        errors = OSSettingsPresubmitChecker.RunChecks(mock_input_api,
+                                                      mock_output_api)
+        self.assertEqual(0, len(errors))
+
+    def testLegacyPolymerSyntaxUsed(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/example_element.js', [
+                'Polymer({',
+                "  is: 'example-element',",
+                '});',
+            ]),
+        ]
+        mock_output_api = MockOutputApi()
+
+        errors = OSSettingsPresubmitChecker.RunChecks(mock_input_api,
+                                                      mock_output_api)
+        self.assertEqual(1, len(errors))
+
+    def testLegacyPolymerSyntaxNotUsed(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/example_element.js', [
+                'class ExampleElement extends PolymerElement {',
+                '  static get is() {',
+                "    return 'example-element';",
+                "  }",
+                '}',
+            ]),
+        ]
+        mock_output_api = MockOutputApi()
+
+        errors = OSSettingsPresubmitChecker.RunChecks(mock_input_api,
+                                                      mock_output_api)
+        self.assertEqual(0, len(errors))
+
+    def testSchemeSpecificURLsUsed(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/example_element.js', [
+                'import \'chrome://resources/utils.js\';',
+            ]),
+        ]
+        mock_output_api = MockOutputApi()
+
+        errors = OSSettingsPresubmitChecker.RunChecks(mock_input_api,
+                                                      mock_output_api)
+        self.assertEqual(0, len(errors))
+
+    def testSchemeSpecificURLsNotUsed(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/example_element.js', [
+                'import \'chrome://resources/good.js\';',
+                'import \'//resources/bad.js\';',
+                'import \'//resources/bad_again.js\';',
+            ]),
+        ]
+        mock_output_api = MockOutputApi()
+
+        errors = OSSettingsPresubmitChecker.RunChecks(mock_input_api,
+                                                      mock_output_api)
+        self.assertEqual(2, len(errors))
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_routes.js b/chrome/browser/resources/settings/chromeos/os_settings_routes.js
index e5302aa..d3f9bab 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_routes.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_routes.js
@@ -36,6 +36,7 @@
  *   BLUETOOTH: !Route,
  *   BLUETOOTH_DEVICES: !Route,
  *   BLUETOOTH_DEVICE_DETAIL: !Route,
+ *   BLUETOOTH_SAVED_DEVICES: !Route,
  *   BRUSCHETTA_DETAILS: !Route,
  *   BRUSCHETTA_SHARED_USB_DEVICES: !Route,
  *   CHANGE_PICTURE: !Route,
diff --git a/chrome/browser/resources/settings/chromeos/typescript_preparation_checker_test.py b/chrome/browser/resources/settings/chromeos/typescript_preparation_checker_test.py
deleted file mode 100755
index 36493c2a..0000000
--- a/chrome/browser/resources/settings/chromeos/typescript_preparation_checker_test.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env python3
-# 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.
-
-import os
-import sys
-import unittest
-
-from typescript_preparation_checker import TypescriptPreparationChecker
-
-# Update system path to src/ so we can access src/PRESUBMIT_test_mocks.py.
-sys.path.append(
-    os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', '..',
-                 '..', '..'))
-
-from PRESUBMIT_test_mocks import (MockInputApi, MockOutputApi,
-                                  MockAffectedFile)
-
-
-class TypescriptPreparationCheckerTest(unittest.TestCase):
-    def testAddSingletonGetterUsed(self):
-        mock_input_api = MockInputApi()
-        mock_input_api.files = [
-            MockAffectedFile('chrome/example_browser_proxy.js', [
-                "import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';",
-                '',
-                'addSingletonGetter(ExampleBrowserProxyImpl);',
-            ]),
-        ]
-        mock_output_api = MockOutputApi()
-
-        errors = TypescriptPreparationChecker.RunChecks(
-            mock_input_api, mock_output_api)
-        self.assertEqual(2, len(errors))
-
-    def testAddSingletonGetterNotUsed(self):
-        mock_input_api = MockInputApi()
-        mock_input_api.files = [
-            MockAffectedFile('chrome/example_browser_proxy.js', [
-                'static getInstance() {',
-                '  return instance || (instance = new ExampleBrowserProxyImpl());',
-                '}',
-                'static setInstanceForTesting(obj) {',
-                '  instance = obj;',
-                '}',
-            ]),
-        ]
-        mock_output_api = MockOutputApi()
-
-        errors = TypescriptPreparationChecker.RunChecks(
-            mock_input_api, mock_output_api)
-        self.assertEqual(0, len(errors))
-
-    def testLegacyPolymerSyntaxUsed(self):
-        mock_input_api = MockInputApi()
-        mock_input_api.files = [
-            MockAffectedFile('chrome/example_element.js', [
-                'Polymer({',
-                "  is: 'example-element',",
-                '});',
-            ]),
-        ]
-        mock_output_api = MockOutputApi()
-
-        errors = TypescriptPreparationChecker.RunChecks(
-            mock_input_api, mock_output_api)
-        self.assertEqual(1, len(errors))
-
-    def testLegacyPolymerSyntaxNotUsed(self):
-        mock_input_api = MockInputApi()
-        mock_input_api.files = [
-            MockAffectedFile('chrome/example_element.js', [
-                'class ExampleElement extends PolymerElement {',
-                '  static get is() {',
-                "    return 'example-element';",
-                "  }",
-                '}',
-            ]),
-        ]
-        mock_output_api = MockOutputApi()
-
-        errors = TypescriptPreparationChecker.RunChecks(
-            mock_input_api, mock_output_api)
-        self.assertEqual(0, len(errors))
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.html b/chrome/browser/resources/settings/people_page/sync_account_control.html
index da4e5186..26d7e46 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.html
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.html
@@ -199,9 +199,7 @@
         </cr-button>
         <div id="setup-buttons" hidden="[[!showSetupButtons_]]"
             class="cr-button-gap">
-          <cr-button on-click="onSetupCancel_"
-              hidden="[[!isNonSyncingProfilesSupported_()]]">$i18n{cancel}
-          </cr-button>
+          <cr-button on-click="onSetupCancel_">$i18n{cancel}</cr-button>
           <cr-button class="action-button cr-button-gap"
               on-click="onSetupConfirm_">
             $i18n{confirm}
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.ts b/chrome/browser/resources/settings/people_page/sync_account_control.ts
index fe7b37e..7722d9a 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.ts
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.ts
@@ -299,16 +299,6 @@
         !this.getPref('signin.allowed_on_next_startup').value;
   }
 
-  private isNonSyncingProfilesSupported_(): boolean {
-    // <if expr="chromeos_lacros">
-    return loadTimeData.getBoolean('nonSyncingProfilesEnabled');
-    // </if>
-
-    // <if expr="not chromeos_lacros">
-    return true;
-    // </if>
-  }
-
   private shouldShowTurnOffButton_(): boolean {
     // <if expr="chromeos_ash">
     if (this.syncStatus.domain) {
@@ -319,10 +309,6 @@
     }
     // </if>
 
-    if (!this.isNonSyncingProfilesSupported_()) {
-      return false;
-    }
-
     return !this.hideButtons && !this.showSetupButtons_ &&
         !!this.syncStatus.signedIn;
   }
diff --git a/chrome/browser/resources/settings/people_page/sync_page.ts b/chrome/browser/resources/settings/people_page/sync_page.ts
index e20ad76..abae1eb 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.ts
+++ b/chrome/browser/resources/settings/people_page/sync_page.ts
@@ -413,16 +413,6 @@
     this.showSetupCancelDialog_ = false;
   }
 
-  private isNonSyncingProfilesSupported_(): boolean {
-    // <if expr="chromeos_lacros">
-    return loadTimeData.getBoolean('nonSyncingProfilesEnabled');
-    // </if>
-
-    // <if expr="not chromeos_lacros">
-    return true;
-    // </if>
-  }
-
   override currentRouteChanged() {
     const router = Router.getInstance();
     if (router.getCurrentRoute() === getSyncRoutes().SYNC) {
@@ -444,8 +434,7 @@
     }
 
     const userActionCancelsSetup = this.syncStatus &&
-        this.syncStatus.firstSetupInProgress && this.didAbort_ &&
-        this.isNonSyncingProfilesSupported_();
+        this.syncStatus.firstSetupInProgress && this.didAbort_;
     if (userActionCancelsSetup && !this.setupCancelConfirmed_) {
       chrome.metricsPrivate.recordUserAction(
           'Signin_Signin_BackOnAdvancedSyncSettings');
diff --git a/chrome/browser/resources/signin/profile_customization/images/profile_customization_illustration.svg b/chrome/browser/resources/signin/profile_customization/images/profile_customization_illustration.svg
index 9cb4db4..ab19ad2 100644
--- a/chrome/browser/resources/signin/profile_customization/images/profile_customization_illustration.svg
+++ b/chrome/browser/resources/signin/profile_customization/images/profile_customization_illustration.svg
@@ -1 +1 @@
-<svg width="242" height="133" viewBox="0 0 242 133" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 46.552c20-12.5 65-20.5 70.5 0 8.935 33.304-48.109 60.005-37.5 75.5 14 20.448 90-75.5 156-56.5 50.5 14.537 37.5 67 37.5 67" stroke="#E8EAED" stroke-width="2"/><path d="M67.557 82.5C76.324 71.725 83.014 59.65 79.5 46.552c-2.101-7.831-9.966-11.503-20-12.355" stroke="#FCC934" stroke-width="2"/><path d="M164.814 64.5c-4.621.868-9.234 2.098-13.814 3.615a133.584 133.584 0 0 0-7 2.541" stroke="#34A853" stroke-width="2"/><path d="M198 65.552c33.058 9.516 38.905 35.283 39 51.948" stroke="#669DF6" stroke-width="2"/><path d="M7.042 103.126a5.931 5.931 0 1 0 8.167 1.916 5.93 5.93 0 0 0-8.167-1.916Z" fill="#FBBC04"/><path d="m236.73 32.564-6.544-2.076a1.484 1.484 0 0 0-1.453.319l-5.071 4.63a1.49 1.49 0 0 0-.45 1.418l1.476 6.707c.113.519.495.937 1.002 1.098l6.545 2.076c.507.16 1.06.04 1.452-.32l5.072-4.63c.391-.36.562-.898.449-1.417l-1.475-6.708a1.484 1.484 0 0 0-1.003-1.097Z" fill="#34A853"/><path d="m143.342 12.326-16.106-1.051a1.175 1.175 0 0 0-1.251 1.097c-.013.206.028.412.119.598l7.141 14.476a1.178 1.178 0 0 0 1.575.535c.186-.092.343-.23.458-.402l8.965-13.425a1.17 1.17 0 0 0 .077-1.174 1.178 1.178 0 0 0-.978-.654ZM209.507 103.2c1.552 4.167-1.582 18.675-1.582 18.675s-11.86-8.925-13.412-13.092c-1.552-4.166.547-8.794 4.688-10.336 4.14-1.542 8.755.586 10.306 4.753Z" fill="#E8EAED"/><path d="m189.061 79.814 5.623-2.094 6.74 20.966-3.749 1.396-8.614-20.268Z" fill="#E8EAED"/><path d="M174.67 38.301a2 2 0 1 1 3.748-1.396l14.98 40.227-3.749 1.396L174.67 38.3Z" fill="#fff" stroke="#E8EAED" stroke-width="2"/><path d="M209.894 105.322c.395 5.607-1.969 16.553-1.969 16.553s-4.801-3.612-8.693-7.314a19.218 19.218 0 0 1 1.868-2.92 18.947 18.947 0 0 1 8.794-6.319Z" fill="#FBBC04"/><path d="M56.84 7.068a4.89 4.89 0 0 1 6.7-1.763 4.92 4.92 0 0 1 1.767 6.716l-30.62 52.646-8.467-4.953L56.84 7.068Z" fill="#fff" stroke="#E8EAED" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="m24.274 72.805 1.946-13.09 8.453 4.946-10.4 8.144Z" stroke="#E8EAED" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="m25.047 67.56-.778 5.237 4.16-3.257-3.382-1.98Z" fill="#E8EAED"/></svg>
\ No newline at end of file
+<svg width="242" height="133" viewBox="0 0 242 133" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 46.552c20-12.5 65-20.5 70.5 0 8.935 33.304-48.109 60.005-37.5 75.5 14 20.448 90-75.5 156-56.5 50.5 14.537 37.5 67 37.5 67" stroke="#E8EAED" stroke-width="2"/><path d="M67.557 82.5C76.324 71.725 83.014 59.65 79.5 46.552c-2.101-7.831-9.966-11.503-20-12.355" stroke="#FCC934" stroke-width="2"/><path d="M164.814 64.5c-4.621.868-9.234 2.098-13.814 3.615a133.584 133.584 0 0 0-7 2.541" stroke="#34A853" stroke-width="2"/><path d="M198 65.552c33.058 9.516 38.905 35.283 39 51.948" stroke="#669DF6" stroke-width="2"/><path d="M7.042 103.126a5.931 5.931 0 1 0 8.167 1.916 5.93 5.93 0 0 0-8.167-1.916Z" fill="#FBBC04"/><path d="m236.73 32.564-6.544-2.076a1.484 1.484 0 0 0-1.453.319l-5.071 4.63a1.49 1.49 0 0 0-.45 1.418l1.476 6.707c.113.519.495.937 1.002 1.098l6.545 2.076c.507.16 1.06.04 1.452-.32l5.072-4.63c.391-.36.562-.898.449-1.417l-1.475-6.708a1.484 1.484 0 0 0-1.003-1.097Z" fill="#34A853"/><path d="m143.342 12.326-16.106-1.051a1.175 1.175 0 0 0-1.251 1.097 1.19 1.19 0 0 0 .119.598l7.141 14.476a1.178 1.178 0 0 0 1.575.535c.186-.092.343-.23.458-.402l8.965-13.425a1.17 1.17 0 0 0 .077-1.174 1.178 1.178 0 0 0-.978-.654Zm66.165 90.874c1.552 4.167-1.582 18.675-1.582 18.675s-11.86-8.925-13.412-13.092c-1.552-4.166.547-8.794 4.688-10.336 4.14-1.542 8.755.586 10.306 4.753Z" fill="#E8EAED"/><path d="m189.061 79.814 5.623-2.094 6.74 20.966-3.749 1.396-8.614-20.268Z" fill="#E8EAED"/><path d="M174.67 38.301a2 2 0 1 1 3.748-1.396l14.98 40.227-3.749 1.396L174.67 38.3Z" fill="#fff" stroke="#E8EAED" stroke-width="2"/><path d="M209.894 105.322c.395 5.607-1.969 16.553-1.969 16.553s-4.801-3.612-8.693-7.314a19.218 19.218 0 0 1 1.868-2.92 18.947 18.947 0 0 1 8.794-6.319Z" fill="#FBBC04"/><path d="M56.84 7.068a4.89 4.89 0 0 1 6.7-1.763 4.92 4.92 0 0 1 1.767 6.716l-30.62 52.646-8.467-4.953L56.84 7.068Z" fill="#fff" stroke="#E8EAED" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="m24.274 72.805 1.946-13.09 8.453 4.946-10.4 8.144Z" stroke="#E8EAED" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="m25.047 67.56-.778 5.237 4.16-3.257-3.382-1.98Z" fill="#E8EAED"/></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html
index 1554bdb..52e1944 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.html
@@ -100,7 +100,6 @@
     $i18n{signInButtonLabel}
   </cr-button>
   <cr-button id="notNowButton" on-click="onNotNowClick_"
-      hidden="[[!localProfileCreationFlowSupported_]]"
       disabled="[[loadSigninInProgess_]]">
     $i18n{notNowButtonLabel}
   </cr-button>
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.ts b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.ts
index f463b16..da06549 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.ts
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/profile_type_choice.ts
@@ -77,17 +77,6 @@
         value: false,
       },
       // </if>
-
-      /**
-       * If true, it is possible to create local profiles without sign-in.
-       */
-      localProfileCreationFlowSupported_: {
-        type: Boolean,
-        value() {
-          return loadTimeData.getBoolean('localProfileCreationFlowSupported');
-        },
-      },
-
     };
   }
 
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
index 84b42fef..299151965 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.html
@@ -24,9 +24,7 @@
     margin: auto 0;
   }
 
-  /* The settings button is at the start of the line (opposite to other buttons)
-     when sync is optional. */
-  .sync-optional #settingsButton {
+  #settingsButton {
     inset-inline-start: var(--action-container-padding);
     position: absolute;
   }
@@ -244,7 +242,7 @@
     </div>
     <div class="action-row">
       <paper-spinner-lite active="[[anyButtonClicked_]]"></paper-spinner-lite>
-      <div class$="action-container [[syncOptionalClass_]]">
+      <div class="action-container">
         <cr-button class="action-button" id="confirmButton"
             on-click="onConfirm_" disabled="[[anyButtonClicked_]]"
             consent-confirmation autofocus>
@@ -257,7 +255,7 @@
           </cr-button>
         </if>
         <cr-button id="cancelButton" on-click="onUndo_"
-            disabled="[[anyButtonClicked_]]" hidden="[[syncForced_]]">
+            disabled="[[anyButtonClicked_]]">
           $i18n{syncConfirmationUndoLabel}
         </cr-button>
         <if expr="not (is_macosx or is_linux or chromeos_ash or chromeos_lacros)">
@@ -297,8 +295,7 @@
     </div>
     <div class="action-row">
       <paper-spinner-lite active="[[anyButtonClicked_]]"></paper-spinner-lite>
-      <div id="buttonsContainer"
-          class$="action-container [[syncOptionalClass_]]">
+      <div id="buttonsContainer" class="action-container">
         <cr-button class="action-button" id="confirmButton"
             on-click="onConfirm_" disabled="[[anyButtonClicked_]]"
             consent-confirmation>
@@ -311,7 +308,7 @@
           </cr-button>
         </if>
         <cr-button id="notNowButton" on-click="onUndo_"
-          disabled="[[anyButtonClicked_]]" hidden="[[syncForced_]]">
+          disabled="[[anyButtonClicked_]]">
           $i18n{syncConfirmationUndoLabel}
         </cr-button>
         <if expr="not (is_macosx or is_linux or chromeos_ash or chromeos_lacros)">
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts
index 7047ba8f..6e924b5 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.ts
@@ -61,23 +61,6 @@
         type: Boolean,
         value: false,
       },
-
-      syncForced_: {
-        type: Boolean,
-        value() {
-          return loadTimeData.getBoolean('syncForced');
-        }
-      },
-
-      syncOptionalClass_: {
-        type: String,
-        value() {
-          if (loadTimeData.getBoolean('syncForced')) {
-            return '';
-          }
-          return 'sync-optional';
-        },
-      },
     };
   }
 
@@ -85,8 +68,6 @@
   private anyButtonClicked_: boolean;
   private isModalDialog_: boolean;
   private showEnterpriseBadge_: boolean;
-  private syncForced_: boolean;
-  private syncOptionalClass_: string;
   private syncConfirmationBrowserProxy_: SyncConfirmationBrowserProxy =
       SyncConfirmationBrowserProxyImpl.getInstance();
 
diff --git a/chrome/browser/resources/support_tool/data_collectors.html b/chrome/browser/resources/support_tool/data_collectors.html
index d282110..983d400 100644
--- a/chrome/browser/resources/support_tool/data_collectors.html
+++ b/chrome/browser/resources/support_tool/data_collectors.html
@@ -10,10 +10,11 @@
     }
 </style>
 
-<h1>Step 2 of 4: Select diagnostics data to export</h1>
+<h1 tabindex="0">Step 2 of 4: Select diagnostics data to export</h1>
 <iron-list class="data-collector-list" items="[[dataCollectors_]]">
   <template>
-    <cr-checkbox class="data-collector-checkbox" checked="{{item.isIncluded}}">
+    <cr-checkbox class="data-collector-checkbox" checked="{{item.isIncluded}}"
+        tabindex="0">
       [[item.name]]
     </cr-checkbox>
   </template>
diff --git a/chrome/browser/resources/support_tool/data_collectors.ts b/chrome/browser/resources/support_tool/data_collectors.ts
index 1b89f1a..5bc58af 100644
--- a/chrome/browser/resources/support_tool/data_collectors.ts
+++ b/chrome/browser/resources/support_tool/data_collectors.ts
@@ -10,8 +10,11 @@
 
 import {BrowserProxy, BrowserProxyImpl, DataCollectorItem} from './browser_proxy.js';
 import {getTemplate} from './data_collectors.html.js';
+import {SupportToolPageMixin} from './support_tool_page_mixin.js';
 
-export class DataCollectorsElement extends PolymerElement {
+const DataCollectorsElementBase = SupportToolPageMixin(PolymerElement);
+
+export class DataCollectorsElement extends DataCollectorsElementBase {
   static get is() {
     return 'data-collectors';
   }
diff --git a/chrome/browser/resources/support_tool/data_export_done.html b/chrome/browser/resources/support_tool/data_export_done.html
index 76671f1..a93e564 100644
--- a/chrome/browser/resources/support_tool/data_export_done.html
+++ b/chrome/browser/resources/support_tool/data_export_done.html
@@ -15,13 +15,14 @@
 
 </style>
 
-<h1>Step 4 of 4: Diagnostics data is exported</h1>
-<div class="support-tool-title">
+<h1 tabindex="0">Step 4 of 4: Diagnostics data is exported</h1>
+<div class="support-tool-title" tabindex="0">
   Data has been exported into the selected location
 </div>
 <div>
   <iron-icon id="check-icon" icon="cr:check-circle"></iron-icon>
-  <a id="path-link" on-click="onFilePathClicked_" is="action-link">
+  <a id="path-link" on-click="onFilePathClicked_" href="#" is="action-link"
+      tabindex="0">
     [[path_]]
   </a>
 </div>
diff --git a/chrome/browser/resources/support_tool/data_export_done.ts b/chrome/browser/resources/support_tool/data_export_done.ts
index 93f0d6e4..7af1361 100644
--- a/chrome/browser/resources/support_tool/data_export_done.ts
+++ b/chrome/browser/resources/support_tool/data_export_done.ts
@@ -12,8 +12,11 @@
 
 import {BrowserProxy, BrowserProxyImpl} from './browser_proxy.js';
 import {getTemplate} from './data_export_done.html.js';
+import {SupportToolPageMixin} from './support_tool_page_mixin.js';
 
-export class DataExportDoneElement extends PolymerElement {
+const DataExportDoneElementBase = SupportToolPageMixin(PolymerElement);
+
+export class DataExportDoneElement extends DataExportDoneElementBase {
   static get is() {
     return 'data-export-done';
   }
diff --git a/chrome/browser/resources/support_tool/issue_details.html b/chrome/browser/resources/support_tool/issue_details.html
index a2e7124..e8b176eb 100644
--- a/chrome/browser/resources/support_tool/issue_details.html
+++ b/chrome/browser/resources/support_tool/issue_details.html
@@ -29,19 +29,22 @@
   }
 </style>
 
-<h1>Step 1 of 4: Describe the issue</h1>
+<h1 tabindex="0">Step 1 of 4: Describe the issue</h1>
 <div class="support-tool-title">Support Case ID</div>
 <cr-input class="support-case-id" value="{{caseId_}}"
-  spellcheck="false" maxlength="20">
+  spellcheck="false" maxlength="20" aria-label="Support Case ID">
 </cr-input>
-<div class="support-tool-title">Email</div>
-<select class="md-select" value="{{selectedEmail_::change}}">
+<div id="email-title" class="support-tool-title" aria-hidden="true">Email</div>
+<select class="md-select" value="{{selectedEmail_::change}}"
+    aria-labelledby="email-title">
   <template is="dom-repeat" items="[[emails_]]">
   <option value="[[item]]">[[item]]</option>
   </template>
 </select>
-<div class="support-tool-title">Describe the issue</div>
-<textarea id="description" class="support-tool-text" value="{{issueDescription_::input}}"
-  spellcheck="true"
+<div id="description-title" class="support-tool-title" aria-hidden="true">
+  Describe the issue
+</div>
+<textarea id="description" class="support-tool-text" spellcheck="true"
+  value="{{issueDescription_::input}}" aria-labelledby="description-title"
   placeholder="Provide a clear desciption of the issue and steps to reproduce the issue (if possible)">
-</textarea>
+</textarea>
\ No newline at end of file
diff --git a/chrome/browser/resources/support_tool/issue_details.ts b/chrome/browser/resources/support_tool/issue_details.ts
index 1c42030..f89651d 100644
--- a/chrome/browser/resources/support_tool/issue_details.ts
+++ b/chrome/browser/resources/support_tool/issue_details.ts
@@ -13,10 +13,13 @@
 
 import {BrowserProxy, BrowserProxyImpl, IssueDetails} from './browser_proxy.js';
 import {getTemplate} from './issue_details.html.js';
+import {SupportToolPageMixin} from './support_tool_page_mixin.js';
 
 const DONT_INCLUDE_EMAIL: string = 'Do not include email address';
 
-export class IssueDetailsElement extends PolymerElement {
+const IssueDetailsElementBase = SupportToolPageMixin(PolymerElement);
+
+export class IssueDetailsElement extends IssueDetailsElementBase {
   static get is() {
     return 'issue-details';
   }
diff --git a/chrome/browser/resources/support_tool/pii_selection.html b/chrome/browser/resources/support_tool/pii_selection.html
index 20cafcf..909a6d0 100644
--- a/chrome/browser/resources/support_tool/pii_selection.html
+++ b/chrome/browser/resources/support_tool/pii_selection.html
@@ -65,28 +65,30 @@
   }
 </style>
 
-<h1>Step 3 of 4: Review personally identifiable information</h1>
-<div id="pii-warning-text" class="support-tool-title">
+<h1 tabindex="0">
+  Step 3 of 4: Review personally identifiable information
+</h1>
+<div id="pii-warning-text" class="support-tool-title" tabindex="0">
   Diagnostic data collection is complete. Some of your personal information is
   included in this data.
 </div>
 <div id="radio-group">
   <cr-radio-group selected="[[selectedRadioButton_]]"
       on-selected-changed="onSelectedRadioButtonChanged_">
-    <cr-radio-button name="[[piiRadioButtonsEnum_.INCLUDE_ALL]]">
+    <cr-radio-button name="[[piiRadioButtonsEnum_.INCLUDE_ALL]]" tabindex="0">
       Include all personal information
     </cr-radio-button>
-    <cr-radio-button name="[[piiRadioButtonsEnum_.INCLUDE_NONE]]">
+    <cr-radio-button name="[[piiRadioButtonsEnum_.INCLUDE_NONE]]" tabindex="0">
       Automatically remove most personal information
     </cr-radio-button>
     <iron-collapse id="privacy-disclaimer"
         opened$="[[showDisclaimer_(selectedRadioButton_)]]">
-      <div>
+      <div tabindex="0">
         Some personal information may still be included in the data. Make sure
-        to review the exported files. 
+        to review the exported files.
       </div>
     </iron-collapse>
-    <cr-radio-button name="[[piiRadioButtonsEnum_.INCLUDE_SOME]]">
+    <cr-radio-button name="[[piiRadioButtonsEnum_.INCLUDE_SOME]]" tabindex="0">
       Manually select personal information you want to include
     </cr-radio-button>
   </cr-radio-group>
@@ -96,13 +98,13 @@
     <template is="dom-repeat" items="[[detectedPIIItems_]]">
       <div id="detected-pii-item">
         <cr-expand-button expanded="{{item.expandDetails}}">
-          <cr-checkbox checked="{{item.keep}}">
+          <cr-checkbox checked="{{item.keep}}" tabindex="0">
             [[item.piiTypeDescription]]: [[item.count]]
           </cr-checkbox>
         </cr-expand-button>
         <iron-collapse class="pii-item-collapse"
             opened="[[item.expandDetails]]">
-          <div class="pii-details">[[item.detectedData]]</div>
+          <div class="pii-details" tabindex="0">[[item.detectedData]]</div>
         </iron-collapse>
       </div>
     </template>
diff --git a/chrome/browser/resources/support_tool/pii_selection.ts b/chrome/browser/resources/support_tool/pii_selection.ts
index 0f12cb70..28a1662b 100644
--- a/chrome/browser/resources/support_tool/pii_selection.ts
+++ b/chrome/browser/resources/support_tool/pii_selection.ts
@@ -14,6 +14,7 @@
 
 import {BrowserProxy, BrowserProxyImpl, PIIDataItem} from './browser_proxy.js';
 import {getTemplate} from './pii_selection.html.js';
+import {SupportToolPageMixin} from './support_tool_page_mixin.js';
 
 // Names of the radio buttons which allow the user to choose to keep or remove
 // their PII data.
@@ -24,7 +25,9 @@
   UNSELECTED = 'unselected',
 }
 
-export class PIISelectionElement extends PolymerElement {
+const PIISelectionElementBase = SupportToolPageMixin(PolymerElement);
+
+export class PIISelectionElement extends PIISelectionElementBase {
   static get is() {
     return 'pii-selection';
   }
diff --git a/chrome/browser/resources/support_tool/spinner_page.html b/chrome/browser/resources/support_tool/spinner_page.html
index ed2c9851..9128216 100644
--- a/chrome/browser/resources/support_tool/spinner_page.html
+++ b/chrome/browser/resources/support_tool/spinner_page.html
@@ -10,7 +10,7 @@
   }
 </style>
 
-<h1>[[pageTitle]]</h1>
+<h1  id="header" tabindex="0">[[pageTitle]]</h1>
 <paper-spinner-lite active>
 </paper-spinner-lite>
 <div class="navigation-buttons">
diff --git a/chrome/browser/resources/support_tool/spinner_page.ts b/chrome/browser/resources/support_tool/spinner_page.ts
index 6834366..299e997 100644
--- a/chrome/browser/resources/support_tool/spinner_page.ts
+++ b/chrome/browser/resources/support_tool/spinner_page.ts
@@ -10,8 +10,11 @@
 
 import {BrowserProxy, BrowserProxyImpl} from './browser_proxy.js';
 import {getTemplate} from './spinner_page.html.js';
+import {SupportToolPageMixin} from './support_tool_page_mixin.js';
 
-export class SpinnerPageElement extends PolymerElement {
+const SpinnerPageElementBase = SupportToolPageMixin(PolymerElement);
+
+export class SpinnerPageElement extends SpinnerPageElementBase {
   static get is() {
     return 'spinner-page';
   }
diff --git a/chrome/browser/resources/support_tool/support_tool.gni b/chrome/browser/resources/support_tool/support_tool.gni
index 1044b44..8366fad5 100644
--- a/chrome/browser/resources/support_tool/support_tool.gni
+++ b/chrome/browser/resources/support_tool/support_tool.gni
@@ -13,6 +13,11 @@
   "url_generator.ts",
 ]
 
+_non_web_component_files = [
+  "browser_proxy.ts",
+  "support_tool_page_mixin.ts",
+]
+
 # Files that are passed as input to html_to_wrapper().
 html_files = []
 foreach(f, _web_component_files) {
@@ -34,4 +39,4 @@
   css_wrapper_files += [ f + ".ts" ]
 }
 
-ts_files = _web_component_files + [ "browser_proxy.ts" ]
+ts_files = _web_component_files + _non_web_component_files
diff --git a/chrome/browser/resources/support_tool/support_tool.html b/chrome/browser/resources/support_tool/support_tool.html
index 4401b48..9d34169 100644
--- a/chrome/browser/resources/support_tool/support_tool.html
+++ b/chrome/browser/resources/support_tool/support_tool.html
@@ -30,8 +30,8 @@
     <pii-selection id="piiSelection"
         page-index="[[supportToolPageIndex_.PII_SELECTION]]">
     </pii-selection>
-    <spinner-page page-index="[[supportToolPageIndex_.EXPORT_SPINNER]]"
-        page-title="Exporting diagnostic data">
+    <spinner-page id="exportSpinner" page-title="Exporting diagnostic data"
+        page-index="[[supportToolPageIndex_.EXPORT_SPINNER]]">
     </spinner-page>
     <data-export-done id="dataExportDone"
         page-index="[[supportToolPageIndex_.DATA_EXPORT_DONE]]">
@@ -49,9 +49,10 @@
     Continue
   </cr-button>
 </div>
-<cr-toast id="errorMessageToast" duration="0">
-  <span>[[errorMessage_]]</span>
+<cr-toast id="errorMessageToast" duration="0" tabindex="0"
+    aria-labelledby="error-message">
+  <span id="error-message">[[errorMessage_]]</span>
   <cr-icon-button on-click="onErrorMessageToastCloseClicked_"
-      iron-icon="cr:close">
+      iron-icon="cr:close" aria-label="close">
   </cr-icon-button>
 </cr-toast>
diff --git a/chrome/browser/resources/support_tool/support_tool.ts b/chrome/browser/resources/support_tool/support_tool.ts
index 51f4723..9eaddd6 100644
--- a/chrome/browser/resources/support_tool/support_tool.ts
+++ b/chrome/browser/resources/support_tool/support_tool.ts
@@ -47,6 +47,7 @@
     dataCollectors: DataCollectorsElement,
     spinnerPage: SpinnerPageElement,
     piiSelection: PIISelectionElement,
+    exportSpinner: SpinnerPageElement,
     dataExportDone: DataExportDoneElement,
     errorMessageToast: CrToastElement,
   };
@@ -68,6 +69,7 @@
       selectedPage_: {
         type: SupportToolPageIndex,
         value: SupportToolPageIndex.ISSUE_DETAILS,
+        observer: 'onSelectedPageChange_',
       },
       supportToolPageIndex_: {
         readonly: true,
@@ -174,6 +176,33 @@
     // data collectors selection page.
     return this.selectedPage_ >= SupportToolPageIndex.SPINNER;
   }
+
+  private onSelectedPageChange_() {
+    // On every selected page change, the focus will be moved to each page's
+    // header to ensure a smooth experience in terms of accessibility.
+    switch (this.selectedPage_) {
+      case SupportToolPageIndex.ISSUE_DETAILS:
+        this.$.issueDetails.ensureFocusOnPageHeader();
+        break;
+      case SupportToolPageIndex.DATA_COLLECTOR_SELECTION:
+        this.$.dataCollectors.ensureFocusOnPageHeader();
+        break;
+      case SupportToolPageIndex.SPINNER:
+        this.$.spinnerPage.ensureFocusOnPageHeader();
+        break;
+      case SupportToolPageIndex.PII_SELECTION:
+        this.$.piiSelection.ensureFocusOnPageHeader();
+        break;
+      case SupportToolPageIndex.EXPORT_SPINNER:
+        this.$.exportSpinner.ensureFocusOnPageHeader();
+        break;
+      case SupportToolPageIndex.DATA_EXPORT_DONE:
+        this.$.dataExportDone.ensureFocusOnPageHeader();
+        break;
+      default:
+        break;
+    }
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/support_tool/support_tool_page_mixin.ts b/chrome/browser/resources/support_tool/support_tool_page_mixin.ts
new file mode 100644
index 0000000..40242385
--- /dev/null
+++ b/chrome/browser/resources/support_tool/support_tool_page_mixin.ts
@@ -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.
+
+/**
+ * @fileoverview Mixin to be used by Polymer elements that define Support Tool
+ * pages.
+ */
+
+import {dedupingMixin, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+type Constructor<T> = new (...args: any[]) => T;
+
+export const SupportToolPageMixin = dedupingMixin(
+    <T extends Constructor<PolymerElement>>(superClass: T): T&
+    Constructor<SupportToolPageMixinInterface> => {
+      class SupportToolPageMixin extends superClass implements
+          SupportToolPageMixinInterface {
+        $$<E extends Element = Element>(query: string) {
+          return this.shadowRoot!.querySelector<E>(query);
+        }
+
+        // Puts the focus on the first header (h1) element of the page. Every
+        // Support Tool page Polymer element that implements this mixin should
+        // have a focusable header to describe the step.
+        ensureFocusOnPageHeader() {
+          this.$$<HTMLElement>('h1')!.focus();
+        }
+      }
+      return SupportToolPageMixin;
+    });
+
+export interface SupportToolPageMixinInterface {
+  $$<E extends Element = Element>(query: string): E|null;
+
+  ensureFocusOnPageHeader(): void;
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/support_tool/url_generator.html b/chrome/browser/resources/support_tool/url_generator.html
index 45e8ec0..f152d337 100644
--- a/chrome/browser/resources/support_tool/url_generator.html
+++ b/chrome/browser/resources/support_tool/url_generator.html
@@ -27,16 +27,18 @@
   }
 </style>
 
-<h1>Get a Support Tool link</h1>
+<h1 tabindex="0">Get a Support Tool link</h1>
 <div class="support-tool-title">Support Case ID</div>
 <cr-input id="caseIdInput" class="support-case-id" value="{{caseId_}}"
-  spellcheck="false" maxlength="20"">
+  spellcheck="false" maxlength="20" aria-label="Support Case ID">
 </cr-input>
-<div class="support-tool-title">Data sources to collect</div>
-<div class="data-collector-list">
+<div id="data-sources-title" class="support-tool-title" tabindex="0">
+  Data sources to collect
+</div>
+<div class="data-collector-list" aria-labelledby="data-sources-title">
   <template is="dom-repeat" items="[[dataCollectors_]]">
     <cr-checkbox class="data-collector-checkbox" checked="{{item.isIncluded}}" 
-        on-click="onDataCollectorItemClicked_">
+        on-click="onDataCollectorItemClicked_" tabindex="0">
       [[item.name]]
     </cr-checkbox>
   </template>
@@ -44,18 +46,22 @@
 
 <div class="support-tool-title">Get a link</div>
 <div id="info-text">
-  Copy and send this link to the user to collect the logs.
+  <span tabindex="0">
+    Copy and send this link to the user to collect the logs.
+  </span>
   <cr-button id="copyURLButton" class="navigation-buttons action-button"
       on-click="onCopyURLClick_" disabled="[[buttonDisabled_]]">
     Copy link
   </cr-button>
 </div>
-<cr-toast id="copyToast" duration="5000">
-  <span>Link copied</span>
+<cr-toast id="copyToast" duration="5000" tabindex="0"
+    aria-labelledby="link-copied-message">
+  <span id="link-copied-message">Link copied</span>
 </cr-toast>
-<cr-toast id="errorMessageToast" duration="0">
-  <span>[[errorMessage_]]</span>
+<cr-toast id="errorMessageToast" duration="0" tabindex="0"
+    aria-labelledby="error-message">
+  <span id="error-message">[[errorMessage_]]</span>
   <cr-icon-button on-click="onErrorMessageToastCloseClicked_"
-      iron-icon="cr:close">
+      iron-icon="cr:close" aria-label="close">
   </cr-icon-button>
 </cr-toast>
diff --git a/chrome/browser/resources/support_tool/url_generator.ts b/chrome/browser/resources/support_tool/url_generator.ts
index 41cb5ba..c9507eb 100644
--- a/chrome/browser/resources/support_tool/url_generator.ts
+++ b/chrome/browser/resources/support_tool/url_generator.ts
@@ -100,6 +100,7 @@
       this.generatedURL_ = result.url;
       navigator.clipboard.writeText(this.generatedURL_.toString());
       this.$.copyToast.show();
+      this.$.copyToast.focus();
     } else {
       this.showErrorMessageToast_(result.errorMessage);
     }
diff --git a/chrome/browser/safe_browsing/test_extension_event_observer.cc b/chrome/browser/safe_browsing/test_extension_event_observer.cc
index e1061ed..d97771e6 100644
--- a/chrome/browser/safe_browsing/test_extension_event_observer.cc
+++ b/chrome/browser/safe_browsing/test_extension_event_observer.cc
@@ -28,7 +28,7 @@
 }
 
 base::Value TestExtensionEventObserver::PassEventArgs() {
-  return std::move(latest_event_args_);
+  return base::Value(std::move(latest_event_args_));
 }
 
 void TestExtensionEventObserver::OnBroadcastEvent(
@@ -38,7 +38,7 @@
       event.event_name == OnPolicySpecifiedPasswordReuseDetected::kEventName ||
       event.event_name == OnPolicySpecifiedPasswordChanged::kEventName ||
       event.event_name == OnDangerousDownloadOpened::kEventName) {
-    latest_event_args_ = event.event_args->Clone();
+    latest_event_args_ = event.event_args.Clone();
     latest_event_name_ = event.event_name;
   }
 }
diff --git a/chrome/browser/safe_browsing/test_extension_event_observer.h b/chrome/browser/safe_browsing/test_extension_event_observer.h
index 11c14422..9e66e3f 100644
--- a/chrome/browser/safe_browsing/test_extension_event_observer.h
+++ b/chrome/browser/safe_browsing/test_extension_event_observer.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_SAFE_BROWSING_TEST_EXTENSION_EVENT_OBSERVER_H_
 #define CHROME_BROWSER_SAFE_BROWSING_TEST_EXTENSION_EVENT_OBSERVER_H_
 
+#include "base/values.h"
 #include "extensions/browser/test_event_router.h"
 
 class GURL;
@@ -38,7 +39,7 @@
 
  private:
   // The arguments passed for the last observed event.
-  base::Value latest_event_args_;
+  base::Value::List latest_event_args_;
   std::string latest_event_name_;
 };
 
diff --git a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java
index e50db51e..b64c3fe3 100644
--- a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java
+++ b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java
@@ -590,12 +590,14 @@
                 mPasswordCheckupHelper, getSyncingAccount(),
                 count
                 -> {
-                    if (weakRef.get() == null) return;
-                    weakRef.get().onBreachedCredentialsObtained(count, false);
+                    SafetyCheckMediator mediator = weakRef.get();
+                    if (mediator == null) return;
+                    mediator.onBreachedCredentialsObtained(count, false);
                 },
                 error -> {
-                    if (weakRef.get() == null) return;
-                    weakRef.get().onPasswordCheckFailed(error);
+                    SafetyCheckMediator mediator = weakRef.get();
+                    if (mediator == null) return;
+                    mediator.onPasswordCheckFailed(error);
                 });
     }
 
@@ -616,12 +618,14 @@
                 mPasswordCheckupHelper, getSyncingAccount(),
                 unused
                 -> {
-                    if (weakRef.get() == null) return;
-                    weakRef.get().onPasswordCheckFinished();
+                    SafetyCheckMediator mediator = weakRef.get();
+                    if (mediator == null) return;
+                    mediator.onPasswordCheckFinished();
                 },
                 error -> {
-                    if (weakRef.get() == null) return;
-                    weakRef.get().onPasswordCheckFailed(error);
+                    SafetyCheckMediator mediator = weakRef.get();
+                    if (mediator == null) return;
+                    mediator.onPasswordCheckFailed(error);
                 });
     }
 
@@ -655,12 +659,14 @@
                 mPasswordCheckupHelper, getSyncingAccount(),
                 count
                 -> {
-                    if (weakRef.get() == null) return;
-                    weakRef.get().onBreachedCredentialsObtained(count, true);
+                    SafetyCheckMediator mediator = weakRef.get();
+                    if (mediator == null) return;
+                    mediator.onBreachedCredentialsObtained(count, true);
                 },
                 error -> {
-                    if (weakRef.get() == null) return;
-                    weakRef.get().onPasswordCheckFailed(error);
+                    SafetyCheckMediator mediator = weakRef.get();
+                    if (mediator == null) return;
+                    mediator.onPasswordCheckFailed(error);
                 });
     }
 
diff --git a/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediator.java b/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediator.java
index 70c9d205..1c9e6f8 100644
--- a/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediator.java
+++ b/chrome/browser/search_resumption/java/src/org/chromium/chrome/browser/search_resumption/SearchResumptionModuleMediator.java
@@ -94,9 +94,9 @@
     private int getPageClassification() {
         if (TemplateUrlServiceFactory.get().isSearchResultsPageFromDefaultSearchProvider(
                     mTabToTrackSuggestion.getUrl())) {
-            return PageClassification.NTP_SEARCH_RESUMPTION_SEARCH_RESULT_PAGE_VALUE;
+            return PageClassification.SEARCH_RESUMPTION_SEARCH_RESULT_PAGE_VALUE;
         } else {
-            return PageClassification.NTP_SEARCH_RESUMPTION_OTHER_VALUE;
+            return PageClassification.SEARCH_RESUMPTION_OTHER_VALUE;
         }
     }
 
diff --git a/chrome/browser/segmentation_platform/segmentation_platform_config.cc b/chrome/browser/segmentation_platform/segmentation_platform_config.cc
index c6661c8..7f9a8bd 100644
--- a/chrome/browser/segmentation_platform/segmentation_platform_config.cc
+++ b/chrome/browser/segmentation_platform/segmentation_platform_config.cc
@@ -48,7 +48,7 @@
 
 #if BUILDFLAG(IS_ANDROID)
 
-constexpr int kAdaptiveToolbarDefaultSelectionTTLDays = 28;
+constexpr int kAdaptiveToolbarDefaultSelectionTTLDays = 56;
 
 constexpr int kChromeStartDefaultSelectionTTLDays = 30;
 constexpr int kChromeStartDefaultUnknownTTLDays = 7;
diff --git a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
index c736ecf..3bcd2a5 100644
--- a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
+++ b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
@@ -441,7 +441,7 @@
   SystemWebAppSessionRestoreTestChromeOS()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        web_app::TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
+        ash::TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp();
     maybe_installation_->set_update_policy(
         ash::SystemWebAppManager::UpdatePolicy::kOnVersionChange);
   }
diff --git a/chrome/browser/sessions/tab_restore_service_browsertest.cc b/chrome/browser/sessions/tab_restore_service_browsertest.cc
index b196ccf..10d2ac7 100644
--- a/chrome/browser/sessions/tab_restore_service_browsertest.cc
+++ b/chrome/browser/sessions/tab_restore_service_browsertest.cc
@@ -9,12 +9,12 @@
 #include "components/sessions/core/tab_restore_service.h"
 
 #include "build/chromeos_buildflags.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/tab_restore_service_factory.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -26,15 +26,14 @@
  public:
   TabRestoreServiceImplBrowserTest()
       : test_system_web_app_installation_(
-            web_app::TestSystemWebAppInstallation::
-                SetUpTabbedMultiWindowApp()) {
+            ash::TestSystemWebAppInstallation::SetUpTabbedMultiWindowApp()) {
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
     web_app::EnableSystemWebAppsInLacrosForTesting();
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
   }
 
  protected:
-  std::unique_ptr<web_app::TestSystemWebAppInstallation>
+  std::unique_ptr<ash::TestSystemWebAppInstallation>
       test_system_web_app_installation_;
 };
 
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc
index abdbdbd6..400bb1ee 100644
--- a/chrome/browser/signin/account_reconcilor_factory.cc
+++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/check.h"
-#include "base/feature_list.h"
 #include "base/notreached.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -22,7 +21,6 @@
 #include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_buildflags.h"
-#include "components/signin/public/base/signin_switches.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/components/tpm/install_attributes.h"
@@ -196,15 +194,11 @@
       return std::make_unique<signin::MirrorAccountReconcilorDelegate>(
           IdentityManagerFactory::GetForProfile(profile));
 #elif BUILDFLAG(IS_CHROMEOS_LACROS)
-      if (base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-        bool is_main_profile = ChromeSigninClientFactory::GetForProfile(profile)
-                                   ->GetInitialPrimaryAccount()
-                                   .has_value();
-        return std::make_unique<signin::MirrorLandingAccountReconcilorDelegate>(
-            IdentityManagerFactory::GetForProfile(profile), is_main_profile);
-      }
-      return std::make_unique<signin::MirrorAccountReconcilorDelegate>(
-          IdentityManagerFactory::GetForProfile(profile));
+      return std::make_unique<signin::MirrorLandingAccountReconcilorDelegate>(
+          IdentityManagerFactory::GetForProfile(profile),
+          ChromeSigninClientFactory::GetForProfile(profile)
+              ->GetInitialPrimaryAccount()
+              .has_value());
 #else
       return std::make_unique<signin::MirrorAccountReconcilorDelegate>(
           IdentityManagerFactory::GetForProfile(profile));
diff --git a/chrome/browser/signin/identity_services_provider_android.cc b/chrome/browser/signin/identity_services_provider_android.cc
index cb49ede..eef6a49 100644
--- a/chrome/browser/signin/identity_services_provider_android.cc
+++ b/chrome/browser/signin/identity_services_provider_android.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/android/jni_android.h"
+#include "chrome/browser/android/signin/signin_manager_android.h"
 #include "chrome/browser/profiles/profile_android.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/services/android/jni_headers/IdentityServicesProvider_jni.h"
@@ -17,7 +18,11 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& j_profile_android) {
   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
-  return IdentityManagerFactory::GetForProfile(profile)->GetJavaObject();
+  signin::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile);
+  // Ensuring that the pointer is not null here produces unactionable stack
+  // traces, so just let the Java side handle possible issues with null.
+  return identity_manager ? identity_manager->GetJavaObject() : nullptr;
 }
 
 static ScopedJavaLocalRef<jobject>
@@ -27,7 +32,11 @@
   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
   signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(profile);
-  return identity_manager->LegacyGetAccountTrackerServiceJavaObject();
+  // Ensuring that the pointer is not null here produces unactionable stack
+  // traces, so just let the Java side handle possible issues with null.
+  return identity_manager
+             ? identity_manager->LegacyGetAccountTrackerServiceJavaObject()
+             : nullptr;
 }
 
 static ScopedJavaLocalRef<jobject>
@@ -35,5 +44,9 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& j_profile_android) {
   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
-  return SigninManagerAndroidFactory::GetJavaObjectForProfile(profile);
+  SigninManagerAndroid* signin_manager =
+      SigninManagerAndroidFactory::GetForProfile(profile);
+  // Ensuring that the pointer is not null here produces unactionable stack
+  // traces, so just let the Java side handle possible issues with null.
+  return signin_manager ? signin_manager->GetJavaObject() : nullptr;
 }
diff --git a/chrome/browser/signin/signin_manager_android_factory.cc b/chrome/browser/signin/signin_manager_android_factory.cc
index 83c53f0a..e2bd6ea 100644
--- a/chrome/browser/signin/signin_manager_android_factory.cc
+++ b/chrome/browser/signin/signin_manager_android_factory.cc
@@ -20,11 +20,10 @@
 SigninManagerAndroidFactory::~SigninManagerAndroidFactory() {}
 
 // static
-base::android::ScopedJavaLocalRef<jobject>
-SigninManagerAndroidFactory::GetJavaObjectForProfile(Profile* profile) {
+SigninManagerAndroid* SigninManagerAndroidFactory::GetForProfile(
+    Profile* profile) {
   return static_cast<SigninManagerAndroid*>(
-             GetInstance()->GetServiceForBrowserContext(profile, true))
-      ->GetJavaObject();
+      GetInstance()->GetServiceForBrowserContext(profile, true));
 }
 
 // static
diff --git a/chrome/browser/signin/signin_manager_android_factory.h b/chrome/browser/signin/signin_manager_android_factory.h
index 5eabc40..fd1b07c2 100644
--- a/chrome/browser/signin/signin_manager_android_factory.h
+++ b/chrome/browser/signin/signin_manager_android_factory.h
@@ -10,11 +10,11 @@
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
 class Profile;
+class SigninManagerAndroid;
 
 class SigninManagerAndroidFactory : public BrowserContextKeyedServiceFactory {
  public:
-  static base::android::ScopedJavaLocalRef<jobject> GetJavaObjectForProfile(
-      Profile* profile);
+  static SigninManagerAndroid* GetForProfile(Profile* profile);
 
   // Returns an instance of the SigninManagerAndroidFactory singleton.
   static SigninManagerAndroidFactory* GetInstance();
diff --git a/chrome/browser/spellchecker/spellcheck_service.cc b/chrome/browser/spellchecker/spellcheck_service.cc
index fb1ce87c..16c3402 100644
--- a/chrome/browser/spellchecker/spellcheck_service.cc
+++ b/chrome/browser/spellchecker/spellcheck_service.cc
@@ -845,13 +845,8 @@
 }
 
 void SpellcheckService::OnAcceptLanguagesChanged() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  // Accept-Languages and spell check are decoupled in LSV2 Update 2.
-  if (base::FeatureList::IsEnabled(ash::features::kLanguageSettingsUpdate2)) {
-    return;
-  }
-#endif
-
+  // Accept-Languages and spell check are decoupled on CrOS.
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
   std::vector<std::string> accept_languages = GetNormalizedAcceptLanguages();
 
   StringListPrefMember dictionaries_pref;
@@ -871,6 +866,7 @@
 #if BUILDFLAG(IS_WIN)
   RecordChromeLocalesStats();
 #endif  // BUILDFLAG(IS_WIN)
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 std::vector<std::string> SpellcheckService::GetNormalizedAcceptLanguages(
diff --git a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
index 15a57ba..29d52b1 100644
--- a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
+++ b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -85,14 +85,6 @@
     InProcessBrowserTest::SetUp();
   }
 #endif  // BUILDFLAG(IS_WIN)
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  void SetUp() override {
-    // On CrOS, Language Settings Update 2 will be the norm going forward.
-    // Forcibly enable it here in case it is disabled in the future.
-    feature_list_.InitAndEnableFeature(ash::features::kLanguageSettingsUpdate2);
-    InProcessBrowserTest::SetUp();
-  }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   void SetUpOnMainThread() override {
     renderer_ = std::make_unique<content::MockRenderProcessHost>(GetContext());
@@ -367,38 +359,14 @@
 #endif  // !BUILDFLAG(IS_MAC)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-// Tests related to CrOS Language Settings Update 2.
-// Spell check languages and accept languages are decoupled with Update 2.
-// All tests which rely on the coupling should use the below class.
-// TODO(crbug.com/1177519): Remove this once Update 2 is fully launched.
-class SpellcheckServiceLanguageSettingsUpdate2DisabledBrowserTest
-    : public SpellcheckServiceBrowserTest {
-  void SetUp() override {
-    feature_list_.InitAndDisableFeature(
-        ash::features::kLanguageSettingsUpdate2);
-    InProcessBrowserTest::SetUp();
-  }
-};
-
 // Removing a spellcheck language from accept languages should not remove it
-// from spellcheck languages list with Update 2 enabled.
+// from spellcheck languages list on CrOS.
 IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
                        RemoveSpellcheckLanguageFromAcceptLanguages) {
   InitSpellcheck(true, "", "en-US,fr");
   SetAcceptLanguages("en-US,es,ru");
   EXPECT_EQ("en-US,fr", GetMultilingualDictionaries());
 }
-
-// Removing a spellcheck language from accept languages should remove it from
-// spellcheck languages list as well with Update 2 disabled.
-// TODO(crbug.com/1177519): Remove this once Update 2 is fully launched.
-IN_PROC_BROWSER_TEST_F(
-    SpellcheckServiceLanguageSettingsUpdate2DisabledBrowserTest,
-    RemoveSpellcheckLanguageFromAcceptLanguages) {
-  InitSpellcheck(true, "", "en-US,fr");
-  SetAcceptLanguages("en-US,es,ru");
-  EXPECT_EQ("en-US", GetMultilingualDictionaries());
-}
 #else
 // Removing a spellcheck language from accept languages should remove it from
 // spellcheck languages list as well.
diff --git a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.h b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.h
index 284d616..cab0bd4 100644
--- a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.h
+++ b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.h
@@ -80,6 +80,7 @@
     virtual void OnGetFamilyMembersSuccess(
         const std::vector<FamilyMember>& members) {}
     virtual void OnFailure(ErrorCode error) {}
+    virtual ~Consumer() = default;
   };
 
   // Instantiates a fetcher, but doesn't start a fetch - use the StartGet*
diff --git a/chrome/browser/sync/sync_service_factory.cc b/chrome/browser/sync/sync_service_factory.cc
index 581e57a..9cdc094 100644
--- a/chrome/browser/sync/sync_service_factory.cc
+++ b/chrome/browser/sync/sync_service_factory.cc
@@ -78,9 +78,6 @@
 #include "chrome/browser/sync/wifi_configuration_sync_service_factory.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "components/signin/public/base/signin_switches.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 namespace {
 
 std::unique_ptr<KeyedService> BuildSyncService(
@@ -151,12 +148,6 @@
     // need to take care that SyncServiceImpl doesn't get tripped up between
     // those two cases. Bug 88109.
     bool is_auto_start = browser_defaults::kSyncAutoStarts;
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-    if (profile->IsMainProfile() &&
-        !base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-      is_auto_start = true;
-    }
-#endif
     init_params.start_behavior = is_auto_start
                                      ? syncer::SyncServiceImpl::AUTO_START
                                      : syncer::SyncServiceImpl::MANUAL_START;
diff --git a/chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.cc b/chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.cc
index e1f1573..d5655b7e 100644
--- a/chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.cc
+++ b/chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.h"
 
+#include "base/containers/contains.h"
 #include "base/time/time.h"
 #include "components/sync/invalidations/fcm_handler.h"
-#include "components/sync/protocol/sync_invalidations_payload.pb.h"
 
 namespace fake_server {
 
@@ -19,15 +19,38 @@
 }  // namespace
 
 FakeServerSyncInvalidationSender::FakeServerSyncInvalidationSender(
-    FakeServer* fake_server,
-    const std::vector<syncer::FCMHandler*>& fcm_handlers)
-    : fake_server_(fake_server), fcm_handlers_(fcm_handlers) {
+    FakeServer* fake_server)
+    : fake_server_(fake_server) {
   DCHECK(fake_server_);
   fake_server_->AddObserver(this);
 }
 
 FakeServerSyncInvalidationSender::~FakeServerSyncInvalidationSender() {
   fake_server_->RemoveObserver(this);
+
+  // Unsubscribe from all the remaining FCM handlers. This is mostly the case
+  // for Android platform.
+  for (syncer::FCMHandler* fcm_handler : fcm_handlers_) {
+    fcm_handler->RemoveTokenObserver(this);
+  }
+}
+
+void FakeServerSyncInvalidationSender::AddFCMHandler(
+    syncer::FCMHandler* fcm_handler) {
+  DCHECK(fcm_handler);
+  DCHECK(!base::Contains(fcm_handlers_, fcm_handler));
+
+  fcm_handlers_.push_back(fcm_handler);
+  fcm_handler->AddTokenObserver(this);
+}
+
+void FakeServerSyncInvalidationSender::RemoveFCMHandler(
+    syncer::FCMHandler* fcm_handler) {
+  DCHECK(fcm_handler);
+  DCHECK(base::Contains(fcm_handlers_, fcm_handler));
+
+  fcm_handler->RemoveTokenObserver(this);
+  base::Erase(fcm_handlers_, fcm_handler);
 }
 
 void FakeServerSyncInvalidationSender::OnCommit(
@@ -35,21 +58,17 @@
     syncer::ModelTypeSet committed_model_types) {
   const std::map<std::string, syncer::ModelTypeSet>
       token_to_interested_data_types_map = GetTokenToInterestedDataTypesMap();
-  // Pass a message to each FCMHandler to simulate a message from the
-  // GCMDriver.
-  // TODO(crbug.com/1082115): Implement reflection blocking.
-  for (syncer::FCMHandler* fcm_handler : fcm_handlers_) {
-    const std::string& token = fcm_handler->GetFCMRegistrationToken();
-    if (!token_to_interested_data_types_map.count(token)) {
-      continue;
-    }
+
+  for (const auto& token_and_data_types : token_to_interested_data_types_map) {
+    const std::string& token = token_and_data_types.first;
 
     // Send the invalidation only for interested types.
-    const syncer::ModelTypeSet invalidated_data_types = Intersection(
-        committed_model_types, token_to_interested_data_types_map.at(token));
+    const syncer::ModelTypeSet invalidated_data_types =
+        Intersection(committed_model_types, token_and_data_types.second);
     if (invalidated_data_types.Empty()) {
       continue;
     }
+
     sync_pb::SyncInvalidationsPayload payload;
     for (const syncer::ModelType data_type : invalidated_data_types) {
       payload.add_data_type_invalidations()->set_data_type_id(
@@ -61,10 +80,14 @@
     payload.set_version(base::Time::Now().ToJavaTime());
     payload.set_hint("hint");
 
-    gcm::IncomingMessage message;
-    message.raw_data = payload.SerializeAsString();
-    fcm_handler->OnMessage(kSyncInvalidationsAppId, message);
+    invalidations_to_deliver_[token].push_back(std::move(payload));
   }
+
+  DeliverInvalidationsToHandlers();
+}
+
+void FakeServerSyncInvalidationSender::OnFCMRegistrationTokenChanged() {
+  DeliverInvalidationsToHandlers();
 }
 
 std::map<std::string, syncer::ModelTypeSet>
@@ -92,4 +115,36 @@
   return result;
 }
 
+void FakeServerSyncInvalidationSender::DeliverInvalidationsToHandlers() {
+  for (auto& token_and_invalidations : invalidations_to_deliver_) {
+    const std::string& token = token_and_invalidations.first;
+    // Pass a message to each FCMHandler to simulate a message from the
+    // GCMDriver.
+    // TODO(crbug.com/1082115): Implement reflection blocking.
+    syncer::FCMHandler* fcm_handler = GetFCMHandlerByToken(token);
+    if (!fcm_handler) {
+      continue;
+    }
+
+    for (const sync_pb::SyncInvalidationsPayload& payload :
+         token_and_invalidations.second) {
+      gcm::IncomingMessage message;
+      message.raw_data = payload.SerializeAsString();
+      fcm_handler->OnMessage(kSyncInvalidationsAppId, message);
+    }
+
+    token_and_invalidations.second.clear();
+  }
+}
+
+syncer::FCMHandler* FakeServerSyncInvalidationSender::GetFCMHandlerByToken(
+    const std::string& fcm_registration_token) const {
+  for (syncer::FCMHandler* fcm_handler : fcm_handlers_) {
+    if (fcm_registration_token == fcm_handler->GetFCMRegistrationToken()) {
+      return fcm_handler;
+    }
+  }
+  return nullptr;
+}
+
 }  // namespace fake_server
diff --git a/chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.h b/chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.h
index 03c25df..acf8de2e 100644
--- a/chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.h
+++ b/chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.h
@@ -7,6 +7,8 @@
 
 #include "base/memory/raw_ptr.h"
 #include "components/sync/base/model_type.h"
+#include "components/sync/invalidations/fcm_registration_token_observer.h"
+#include "components/sync/protocol/sync_invalidations_payload.pb.h"
 #include "components/sync/test/fake_server/fake_server.h"
 
 namespace syncer {
@@ -18,28 +20,55 @@
 // This class is observing changes to the fake server, and sends invalidations
 // to clients upon commits. Sent invalidation follows the same format expected
 // by the sync invalidations framework (i.e. SyncInvalidationsService).
-class FakeServerSyncInvalidationSender : public FakeServer::Observer {
+class FakeServerSyncInvalidationSender
+    : public FakeServer::Observer,
+      public syncer::FCMRegistrationTokenObserver {
  public:
   // |fake_server| must not be nullptr, and must outlive this object.
-  FakeServerSyncInvalidationSender(
-      FakeServer* fake_server,
-      const std::vector<syncer::FCMHandler*>& fcm_handlers);
+  explicit FakeServerSyncInvalidationSender(FakeServer* fake_server);
   ~FakeServerSyncInvalidationSender() override;
   FakeServerSyncInvalidationSender(const FakeServerSyncInvalidationSender&) =
       delete;
   FakeServerSyncInvalidationSender& operator=(
       const FakeServerSyncInvalidationSender&) = delete;
 
+  // |fcm_handler| must not be nullptr, and must be removed using
+  // RemoveFCMHandler(). If the FCM handler has registered token, all the
+  // message for the token will be delivered immediately.
+  void AddFCMHandler(syncer::FCMHandler* fcm_handler);
+
+  // |fcm_handler| must not be nullptr, and must exist in |fcm_handlers_|.
+  void RemoveFCMHandler(syncer::FCMHandler* fcm_handler);
+
   // FakeServer::Observer implementation.
   void OnCommit(const std::string& committer_invalidator_client_id,
                 syncer::ModelTypeSet committed_model_types) override;
 
+  // syncer::FCMRegistrationTokenObserver implementation.
+  void OnFCMRegistrationTokenChanged() override;
+
  private:
   std::map<std::string, syncer::ModelTypeSet>
   GetTokenToInterestedDataTypesMap();
 
+  // Returns a corresponding FCM handler having the same
+  // |fcm_registration_token| if exists. Otherwise, returns nullptr.
+  syncer::FCMHandler* GetFCMHandlerByToken(
+      const std::string& fcm_registration_token) const;
+
+  // Delivers all the incoming messages to the corresponding FCM handlers.
+  // Messages for FCM tokens which are not registered will be kept.
+  void DeliverInvalidationsToHandlers();
+
   raw_ptr<FakeServer> fake_server_;
   std::vector<syncer::FCMHandler*> fcm_handlers_;
+
+  // Cache of invalidations to be dispatched by
+  // DeliverInvalidationsToHandlers(), keyed by FCM registration token. If no
+  // handler is registered for a token, then the corresponding invalidations
+  // will remain here until a handler is added.
+  std::map<std::string, std::vector<sync_pb::SyncInvalidationsPayload>>
+      invalidations_to_deliver_;
 };
 
 }  // namespace fake_server
diff --git a/chrome/browser/sync/test/integration/password_manager_sync_test.cc b/chrome/browser/sync/test/integration/password_manager_sync_test.cc
index 33150cc..b216381 100644
--- a/chrome/browser/sync/test/integration/password_manager_sync_test.cc
+++ b/chrome/browser/sync/test/integration/password_manager_sync_test.cc
@@ -48,10 +48,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "components/signin/public/base/signin_switches.h"
-#endif
-
 namespace {
 
 using testing::ElementsAre;
@@ -94,11 +90,8 @@
     // updating a password become flaky.
     feature_list_.InitWithFeatures(
         {
-          password_manager::features::kEnablePasswordsAccountStorage,
-              password_manager::features::kFillOnAccountSelect,
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-              switches::kLacrosNonSyncingProfiles,
-#endif
+            password_manager::features::kEnablePasswordsAccountStorage,
+            password_manager::features::kFillOnAccountSelect,
         },
         {});
   }
diff --git a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
index 41a00f65..49d7d033 100644
--- a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
@@ -5,7 +5,6 @@
 #include "base/callback_list.h"
 #include "base/files/file_util.h"
 #include "base/path_service.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -21,10 +20,6 @@
 #include "components/sync/driver/sync_service_impl.h"
 #include "content/public/test/browser_test.h"
 
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "components/signin/public/base/signin_switches.h"
-#endif
-
 namespace {
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
@@ -72,11 +67,6 @@
   Profile* profile() { return GetProfile(0); }
 
  private:
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  base::test::ScopedFeatureList feature_list_{
-      switches::kLacrosNonSyncingProfiles};
-#endif
-
   base::CallbackListSubscription test_signin_client_subscription_;
 };
 
diff --git a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
index bbcf676..4d2fc5f3 100644
--- a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
@@ -5,7 +5,6 @@
 #include "base/feature_list.h"
 #include "base/files/file_util.h"
 #include "base/path_service.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -16,7 +15,6 @@
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/common/chrome_paths.h"
 #include "components/send_tab_to_self/features.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/driver/glue/sync_transport_data_prefs.h"
 #include "components/sync/driver/sync_service_impl.h"
@@ -76,12 +74,6 @@
  public:
   SingleClientStandaloneTransportSyncTest() : SyncTest(SINGLE_CLIENT) {}
   ~SingleClientStandaloneTransportSyncTest() override = default;
-
- private:
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
-#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 };
 
 // On Chrome OS sync auto-starts on sign-in.
diff --git a/chrome/browser/sync/test/integration/single_client_wifi_configuration_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wifi_configuration_sync_test.cc
index 2a53ec6..508da9d2 100644
--- a/chrome/browser/sync/test/integration/single_client_wifi_configuration_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_wifi_configuration_sync_test.cc
@@ -15,7 +15,7 @@
 #include "chromeos/components/sync_wifi/network_identifier.h"
 #include "chromeos/components/sync_wifi/test_data_generator.h"
 #include "chromeos/dbus/shill/shill_profile_client.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "components/sync/engine/loopback_server/persistent_unique_client_entity.h"
 #include "components/sync/nigori/cryptographer_impl.h"
 #include "components/sync/nigori/nigori_test_utils.h"
@@ -62,7 +62,7 @@
 // becomes locally available.
 class LocalWifiConfigurationChecker
     : public StatusChangeChecker,
-      public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+      public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   LocalWifiConfigurationChecker(
       mojo::Remote<chromeos::network_config::mojom::CrosNetworkConfig>*
@@ -94,17 +94,6 @@
                            weak_ptr_factory_.GetWeakPtr()));
   }
 
-  void OnActiveNetworksChanged(
-      std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
-          networks) override {}
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
-      override {}
-  void OnDeviceStateListChanged() override {}
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
-
   // StatusChangeChecker implementation.
   bool IsExitConditionSatisfied(std::ostream* os) override {
     *os << "Waiting for network with ssid: " << expected_ssid_;
diff --git a/chrome/browser/sync/test/integration/sync_service_impl_harness.cc b/chrome/browser/sync/test/integration/sync_service_impl_harness.cc
index bf702646..8c90b66 100644
--- a/chrome/browser/sync/test/integration/sync_service_impl_harness.cc
+++ b/chrome/browser/sync/test/integration/sync_service_impl_harness.cc
@@ -106,18 +106,7 @@
     if (HasAuthError(service())) {
       return true;
     }
-    // TODO(crbug.com/1010397): The verification of INITIALIZING is only needed
-    // due to SyncEncryptionHandlerImpl issuing an unnecessary
-    // OnPassphraseRequired() during initialization.
-    if (service()
-            ->GetUserSettings()
-            ->IsPassphraseRequiredForPreferredDataTypes() &&
-        transport_state != syncer::SyncService::TransportState::INITIALIZING) {
-      LOG(FATAL)
-          << "A passphrase is required for decryption but was not provided. "
-             "Waiting for sync to become available won't succeed. Make sure "
-             "to pass it when setting up sync.";
-    }
+
     // Still waiting on sync setup.
     return false;
   }
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index d0cf9d2..5819e074 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -13,6 +13,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/path_service.h"
 #include "base/rand_util.h"
 #include "base/ranges/algorithm.h"
@@ -74,6 +75,7 @@
 #include "components/sync/driver/sync_service_impl.h"
 #include "components/sync/driver/sync_user_settings.h"
 #include "components/sync/engine/sync_scheduler_impl.h"
+#include "components/sync/invalidations/fcm_handler.h"
 #include "components/sync/invalidations/sync_invalidations_service_impl.h"
 #include "components/sync/test/fake_server/fake_server_network_resources.h"
 #include "content/public/browser/navigation_entry.h"
@@ -512,8 +514,16 @@
   for (size_t i = 0; i < browsers_.size(); ++i) {
     if (browsers_[i] == browser) {
       browsers_[i] = nullptr;
+      break;
     }
   }
+
+  if (fake_server_sync_invalidation_sender_ &&
+      base::Contains(profile_to_fcm_handler_map_, browser->profile())) {
+    fake_server_sync_invalidation_sender_->RemoveFCMHandler(
+        profile_to_fcm_handler_map_[browser->profile()]);
+    profile_to_fcm_handler_map_.erase(browser->profile());
+  }
 }
 #endif
 
@@ -651,13 +661,6 @@
   }
 #endif
 
-  // Create the fake server sync invalidations sender.
-  if (server_type_ == IN_PROCESS_FAKE_SERVER) {
-    fake_server_sync_invalidation_sender_ =
-        std::make_unique<fake_server::FakeServerSyncInvalidationSender>(
-            GetFakeServer(), sync_invalidations_fcm_handlers_);
-  }
-
   LOG(INFO)
       << "SyncTest::SetupClients() completed; elapsed time since construction: "
       << (base::Time::Now() - test_construction_time_);
@@ -955,6 +958,7 @@
              observer : fake_server_invalidation_observers_) {
       fake_server_->RemoveObserver(observer.get());
     }
+    profile_to_fcm_handler_map_.clear();
     fake_server_sync_invalidation_sender_.reset();
     fake_server_.reset();
   }
@@ -962,7 +966,7 @@
   // Delete things that unsubscribe in destructor before their targets are gone.
   configuration_refresher_.reset();
 
-  // Note: Closing all the browsers (see below) may destroy the Profiles, if
+  // Note: Closing all the browsers (see above) may destroy the Profiles, if
   // kDestroyProfileOnBrowserClose is enabled. So clear them out here, to make
   // sure they're not used anymore.
   profiles_.clear();
@@ -981,6 +985,7 @@
   }
   browsers_.clear();
 #endif
+
   PlatformBrowserTest::TearDownOnMainThread();
 }
 
@@ -1008,8 +1013,7 @@
                               &profile_to_instance_id_driver_map_));
   SyncInvalidationsServiceFactory::GetInstance()->SetTestingFactory(
       context, base::BindRepeating(&SyncTest::CreateSyncInvalidationsService,
-                                   &profile_to_instance_id_driver_map_,
-                                   &sync_invalidations_fcm_handlers_));
+                                   base::Unretained(this)));
   gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactory(
       context, base::BindRepeating(&FakeSyncGCMDriver::Build));
 }
@@ -1053,11 +1057,7 @@
           }));
 }
 
-// static
 std::unique_ptr<KeyedService> SyncTest::CreateSyncInvalidationsService(
-    std::map<const Profile*, std::unique_ptr<instance_id::InstanceIDDriver>>*
-        profile_to_instance_id_driver_map,
-    std::vector<syncer::FCMHandler*>* sync_invalidations_fcm_handlers,
     content::BrowserContext* context) {
   if (!base::FeatureList::IsEnabled(syncer::kSyncSendInterestedDataTypes)) {
     return nullptr;
@@ -1068,12 +1068,19 @@
   gcm::GCMDriver* gcm_driver =
       gcm::GCMProfileServiceFactory::GetForProfile(profile)->driver();
   instance_id::InstanceIDDriver* instance_id_driver =
-      GetOrCreateInstanceIDDriver(profile, profile_to_instance_id_driver_map);
+      GetOrCreateInstanceIDDriver(profile, &profile_to_instance_id_driver_map_);
   auto service = std::make_unique<syncer::SyncInvalidationsServiceImpl>(
       gcm_driver, instance_id_driver);
 
-  sync_invalidations_fcm_handlers->push_back(
-      service->GetFCMHandlerForTesting());
+  // If |fake_server_sync_invalidation_sender_| hasn't been created yet, it's
+  // likely for the profile which is used only on Android. Created FCM
+  // handlers will be added later once |fake_server_sync_invalidation_sender_|
+  // is initialized.
+  profile_to_fcm_handler_map_[profile] = service->GetFCMHandlerForTesting();
+  if (fake_server_sync_invalidation_sender_) {
+    fake_server_sync_invalidation_sender_->AddFCMHandler(
+        service->GetFCMHandlerForTesting());
+  }
 
   return std::move(service);
 }
@@ -1244,6 +1251,16 @@
     base::FilePath user_data_dir;
     base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
     fake_server_ = std::make_unique<fake_server::FakeServer>(user_data_dir);
+    fake_server_sync_invalidation_sender_ =
+        std::make_unique<fake_server::FakeServerSyncInvalidationSender>(
+            fake_server_.get());
+
+    // Subscribe to invalidations for all the profiles which were created
+    // before. This is mainly the case on Android platform.
+    for (const auto& profile_and_fcm_handler : profile_to_fcm_handler_map_) {
+      fake_server_sync_invalidation_sender_->AddFCMHandler(
+          profile_and_fcm_handler.second);
+    }
     SetupMockGaiaResponses();
   } else {
     LOG(FATAL) << "Don't know which server environment to run test in.";
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h
index e59c10dc4..c7612f49 100644
--- a/chrome/browser/sync/test/integration/sync_test.h
+++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -72,6 +72,7 @@
 }  // namespace fake_server
 
 namespace syncer {
+class FCMHandler;
 class SyncServiceImpl;
 }  // namespace syncer
 
@@ -299,6 +300,10 @@
   // be provided to the client during initialization, before Sync starts. It is
   // an error to provide both a decryption and encryption passphrases for one
   // client.
+  // TODO(crbug.com/1338480): this and below are overused, most tests can use
+  // SyncUserSettings interface. Avoid usages, reintroduce logic in specific
+  // test that actually need it (if exists) and remove these functions together
+  // with relevant SyncTest SetupSync() code.
   void SetDecryptionPassphraseForClient(int index,
                                         const std::string& passphrase);
 
@@ -346,10 +351,7 @@
           profile_to_instance_id_driver_map,
       content::BrowserContext* context);
 
-  static std::unique_ptr<KeyedService> CreateSyncInvalidationsService(
-      std::map<const Profile*, std::unique_ptr<instance_id::InstanceIDDriver>>*
-          profile_to_instance_id_driver_map,
-      std::vector<syncer::FCMHandler*>* sync_invalidations_fcm_handlers,
+  std::unique_ptr<KeyedService> CreateSyncInvalidationsService(
       content::BrowserContext* context);
 
 #if !BUILDFLAG(IS_ANDROID)
@@ -474,6 +476,8 @@
   std::map<const Profile*, std::unique_ptr<instance_id::InstanceIDDriver>>
       profile_to_instance_id_driver_map_;
 
+  std::map<const Profile*, syncer::FCMHandler*> profile_to_fcm_handler_map_;
+
   // Triggers a GetUpdates via refresh after a configuration.
   std::unique_ptr<ConfigurationRefresher> configuration_refresher_;
 
@@ -505,7 +509,6 @@
       model_updater_factory_;
 #endif
 
-  std::vector<syncer::FCMHandler*> sync_invalidations_fcm_handlers_;
   std::unique_ptr<fake_server::FakeServerSyncInvalidationSender>
       fake_server_sync_invalidation_sender_;
 };
diff --git a/chrome/browser/tab/BUILD.gn b/chrome/browser/tab/BUILD.gn
index 8962660..21a38cda 100644
--- a/chrome/browser/tab/BUILD.gn
+++ b/chrome/browser/tab/BUILD.gn
@@ -32,6 +32,7 @@
     "java/src/org/chromium/chrome/browser/tab/TrustedCdn.java",
     "java/src/org/chromium/chrome/browser/tab/WebContentsState.java",
     "java/src/org/chromium/chrome/browser/tab/WebContentsStateBridge.java",
+    "java/src/org/chromium/chrome/browser/tab/state/CouponPersistedTabData.java",
     "java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java",
     "java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataObserver.java",
     "java/src/org/chromium/chrome/browser/tab/state/EmptyByteBufferPersistedTabDataStorage.java",
@@ -134,6 +135,7 @@
 proto_java_library("critical_persisted_tab_data_proto_java") {
   proto_path = "java/src/org/chromium/chrome/browser/tab/state/proto"
   sources = [
+    "$proto_path/coupon_persisted_tab_data.proto",
     "$proto_path/critical_persisted_tab_data.proto",
     "$proto_path/shopping_persisted_tab_data.proto",
     "$proto_path/store_persisted_tab_data.proto",
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CouponPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CouponPersistedTabData.java
new file mode 100644
index 0000000..ee03c63a
--- /dev/null
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CouponPersistedTabData.java
@@ -0,0 +1,103 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tab.state;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.Callback;
+import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.tab.Tab;
+
+import java.nio.ByteBuffer;
+
+/**
+ * {@link PersistedTabData} for Shopping websites with coupons.
+ *
+ * TODO(crbug.com/1335109): Implement service integration for CouponPersistedTabData
+ * TODO(crbug.com/1337120): Implement prefetching for CouponPersistedTabData
+ * TODO(crbug.com/1337124): Implement clearing CouponPersistedTabData upon new navigation
+ */
+public class CouponPersistedTabData extends PersistedTabData {
+    private static final String TAG = "COPTD";
+    private Coupon mCoupon;
+
+    /**
+     * Acquire {@link CouponPersistedTabData} for a {@link Tab}
+     * @param tab {@link Tab} CouponPersistedTabData is created for
+     * @param coupon {@link Coupon} for the website open in this tab
+     */
+    CouponPersistedTabData(Tab tab, Coupon coupon) {
+        this(tab);
+        mCoupon = coupon;
+    }
+
+    /**
+     * Acquire {@link CouponPersistedTabData} for a {@link Tab}
+     * @param tab {@link Tab} CouponPersistedTabData is created for
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+    public CouponPersistedTabData(Tab tab) {
+        super(tab,
+                PersistedTabDataConfiguration.get(CouponPersistedTabData.class, tab.isIncognito())
+                        .getStorage(),
+                PersistedTabDataConfiguration.get(CouponPersistedTabData.class, tab.isIncognito())
+                        .getId());
+    }
+
+    /**
+     * Coupon data type for {@link CouponPersistedTabData}
+     */
+    public static class Coupon {
+        public String couponName;
+        public String promoCode;
+
+        /**
+         * @param name name of coupon
+         * @param code promotional code relating to coupon
+         */
+        public Coupon(String name, String code) {
+            couponName = name;
+            promoCode = code;
+        }
+    }
+
+    /**
+     * @return {@link Coupon} relating to the main offer in the page, if available
+     */
+    public Coupon getCoupon() {
+        if (mCoupon.promoCode.isEmpty()) {
+            return null;
+        }
+        return mCoupon;
+    }
+
+    // TODO(crbug.com/1337470): Implement deserialize & serialize methods.
+    @Override
+    Supplier<ByteBuffer> getSerializeSupplier() {
+        return () -> null;
+    }
+
+    @Override
+    boolean deserialize(@Nullable ByteBuffer bytes) {
+        return false;
+    }
+
+    @Override
+    public String getUmaTag() {
+        return TAG;
+    }
+
+    /**
+     * Acquire {@link CouponPersistedTabData} for a {@link Tab}
+     * @param tab {@link Tab} that {@link CouponPersistedTabData} is acquired for
+     * @param callback {@link Callback} that {@link CouponPersistedTabData} is passed back in
+     */
+    public static void from(Tab tab, Callback<CouponPersistedTabData> callback) {
+        // An empty string as the code field will return a null coupon when calling getCoupon()
+        // so the UI will always be turned off until this method has been further implemented.
+        callback.onResult(new CouponPersistedTabData(tab, new Coupon("Test", "")));
+    }
+}
\ No newline at end of file
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataConfiguration.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataConfiguration.java
index 51fd432..9a1f0d0c 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataConfiguration.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataConfiguration.java
@@ -20,6 +20,7 @@
     ENCRYPTED_CRITICAL_PERSISTED_TAB_DATA("ECPTDFB"),
     MOCK_PERSISTED_TAB_DATA("MPTD"),
     ENCRYPTED_MOCK_PERSISTED_TAB_DATA("EMPTD"),
+    COUPON_PERSISTED_TAB_DATA("COPTD"),
     SHOPPING_PERSISTED_TAB_DATA("SPTD"),
     STORE_PERSISTED_TAB_DATA("STPTD"),
     EMPTY_BYTE_BUFFER_TEST_CONFIG("EBBTC"),
@@ -73,6 +74,8 @@
 
     static {
         // TODO(crbug.com/1060187) remove static initializer and initialization lazy
+        sLookup.put(CouponPersistedTabData.class, COUPON_PERSISTED_TAB_DATA);
+        sEncryptedLookup.put(CouponPersistedTabData.class, COUPON_PERSISTED_TAB_DATA);
         sLookup.put(CriticalPersistedTabData.class, CRITICAL_PERSISTED_TAB_DATA);
         sEncryptedLookup.put(CriticalPersistedTabData.class, ENCRYPTED_CRITICAL_PERSISTED_TAB_DATA);
         sLookup.put(MockPersistedTabData.class, MOCK_PERSISTED_TAB_DATA);
@@ -82,6 +85,8 @@
         sLookup.put(StorePersistedTabData.class, STORE_PERSISTED_TAB_DATA);
         sEncryptedLookup.put(StorePersistedTabData.class, STORE_PERSISTED_TAB_DATA);
 
+        COUPON_PERSISTED_TAB_DATA.mStorageFactory = new LevelDBPersistedTabDataStorageFactory();
+
         CRITICAL_PERSISTED_TAB_DATA.mStorageFactory = () -> {
             return getFilePersistedTabDataStorage();
         };
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/proto/coupon_persisted_tab_data.proto b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/proto/coupon_persisted_tab_data.proto
new file mode 100644
index 0000000..42ebd5f
--- /dev/null
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/proto/coupon_persisted_tab_data.proto
@@ -0,0 +1,17 @@
+// 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.
+
+syntax = "proto2";
+
+package org.chromium.chrome.browser.tab.proto;
+
+option java_package = "org.chromium.chrome.browser.tab.proto";
+
+message CouponPersistedTabDataProto {
+  // String representing the name of the coupon.
+  optional string name = 1;
+
+  // String representing the promotional code related to the coupon.
+  optional string code = 2;
+}
\ No newline at end of file
diff --git a/chrome/browser/translate/android/translate_bridge.cc b/chrome/browser/translate/android/translate_bridge.cc
index 5812faa..a471678 100644
--- a/chrome/browser/translate/android/translate_bridge.cc
+++ b/chrome/browser/translate/android/translate_bridge.cc
@@ -224,25 +224,6 @@
   return translate_prefs->IsBlockedLanguage(language_code);
 }
 
-// Gets all the model languages and calls back to the Java
-// TranslateBridge#addModelLanguageToSet once for each language.
-static ScopedJavaLocalRef<jobjectArray> JNI_TranslateBridge_GetModelLanguages(
-    JNIEnv* env) {
-  Profile* profile = ProfileManager::GetActiveUserProfile();
-  language::LanguageModel* language_model =
-      LanguageModelManagerFactory::GetForBrowserContext(profile)
-          ->GetPrimaryModel();
-  DCHECK(language_model);
-  std::vector<language::LanguageModel::LanguageDetails> languageDetails =
-      language_model->GetLanguages();
-  DCHECK(!languageDetails.empty());
-  std::vector<std::string> model_languages;
-  for (const auto& details : languageDetails) {
-    model_languages.push_back(details.lang_code);
-  }
-  return ToJavaArrayOfStrings(env, model_languages);
-}
-
 // Gets all languages that should always be translated as a Java List.
 static ScopedJavaLocalRef<jobjectArray>
 JNI_TranslateBridge_GetAlwaysTranslateLanguages(JNIEnv* env) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 8611881e..899edba4 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3142,6 +3142,8 @@
       "//chromeos/ash/components/dbus/spaced",
       "//chromeos/ash/components/dbus/system_clock",
       "//chromeos/ash/components/dbus/upstart",
+      "//chromeos/ash/components/dbus/userdataauth",
+      "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
       "//chromeos/ash/components/human_presence",
       "//chromeos/ash/components/network/portal_detector",
       "//chromeos/ash/components/oobe_quick_start",
@@ -3169,8 +3171,6 @@
       "//chromeos/dbus/tpm_manager",
       "//chromeos/dbus/tpm_manager:tpm_manager_proto",
       "//chromeos/dbus/update_engine",
-      "//chromeos/dbus/userdataauth",
-      "//chromeos/dbus/userdataauth:userdataauth_proto",
       "//chromeos/dbus/util",
       "//chromeos/login/login_state",
       "//chromeos/network",
@@ -3181,6 +3181,7 @@
       "//chromeos/services/bluetooth_config",
       "//chromeos/services/bluetooth_config:in_process_bluetooth_config",
       "//chromeos/services/bluetooth_config/public/mojom",
+      "//chromeos/services/network_config/public/cpp",
       "//chromeos/services/network_config/public/mojom",
       "//chromeos/services/network_health/public/mojom",
       "//chromeos/system",
@@ -3750,6 +3751,7 @@
 
     deps += [
       "//chrome/browser/apps/app_shim",
+      "//chrome/updater:browser_sources",
       "//components/remote_cocoa/app_shim",
       "//components/remote_cocoa/browser",
       "//extensions/components/native_app_window",
@@ -3765,10 +3767,7 @@
     weak_frameworks = [ "ScreenTime.framework" ]
 
     if (enable_chromium_updater) {
-      deps += [
-        "//chrome/browser/updater:browser_updater_client",
-        "//chrome/updater:browser_sources",
-      ]
+      deps += [ "//chrome/browser/updater:browser_updater_client" ]
     }
   }
 
@@ -3993,20 +3992,27 @@
     ]
   }
 
-  if (is_linux || is_chromeos) {  # Both desktop Linux and ChromeOS.
+  if (enable_webui_certificate_viewer) {
     sources += [
       "certificate_dialogs.cc",
       "certificate_dialogs.h",
-      "process_singleton_dialog_linux.h",
       "webui/certificate_viewer_ui.cc",
       "webui/certificate_viewer_ui.h",
       "webui/certificate_viewer_webui.cc",
       "webui/certificate_viewer_webui.h",
+    ]
+    deps += [ "//third_party/boringssl" ]
+    if (use_nss_certs) {
+      configs += [ "//build/config/linux/nss" ]
+    }
+  }
+
+  if (is_linux || is_chromeos) {
+    sources += [
+      "process_singleton_dialog_linux.h",
       "webui/webui_js_error/webui_js_error_ui.cc",
       "webui/webui_js_error/webui_js_error_ui.h",
     ]
-    deps += [ "//third_party/boringssl" ]
-    configs += [ "//build/config/linux/nss" ]
     if (use_aura) {
       deps += [ "//third_party/fontconfig" ]
     }
@@ -4084,6 +4090,7 @@
       "side_search/side_search_tab_contents_helper.h",
       "side_search/side_search_utils.cc",
       "side_search/side_search_utils.h",
+      "side_search/unified_side_search_helper.h",
       "sync/one_click_signin_links_delegate.h",
       "sync/one_click_signin_links_delegate_impl.cc",
       "sync/one_click_signin_links_delegate_impl.h",
@@ -4830,6 +4837,9 @@
       "views/side_search/side_search_browser_controller.h",
       "views/side_search/side_search_icon_view.cc",
       "views/side_search/side_search_icon_view.h",
+      "views/side_search/unified_side_search_controller.cc",
+      "views/side_search/unified_side_search_controller.h",
+      "views/side_search/unified_side_search_helper.cc",
       "views/ssl_client_certificate_selector.cc",
       "views/ssl_client_certificate_selector.h",
       "views/status_bubble_views.cc",
@@ -5135,7 +5145,6 @@
     }
     if (is_fuchsia) {
       sources += [
-        "views/certificate_viewer_fuchsia.cc",
         "views/chrome_views_delegate_fuchsia.cc",
         "views/frame/browser_desktop_window_tree_host.h",
         "views/frame/browser_desktop_window_tree_host_fuchsia.cc",
diff --git a/chrome/browser/ui/android/logo/BUILD.gn b/chrome/browser/ui/android/logo/BUILD.gn
index 40547d5..250b2c5 100644
--- a/chrome/browser/ui/android/logo/BUILD.gn
+++ b/chrome/browser/ui/android/logo/BUILD.gn
@@ -55,28 +55,10 @@
   deps = [ "//chrome/browser/ui/android/strings:ui_strings_grd" ]
 }
 
-android_library("javatests") {
-  testonly = true
-  sources = [ "java/src/org/chromium/chrome/browser/logo/LogoViewTest.java" ]
-
-  deps = [
-    ":java",
-    "//base:base_java_test_support",
-    "//chrome/browser/search_engines/android:java",
-    "//chrome/test/android:chrome_java_unit_test_support",
-    "//components/search_engines/android:java",
-    "//content/public/android:content_full_java",
-    "//content/public/test/android:content_java_test_support",
-    "//third_party/androidx:androidx_test_runner_java",
-    "//third_party/junit:junit",
-    "//third_party/mockito:mockito_java",
-    "//ui/android:ui_java_test_support",
-  ]
-}
-
 robolectric_library("junit") {
   sources = [
     "java/src/org/chromium/chrome/browser/logo/LogoLoadHelperUnitTest.java",
+    "java/src/org/chromium/chrome/browser/logo/LogoViewTest.java",
   ]
 
   deps = [
@@ -95,5 +77,6 @@
     "//third_party/androidx:androidx_test_core_java",
     "//third_party/junit:junit",
     "//third_party/mockito:mockito_java",
+    "//ui/android:ui_java_test_support",
   ]
 }
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewTest.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewTest.java
index c997bbbf..9c31c74 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewTest.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewTest.java
@@ -8,38 +8,31 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import android.app.Activity;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.text.TextUtils;
 import android.view.ViewGroup.LayoutParams;
 
-import androidx.test.filters.SmallTest;
+import androidx.test.core.app.ActivityScenario;
 
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
+import org.mockito.MockitoAnnotations;
 
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.logo.LogoBridge.Logo;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.components.search_engines.TemplateUrlService;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.ui.test.util.BlankUiTestActivityTestCase;
+import org.chromium.ui.base.TestActivity;
 
 /** Instrumentation tests for {@link LogoView}. */
-@RunWith(BaseJUnit4ClassRunner.class)
-@Batch(Batch.UNIT_TESTS)
-public class LogoViewTest extends BlankUiTestActivityTestCase {
-    @Rule
-    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+@RunWith(BaseRobolectricTestRunner.class)
+public class LogoViewTest {
     @Mock
     public TemplateUrlService mTemplateUrlService;
     @Mock
@@ -50,19 +43,22 @@
             "https://www.gstatic.com/chrome/ntp/doodle_test/ddljson_android4.json";
     private static final String ALT_TEXT = "Hello World!";
 
+    private ActivityScenario<TestActivity> mActivityScenario;
     private LogoView mView;
     private Bitmap mBitmap;
 
     @Before
     public void setup() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Activity activity = getActivity();
+        MockitoAnnotations.initMocks(this);
+        mActivityScenario = ActivityScenario.launch(TestActivity.class);
+        mBitmap = Bitmap.createBitmap(1, 1, Config.ALPHA_8);
+        TemplateUrlServiceFactory.setInstanceForTesting(mTemplateUrlService);
+
+        mActivityScenario.onActivity(activity -> {
             mView = new LogoView(activity, null);
-            mBitmap = Bitmap.createBitmap(1, 1, Config.ALPHA_8);
             LayoutParams params =
                     new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
-            TemplateUrlServiceFactory.setInstanceForTesting(mTemplateUrlService);
-            getActivity().setContentView(mView, params);
+            activity.setContentView(mView, params);
         });
     }
 
@@ -73,13 +69,10 @@
     }
 
     @Test
-    @SmallTest
     public void testDefaultLogoView() {
         doReturn(true).when(mTemplateUrlService).isDefaultSearchEngineGoogle();
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mView.updateLogo(null);
-            mView.endAnimationsForTesting();
-        });
+        mView.updateLogo(null);
+        mView.endAnimationsForTesting();
 
         Assert.assertFalse("Default logo should not be clickable.", mView.isClickable());
         Assert.assertFalse("Default logo should not be focusable.", mView.isFocusable());
@@ -88,13 +81,10 @@
     }
 
     @Test
-    @SmallTest
     public void testLogoView_WithUrl() {
         Logo logo = new Logo(mBitmap, LOGO_URL, null, null);
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mView.updateLogo(logo);
-            mView.endAnimationsForTesting();
-        });
+        mView.updateLogo(logo);
+        mView.endAnimationsForTesting();
 
         Assert.assertTrue("Logo with URL should be clickable.", mView.isClickable());
         Assert.assertTrue("Logo with URL should be focusable.", mView.isFocusable());
@@ -103,13 +93,10 @@
     }
 
     @Test
-    @SmallTest
     public void testLogoView_WithAnimatedUrl() {
         Logo logo = new Logo(mBitmap, null, null, ANIMATED_LOGO_URL);
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mView.updateLogo(logo);
-            mView.endAnimationsForTesting();
-        });
+        mView.updateLogo(logo);
+        mView.endAnimationsForTesting();
 
         Assert.assertTrue("Logo with animated URL should be clickable.", mView.isClickable());
         Assert.assertTrue("Logo with animated URL should be focusable.", mView.isFocusable());
@@ -118,26 +105,20 @@
     }
 
     @Test
-    @SmallTest
     public void testLogoView_WithUrl_Clicked() {
         mView.setDelegate(mLogoDelegate);
         Logo logo = new Logo(mBitmap, LOGO_URL, null, null);
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mView.updateLogo(logo);
-            mView.endAnimationsForTesting();
-            mView.performClick();
-        });
+        mView.updateLogo(logo);
+        mView.endAnimationsForTesting();
+        mView.performClick();
         verify(mLogoDelegate, times(1)).onLogoClicked(false);
     }
 
     @Test
-    @SmallTest
     public void testLogoView_WithAltText() {
         Logo logo = new Logo(mBitmap, null, ALT_TEXT, null);
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            mView.updateLogo(logo);
-            mView.endAnimationsForTesting();
-        });
+        mView.updateLogo(logo);
+        mView.endAnimationsForTesting();
 
         Assert.assertFalse("Logo without URL should not be clickable.", mView.isClickable());
         Assert.assertTrue("Logo with alt text should be focusable.", mView.isFocusable());
diff --git a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java
index 57907ea..95646404 100644
--- a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java
+++ b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java
@@ -6,7 +6,6 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING;
@@ -26,13 +25,11 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
-import org.chromium.base.metrics.UmaRecorder;
-import org.chromium.base.metrics.UmaRecorderHolder;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.JniMocker;
@@ -79,8 +76,6 @@
     public Profile mProfile;
     @Mock
     public Tracker mTracker;
-    @Mock
-    public UmaRecorder mUmaRecorder;
 
     private ThemeSettingsFragment mFragment;
     private RadioButtonGroupThemePreference mPreference;
@@ -99,7 +94,6 @@
 
         Profile.setLastUsedProfileForTesting(mProfile);
         TrackerFactory.setTrackerForTests(mTracker);
-        UmaRecorderHolder.setNonNativeDelegate(mUmaRecorder);
 
         // Default value for feature DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING.
         mForceDarkModeEnabled = true;
@@ -121,7 +115,6 @@
             SharedPreferencesManager.getInstance().removeKey(UI_THEME_SETTING);
             Profile.setLastUsedProfileForTesting(null);
             TrackerFactory.setTrackerForTests(null);
-            UmaRecorderHolder.resetForTesting();
         });
     }
 
@@ -284,10 +277,14 @@
     }
 
     private void assertThemeSettingsEntryRecorded(int sample) {
-        ArgumentCaptor<Integer> sampleCaptor = ArgumentCaptor.forClass(Integer.class);
-        Mockito.verify(mUmaRecorder, Mockito.times(1))
-                .recordLinearHistogram(eq("Android.DarkTheme.ThemeSettingsEntry"),
-                        sampleCaptor.capture(), anyInt(), anyInt(), anyInt());
-        Assert.assertEquals(sample, sampleCaptor.getValue().intValue());
+        Assert.assertEquals("<Android.DarkTheme.ThemeSettingsEntry> should be recorded once.", 1,
+                RecordHistogram.getHistogramTotalCountForTesting(
+                        "Android.DarkTheme.ThemeSettingsEntry"));
+        Assert.assertEquals(
+                "<Android.DarkTheme.ThemeSettingsEntry> should be recorded once for sample <"
+                        + sample + ">.",
+                1,
+                RecordHistogram.getHistogramValueCountForTesting(
+                        "Android.DarkTheme.ThemeSettingsEntry", sample));
     }
 }
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetMediator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetMediator.java
index a484a463..fa2258e 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetMediator.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetMediator.java
@@ -13,6 +13,7 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.base.Callback;
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.chrome.browser.signin.services.ProfileDataCache;
 import org.chromium.chrome.browser.signin.services.SigninMetricsUtils;
 import org.chromium.chrome.browser.signin.services.SigninPreferencesManager;
@@ -27,7 +28,9 @@
 import org.chromium.components.signin.base.GoogleServiceAuthError.State;
 import org.chromium.components.signin.metrics.AccountConsistencyPromoAction;
 import org.chromium.ui.base.WindowAndroid;
+import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyObservable.PropertyObserver;
 
 import java.util.List;
 
@@ -49,6 +52,10 @@
     private @Nullable String mDefaultAccountName;
     private @Nullable String mAddedAccountName;
 
+    private final PropertyObserver<PropertyKey> mModelPropertyChangedObserver;
+    private final ObservableSupplierImpl<Boolean> mBackPressStateChangedSupplier =
+            new ObservableSupplierImpl<>();
+
     AccountPickerBottomSheetMediator(WindowAndroid windowAndroid,
             AccountPickerDelegate accountPickerDelegate, Runnable onDismissButtonClicked) {
         mWindowAndroid = windowAndroid;
@@ -59,6 +66,14 @@
         mModel = AccountPickerBottomSheetProperties.createModel(this::onSelectedAccountClicked,
                 this::onContinueAsClicked,
                 view -> onDismissButtonClicked.run(), accountPickerDelegate.getEntryPoint());
+        mModelPropertyChangedObserver = (source, propertyKey) -> {
+            if (AccountPickerBottomSheetProperties.VIEW_STATE == propertyKey) {
+                mBackPressStateChangedSupplier.set(
+                        mModel.get(AccountPickerBottomSheetProperties.VIEW_STATE)
+                        == ViewState.EXPANDED_ACCOUNT_LIST);
+            }
+        };
+        mModel.addObserver(mModelPropertyChangedObserver);
         mProfileDataCache.addObserver(this);
 
         mAccountManagerFacade = AccountManagerFacadeProvider.getInstance();
@@ -130,6 +145,11 @@
         return false;
     }
 
+    @Override
+    public ObservableSupplierImpl<Boolean> getBackPressStateChangedSupplier() {
+        return mBackPressStateChangedSupplier;
+    }
+
     /**
      * Implements {@link AccountsChangeObserver}.
      */
@@ -158,6 +178,7 @@
         mAccountPickerDelegate.destroy();
         mProfileDataCache.removeObserver(this);
         mAccountManagerFacade.removeObserver(this);
+        mModel.removeObserver(mModelPropertyChangedObserver);
     }
 
     private void updateAccounts(List<Account> accounts) {
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetView.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetView.java
index 68b1652a..799fbc7 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetView.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetView.java
@@ -18,6 +18,7 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.chrome.browser.signin.services.DisplayableProfileData;
 import org.chromium.chrome.browser.ui.signin.R;
 import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetProperties.ViewState;
@@ -42,6 +43,15 @@
          * @return true if the listener handles the back press, false if not.
          */
         boolean onBackPressed();
+
+        /**
+         * @return A supplier that determines if back press will be handled by the sheet content.
+         */
+        default ObservableSupplierImpl<Boolean> getBackPressStateChangedSupplier() {
+            ObservableSupplierImpl<Boolean> supplier = new ObservableSupplierImpl<>();
+            supplier.set(false);
+            return supplier;
+        }
     }
 
     /**
@@ -211,6 +221,16 @@
     }
 
     @Override
+    public ObservableSupplierImpl<Boolean> getBackPressStateChangedSupplier() {
+        return mBackPressListener.getBackPressStateChangedSupplier();
+    }
+
+    @Override
+    public void onBackPressed() {
+        mBackPressListener.onBackPressed();
+    }
+
+    @Override
     public int getSheetContentDescriptionStringId() {
         return R.string.signin_account_picker_bottom_sheet_subtitle;
     }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index 678d9c6..e7d186e 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2476,12 +2476,6 @@
       <message name="IDS_IPH_PWA_INSTALL_AVAILABLE_TEXT" desc="The in-product-help message for PWAs that can be installed to the device.">
         Install this app
       </message>
-      <message name="IDS_IPH_BUBBLE_ADD_TO_HOME_SCREEN" desc="The in-product-help text bubble message encouraging users to add a commonly visited webpage to the home screen.">
-        To get here quicker, add this page to your Home screen
-      </message>
-      <message name="IDS_IPH_BUBBLE_ADD_TO_HOME_SCREEN_ACCESSIBILITY" desc="The in-product-help text bubble message encouraging users to add a commonly visited webpage to the home screen. Used when a screen reader is turned. 'More options' should match TC ID 8110367050267853536.">
-        To get here quicker, add this page to your Home screen from the More options button
-      </message>
       <message name="IDS_IPH_MESSAGE_ADD_TO_HOME_SCREEN_TITLE" desc="The title of in-product-help message encouraging users to add a commonly visited webpage to the home screen.">
         Add to Home screen
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_IPH_BUBBLE_ADD_TO_HOME_SCREEN.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_IPH_BUBBLE_ADD_TO_HOME_SCREEN.png.sha1
deleted file mode 100644
index 193f6bab..0000000
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_IPH_BUBBLE_ADD_TO_HOME_SCREEN.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-714033d2719ae74fecc97d9eb8e6785e09ae7074
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_IPH_BUBBLE_ADD_TO_HOME_SCREEN_ACCESSIBILITY.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_IPH_BUBBLE_ADD_TO_HOME_SCREEN_ACCESSIBILITY.png.sha1
deleted file mode 100644
index f65a7de..0000000
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_IPH_BUBBLE_ADD_TO_HOME_SCREEN_ACCESSIBILITY.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-b5060473db376f52cdd2bd56ec55ace18a83070a
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_af.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_af.xtb
index 5534c718..7c97af8 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_af.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_af.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktiewe hulp</translation>
 <translation id="3285080554353377245">Video's oor hoe om Chrome te gebruik</translation>
 <translation id="3288003805934695103">Die bladsy herlaai</translation>
-<translation id="3290991969712132877">Voeg hierdie bladsy by jou tuisskerm deur die Meer Opsies-knoppie om vinniger hierheen te kom</translation>
 <translation id="3297344142967351106">Stembystand</translation>
 <translation id="3303414029551471755">Gaan voort om die inhoud af te laai?</translation>
 <translation id="3321367458490630980">Belangstelling is bygevoeg</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> oortjie}other{<ph name="TAB_COUNT_MANY" /> oortjies, <ph name="TAB_COUNT_INCOGNITO" /> incognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Gekoppel met USB-kabel</translation>
-<translation id="4557685098773234337">Voeg hierdie bladsy by jou tuisskerm om vinniger hierheen te kom</translation>
 <translation id="4558311620361989323">Webbladkortpaaie</translation>
 <translation id="4561730552726921821">Suksesvol geregistreer</translation>
 <translation id="4561979708150884304">Geen verbinding nie</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_am.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_am.xtb
index 051725d..52405af3 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_am.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_am.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">ንቁ እገዛ</translation>
 <translation id="3285080554353377245">Chromeን እንዴት እንደሚጠቀሙ ቪዲዮዎች</translation>
 <translation id="3288003805934695103">ገጹን እንደገና መጫን</translation>
-<translation id="3290991969712132877">በፍጥነት እዚህ ለመድረስ ከብዙ አማራጮች አዝራር ላይ ይህንን ገጽ ወደ መነሻ ገጽዎ ያክሉ</translation>
 <translation id="3297344142967351106">የድምጽ እርዳታ</translation>
 <translation id="3303414029551471755">ይዘቱን ማውረድ ይቀጥል?</translation>
 <translation id="3321367458490630980">ዝንባሌ ታክሏል</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ትር}one{<ph name="TAB_COUNT_MANY" /> ትሮች፣ <ph name="TAB_COUNT_INCOGNITO" /> ማንነት የማያሳውቅ}other{<ph name="TAB_COUNT_MANY" /> ትሮች፣ <ph name="TAB_COUNT_INCOGNITO" /> ማንነት የማያሳውቅ}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">በዩኤስቢ ገመድ ተገናኝቷል</translation>
-<translation id="4557685098773234337">በፍጥነት እዚህ ለመድረስ ይህንን ገጽ ወደ መነሻ ገጽዎ ያክሉ</translation>
 <translation id="4558311620361989323">የድረ-ገጽ አቋራጮች</translation>
 <translation id="4561730552726921821">ምዝገባው ተሳክቷል</translation>
 <translation id="4561979708150884304">ግንኙነት የለም</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb
index ce0c452..5f320d3f 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ar.xtb
@@ -438,7 +438,6 @@
 <translation id="3284510035090979597">المساعدة الاستباقية</translation>
 <translation id="3285080554353377245">‏فيديوهات حول كيفية استخدام Chrome</translation>
 <translation id="3288003805934695103">إعادة تحميل الصفحة</translation>
-<translation id="3290991969712132877">للوصول إلى هذا الموقع الإلكتروني بشكل أسرع، يمكنك إضافة هذه الصفحة إلى الشاشة الرئيسية من خلال زر "خيارات إضافية".</translation>
 <translation id="3297344142967351106">المساعَدة الصوتية</translation>
 <translation id="3303414029551471755">هل ترغب في الاستمرار في تنزيل المحتوى؟</translation>
 <translation id="3321367458490630980">تمت إضافة الاهتمام.</translation>
@@ -640,7 +639,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{علامة تبويب واحدة (<ph name="TAB_COUNT_ONE" />)}zero{<ph name="TAB_COUNT_MANY" /> علامة تبويب عادية و<ph name="TAB_COUNT_INCOGNITO" /> علامة تبويب في وضع التصفُّح المتخفي}two{علامتا تبويب عاديتان (<ph name="TAB_COUNT_MANY" />) وعلامتا تبويب في وضع التصفُّح المتخفي (<ph name="TAB_COUNT_INCOGNITO" />)}few{<ph name="TAB_COUNT_MANY" /> علامات تبويب عادية و<ph name="TAB_COUNT_INCOGNITO" /> علامات تبويب في وضع التصفُّح المتخفي}many{<ph name="TAB_COUNT_MANY" /> علامة تبويب عادية و<ph name="TAB_COUNT_INCOGNITO" /> علامة تبويب في وضع التصفُّح المتخفي}other{<ph name="TAB_COUNT_MANY" /> علامة تبويب عادية و<ph name="TAB_COUNT_INCOGNITO" /> علامة تبويب في وضع التصفُّح المتخفي}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">‏تم التوصيل باستخدام كابل USB.</translation>
-<translation id="4557685098773234337">للوصول إلى هذا الموقع الإلكتروني بشكل أسرع، يمكنك إضافة هذه الصفحة إلى الشاشة الرئيسية.</translation>
 <translation id="4558311620361989323">اختصارات صفحة الويب</translation>
 <translation id="4561730552726921821">تم التسجيل بنجاح.</translation>
 <translation id="4561979708150884304">لا يتوفّر اتصال بالإنترنت</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_as.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_as.xtb
index 2c9b8e0..83e281a 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_as.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_as.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">আগতীয়া সহায়</translation>
 <translation id="3285080554353377245">Chrome কেনেকৈ ব্যৱহাৰ কৰিব লাগে সেই সম্পৰ্কে ভিডিঅ'</translation>
 <translation id="3288003805934695103">এই পৃষ্ঠাটো পুনৰ ল’ড কৰি থকা হৈছে</translation>
-<translation id="3290991969712132877">দ্ৰুততাৰে ইয়ালৈ আহিবলৈ অধিক বিকল্পৰ বুটামৰ জৰিয়তে এই পৃষ্ঠাখন আপোনাৰ গৃহ স্ক্ৰীনত যোগ দিয়ক</translation>
 <translation id="3297344142967351106">ধ্বনিৰ সহায়ত ডিভাইচৰ ব্যৱহাৰ</translation>
 <translation id="3303414029551471755">সমলখিনি ডাউনল’ড কৰিবলৈ আগবাঢ়িবনে?</translation>
 <translation id="3321367458490630980">আগ্ৰহ যোগ দিয়া হ’ল</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> টা টেব}one{<ph name="TAB_COUNT_MANY" /> টা টেব, <ph name="TAB_COUNT_INCOGNITO" /> টা ইনক’গনিট’}other{<ph name="TAB_COUNT_MANY" /> টা টেব, <ph name="TAB_COUNT_INCOGNITO" /> টা ইনক’গনিট’}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">ইউএছবি কে’বলৰ জৰিয়তে সংযোগ কৰা হ’ল</translation>
-<translation id="4557685098773234337">দ্ৰুততাৰে ইয়ালৈ আহিবলৈ এই পৃষ্ঠাখন আপোনাৰ গৃহ স্ক্ৰীনত যোগ দিয়ক</translation>
 <translation id="4558311620361989323">ৱেবপৃষ্ঠাৰ শ্বৰ্টকাট</translation>
 <translation id="4561730552726921821">সফলভাৱে পঞ্জীয়ন কৰা হ’ল</translation>
 <translation id="4561979708150884304">ইণ্টাৰনেট নাই</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_az.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_az.xtb
index 4cc9d63..3942139 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_az.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_az.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktiv Kömək</translation>
 <translation id="3285080554353377245">Chrome'dan istifadə haqqında videolar</translation>
 <translation id="3288003805934695103">Səhifə təkrar yüklənir</translation>
-<translation id="3290991969712132877">Bura daha cəld giriş üçün bu səhifəni Daha çox seçim düyməsi ilə Əsas ekrana əlavə edin</translation>
 <translation id="3297344142967351106">Səsli yardım</translation>
 <translation id="3303414029551471755">Kontentin endirilməsinə davam etmək istəyirsiniz?</translation>
 <translation id="3321367458490630980">Maraq əlavə edilib</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> tab}other{<ph name="TAB_COUNT_MANY" /> tab, <ph name="TAB_COUNT_INCOGNITO" /> anonim}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB kabeli ilə qoşulub</translation>
-<translation id="4557685098773234337">Bura daha cəld giriş üçün bu səhifəni Əsas ekrana əlavə edin</translation>
 <translation id="4558311620361989323">Veb səhifə qısayolları</translation>
 <translation id="4561730552726921821">Qeydiyyat uğurlu oldu</translation>
 <translation id="4561979708150884304">Bağlantı yoxdur</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_be.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_be.xtb
index cc3a154..5e7fc34 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_be.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_be.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Актыўная дапамога</translation>
 <translation id="3285080554353377245">Відэа пра выкарыстанне Chrome</translation>
 <translation id="3288003805934695103">Перазагрузка старонкі</translation>
-<translation id="3290991969712132877">Каб вы маглі пераходзіць на гэты сайт хутчэй, дадайце яго на галоўны экран, выкарыстаўшы кнопку "Дадатковыя параметры"</translation>
 <translation id="3297344142967351106">Галасавая дапамога</translation>
 <translation id="3303414029551471755">Перайсці да спампоўкі змесціва?</translation>
 <translation id="3321367458490630980">Інтарэс дададзены</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> укладка}one{Укладак: <ph name="TAB_COUNT_MANY" /> (у рэжыме інкогніта: <ph name="TAB_COUNT_INCOGNITO" />)}few{Укладак: <ph name="TAB_COUNT_MANY" /> (у рэжыме інкогніта: <ph name="TAB_COUNT_INCOGNITO" />)}many{Укладак: <ph name="TAB_COUNT_MANY" /> (у рэжыме інкогніта: <ph name="TAB_COUNT_INCOGNITO" />)}other{Укладак: <ph name="TAB_COUNT_MANY" /> (у рэжыме інкогніта: <ph name="TAB_COUNT_INCOGNITO" />)}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Падключана праз кабель USB</translation>
-<translation id="4557685098773234337">Каб пераходзіць на гэты сайт хутчэй, дадайце яго на галоўны экран</translation>
 <translation id="4558311620361989323">Ярлыкі вэб-старонак</translation>
 <translation id="4561730552726921821">Рэгістрацыя завершана</translation>
 <translation id="4561979708150884304">Няма падключэння</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bg.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bg.xtb
index e9f2fa2b..741227b4 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bg.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bg.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Превантивна помощ</translation>
 <translation id="3285080554353377245">Видеоклипове за използването на Chrome</translation>
 <translation id="3288003805934695103">Презаредете страницата.</translation>
-<translation id="3290991969712132877">За да отваряте тази страница по-бързо, добавете я към началния екран чрез бутона „Още опции“</translation>
 <translation id="3297344142967351106">Гласова помощ</translation>
 <translation id="3303414029551471755">Искате ли да продължите с изтеглянето на съдържанието?</translation>
 <translation id="3321367458490630980">Интересът е добавен</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> раздел}other{<ph name="TAB_COUNT_MANY" /> раздела, <ph name="TAB_COUNT_INCOGNITO" /> в режим „инкогнито“}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Установена е връзка с USB кабел</translation>
-<translation id="4557685098773234337">За да отваряте тази страница по-бързо, добавете я към началния екран</translation>
 <translation id="4558311620361989323">Комбинации за уеб страници</translation>
 <translation id="4561730552726921821">Регистрацията бе успешна</translation>
 <translation id="4561979708150884304">Няма връзка</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb
index 270de03..9867cb57 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">আগেভাগে সহায়তা</translation>
 <translation id="3285080554353377245">Chrome কীভাবে ব্যবহার করবেন সেই সংক্রান্ত ভিডিও</translation>
 <translation id="3288003805934695103">পৃষ্ঠাটি আবার লোড করে দেখুন</translation>
-<translation id="3290991969712132877">এটি আরও তাড়াতাড়ি পেতে, এই পৃষ্ঠাটি 'আরও বিকল্প' বোতাম থেকে আপনার হোম স্ক্রিনে যোগ করুন</translation>
 <translation id="3297344142967351106">ভয়েস সহায়তা</translation>
 <translation id="3303414029551471755">কন্টেন্ট ডাউনলোড করার জন্য এগোতে চান?</translation>
 <translation id="3321367458490630980">আগ্রহ যোগ করা হয়েছে</translation>
@@ -641,7 +640,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" />টি ট্যাব}one{<ph name="TAB_COUNT_MANY" />টি ট্যাব, <ph name="TAB_COUNT_INCOGNITO" />টি ছদ্মবেশী ট্যাব}other{<ph name="TAB_COUNT_MANY" />টি ট্যাব, <ph name="TAB_COUNT_INCOGNITO" />টি ছদ্মবেশী ট্যাব}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">ইউএসবি কেবেলের সাথে কানেক্ট করা হয়েছে</translation>
-<translation id="4557685098773234337">এখানে তাড়াতাড়ি পৌঁছাতে এই পৃষ্ঠাটি আপনার হোম স্ক্রিনে যোগ করুন</translation>
 <translation id="4558311620361989323">ওয়েবপৃষ্ঠার শর্টকাটগুলি</translation>
 <translation id="4561730552726921821">রেজিস্ট্রেশন হয়ে গেছে</translation>
 <translation id="4561979708150884304">কোনও কানেকশন নেই</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bs.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bs.xtb
index f00c6e1..b73722b 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bs.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bs.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktivna pomoć</translation>
 <translation id="3285080554353377245">Videozapisi o načinu korištenja Chromea</translation>
 <translation id="3288003805934695103">Ponovno učitavanje stranice</translation>
-<translation id="3290991969712132877">Da brže dođete ovdje, dodajte ovu stranicu na početni ekran putem dugmeta Više opcija</translation>
 <translation id="3297344142967351106">Glasovna pomoć</translation>
 <translation id="3303414029551471755">Nastaviti s preuzimanjem sadržaja?</translation>
 <translation id="3321367458490630980">Interesovanje je dodano</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> kartica}one{<ph name="TAB_COUNT_MANY" /> kartica, <ph name="TAB_COUNT_INCOGNITO" /> anonimna}few{<ph name="TAB_COUNT_MANY" /> kartice, <ph name="TAB_COUNT_INCOGNITO" /> anonimne}other{<ph name="TAB_COUNT_MANY" /> kartica, <ph name="TAB_COUNT_INCOGNITO" /> anonimnih}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Povezano pomoću USB kabla</translation>
-<translation id="4557685098773234337">Da brže dođete ovdje, dodajte ovu stranicu na početni ekran</translation>
 <translation id="4558311620361989323">Prečice web stranice</translation>
 <translation id="4561730552726921821">Registracija je uspjela</translation>
 <translation id="4561979708150884304">Niste povezani na mrežu</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ca.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ca.xtb
index a8a32f9..7cda94dd 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ca.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ca.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Ajuda proactiva</translation>
 <translation id="3285080554353377245">Vídeos sobre com s'utilitza Chrome</translation>
 <translation id="3288003805934695103">Torneu a carregar la pàgina</translation>
-<translation id="3290991969712132877">Per accedir aquí més ràpidament, afegeix aquesta pàgina a la pantalla d'inici amb el botó Més opcions</translation>
 <translation id="3297344142967351106">Assistència per veu</translation>
 <translation id="3303414029551471755">Voleu baixar el contingut?</translation>
 <translation id="3321367458490630980">S'ha afegit l'interès</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> pestanya}other{<ph name="TAB_COUNT_MANY" /> pestanyes, <ph name="TAB_COUNT_INCOGNITO" /> d'incògnit}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Connectat amb un cable USB</translation>
-<translation id="4557685098773234337">Per accedir aquí ràpidament, afegeix aquesta pàgina a la teva pantalla d'inici</translation>
 <translation id="4558311620361989323">Dreceres per a pàgines web</translation>
 <translation id="4561730552726921821">S'ha registrat correctament</translation>
 <translation id="4561979708150884304">No hi ha connexió</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_cs.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_cs.xtb
index 960e072..1063724 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_cs.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_cs.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktivní nápověda</translation>
 <translation id="3285080554353377245">Výuková videa o používání Chromu</translation>
 <translation id="3288003805934695103">Načíst stránku znovu</translation>
-<translation id="3290991969712132877">Přidejte si stránku na plochu pomocí tlačítka Další možnosti, abyste se sem dostali rychleji</translation>
 <translation id="3297344142967351106">Hlasová asistence</translation>
 <translation id="3303414029551471755">Chcete pokračovat ke stažení obsahu?</translation>
 <translation id="3321367458490630980">Zájem přidán</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> karta}few{<ph name="TAB_COUNT_MANY" /> karty, anonymní: <ph name="TAB_COUNT_INCOGNITO" />}many{<ph name="TAB_COUNT_MANY" /> karty, anonymní: <ph name="TAB_COUNT_INCOGNITO" />}other{<ph name="TAB_COUNT_MANY" /> karet, anonymní: <ph name="TAB_COUNT_INCOGNITO" />}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Připojeno kabelem USB</translation>
-<translation id="4557685098773234337">Přidejte si stránku na plochu, abyste se na ni dostali rychleji</translation>
 <translation id="4558311620361989323">Zkratky webových stránek</translation>
 <translation id="4561730552726921821">Registrace proběhla úspěšně</translation>
 <translation id="4561979708150884304">Žádné připojení</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_cy.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_cy.xtb
index e7f3eb6..4c198501 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_cy.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_cy.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Cymorth Rhagweithiol</translation>
 <translation id="3285080554353377245">Fideos am sut i ddefnyddio Chrome</translation>
 <translation id="3288003805934695103">Wrthi'n ail-lwytho'r dudalen</translation>
-<translation id="3290991969712132877">I gyrraedd yma'n gynt, ychwanegwch y dudalen hon at eich sgrîn hafan o'r botwm Rhagor o ddewisiadau</translation>
 <translation id="3297344142967351106">Cymorth llais</translation>
 <translation id="3303414029551471755">Parhau i lawrlwytho'r cynnwys?</translation>
 <translation id="3321367458490630980">Ychwanegwyd diddordeb</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> tab}zero{<ph name="TAB_COUNT_MANY" /> tab, <ph name="TAB_COUNT_INCOGNITO" /> tab anhysbys}two{<ph name="TAB_COUNT_MANY" /> dab, <ph name="TAB_COUNT_INCOGNITO" /> dab anhysbys}few{<ph name="TAB_COUNT_MANY" /> thab, <ph name="TAB_COUNT_INCOGNITO" /> thab anhysbys}many{<ph name="TAB_COUNT_MANY" /> thab, <ph name="TAB_COUNT_INCOGNITO" /> thab anhysbys}other{<ph name="TAB_COUNT_MANY" /> tab, <ph name="TAB_COUNT_INCOGNITO" /> tab anhysbys}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Wedi cysylltu â chebl USB</translation>
-<translation id="4557685098773234337">I gyrraedd yma ynghynt, ychwanegwch y dudalen hon at eich sgrîn Hafan</translation>
 <translation id="4558311620361989323">Llwybrau byr tudalen we</translation>
 <translation id="4561730552726921821">Wedi cofrestru'n llwyddiannus</translation>
 <translation id="4561979708150884304">Dim cysylltiad</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb
index 6dc09874..6d1010d6 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_da.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktiv hjælp</translation>
 <translation id="3285080554353377245">Videoer om, hvordan du bruger Chrome</translation>
 <translation id="3288003805934695103">Genindlæse siden</translation>
-<translation id="3290991969712132877">Føj denne side til din startskærm ved hjælp af knappen Flere valgmuligheder for hurtigt at vende tilbage hertil</translation>
 <translation id="3297344142967351106">Stemmesøgning</translation>
 <translation id="3303414029551471755">Vil du fortsætte og downloade indholdet?</translation>
 <translation id="3321367458490630980">Interessen er tilføjet</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> fane}one{<ph name="TAB_COUNT_MANY" /> fane og <ph name="TAB_COUNT_INCOGNITO" /> inkognitofane}other{<ph name="TAB_COUNT_MANY" /> faner og <ph name="TAB_COUNT_INCOGNITO" /> inkognitofaner}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Tilsluttet via USB-kabel</translation>
-<translation id="4557685098773234337">Føj dette website til din startskærm for hurtigere at vende tilbage hertil</translation>
 <translation id="4558311620361989323">Genveje på websider</translation>
 <translation id="4561730552726921821">Tilmeldingen blev fuldført</translation>
 <translation id="4561979708150884304">Der er ingen forbindelse</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_de.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_de.xtb
index 9e898d1..ec379be38 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_de.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_de.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktive Hilfe</translation>
 <translation id="3285080554353377245">Videos über die Verwendung von Chrome</translation>
 <translation id="3288003805934695103">Seite aktualisieren</translation>
-<translation id="3290991969712132877">Über die Schaltfläche „Weitere Optionen“ kannst du diese Seite zum Startbildschirm hinzufügen, um schneller zurückzukehren</translation>
 <translation id="3297344142967351106">Sprachassistent</translation>
 <translation id="3303414029551471755">Inhalt herunterladen?</translation>
 <translation id="3321367458490630980">Interesse hinzugefügt</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> Tab}other{<ph name="TAB_COUNT_MANY" /> Tabs, <ph name="TAB_COUNT_INCOGNITO" /> Inkognitotabs}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Per USB-Kabel verbunden</translation>
-<translation id="4557685098773234337">Füge diese Seite zum Startbildschirm hinzu, um schneller zurückzukehren</translation>
 <translation id="4558311620361989323">Tastenkombinationen für Webseiten</translation>
 <translation id="4561730552726921821">Registrierung abgeschlossen</translation>
 <translation id="4561979708150884304">Keine Verbindung</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb
index 3ff35f6..242b9c7e 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Προληπτική βοήθεια</translation>
 <translation id="3285080554353377245">Βίντεο σχετικά με τον τρόπο χρήσης του Chrome</translation>
 <translation id="3288003805934695103">Επαναλάβετε τη φόρτωση της σελίδας</translation>
-<translation id="3290991969712132877">Από το κουμπί Περισσότερες επιλογές, προσθέστε αυτήν τη σελίδα στην αρχική οθόνη για ταχύτερη μετάβαση.</translation>
 <translation id="3297344142967351106">Φωνητική βοήθεια</translation>
 <translation id="3303414029551471755">Συνέχεια για λήψη του περιεχομένου;</translation>
 <translation id="3321367458490630980">Το ενδιαφέρον προστέθηκε</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> καρτέλα}other{<ph name="TAB_COUNT_MANY" /> καρτέλες, <ph name="TAB_COUNT_INCOGNITO" /> ανώνυμης περιήγησης}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Συνδέθηκε με καλώδιο USB</translation>
-<translation id="4557685098773234337">Προσθέστε αυτήν τη σελίδα στην αρχική οθόνη για ταχύτερη μετάβαση.</translation>
 <translation id="4558311620361989323">Συντομεύσεις ιστοσελίδας</translation>
 <translation id="4561730552726921821">Η εγγραφή ήταν επιτυχής</translation>
 <translation id="4561979708150884304">Δεν υπάρχει σύνδεση</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_en-GB.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_en-GB.xtb
index 768bdeb36..6970c0be 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_en-GB.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_en-GB.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proactive help</translation>
 <translation id="3285080554353377245">Videos about how to use Chrome</translation>
 <translation id="3288003805934695103">Reloading the page</translation>
-<translation id="3290991969712132877">To get here quicker, add this page to your home screen from the 'More options' button</translation>
 <translation id="3297344142967351106">Voice assistance</translation>
 <translation id="3303414029551471755">Proceed to download the content?</translation>
 <translation id="3321367458490630980">Interest added</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> tab}other{<ph name="TAB_COUNT_MANY" /> tabs, <ph name="TAB_COUNT_INCOGNITO" /> incognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Connected with USB cable</translation>
-<translation id="4557685098773234337">To get here quicker, add this page to your home screen</translation>
 <translation id="4558311620361989323">Web page shortcuts</translation>
 <translation id="4561730552726921821">Registration succeeded</translation>
 <translation id="4561979708150884304">No connection</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_es-419.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_es-419.xtb
index d57b118..0c02a6c 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_es-419.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_es-419.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Ayuda proactiva</translation>
 <translation id="3285080554353377245">Videos sobre cómo usar Chrome</translation>
 <translation id="3288003805934695103">Volver a cargar la página.</translation>
-<translation id="3290991969712132877">Para acceder aquí más rápido, agrega esta página a tu pantalla principal desde el botón Más opciones</translation>
 <translation id="3297344142967351106">Asistencia de voz</translation>
 <translation id="3303414029551471755">¿Deseas descargar el contenido?</translation>
 <translation id="3321367458490630980">Se agregó el interés.</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> pestaña}other{<ph name="TAB_COUNT_MANY" /> pestañas, <ph name="TAB_COUNT_INCOGNITO" /> de incógnito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Conectado con cable USB</translation>
-<translation id="4557685098773234337">Para acceder aquí más rápido, agrega esta página a la pantalla principal</translation>
 <translation id="4558311620361989323">Accesos directos a páginas web</translation>
 <translation id="4561730552726921821">Se completó correctamente el registro.</translation>
 <translation id="4561979708150884304">Sin conexión</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_es.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_es.xtb
index a069a36..decc4c4 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_es.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_es.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Ayuda proactiva</translation>
 <translation id="3285080554353377245">Vídeos sobre cómo usar Chrome</translation>
 <translation id="3288003805934695103">Volver a cargar la página</translation>
-<translation id="3290991969712132877">Para acceder a esta página más rápido, añádela a tu pantalla de inicio con el botón Más opciones</translation>
 <translation id="3297344142967351106">Asistente de voz</translation>
 <translation id="3303414029551471755">¿Quieres continuar para descargar el contenido?</translation>
 <translation id="3321367458490630980">Interés añadido</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> pestaña}other{<ph name="TAB_COUNT_MANY" /> pestañas, <ph name="TAB_COUNT_INCOGNITO" /> de incógnito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Conectado con cable USB</translation>
-<translation id="4557685098773234337">Para acceder a esta página más rápido, añádela a tu pantalla de inicio</translation>
 <translation id="4558311620361989323">Combinaciones de teclas en páginas web</translation>
 <translation id="4561730552726921821">Se ha registrado correctamente</translation>
 <translation id="4561979708150884304">No hay conexión</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_et.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_et.xtb
index 23656dc..1ce3631 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_et.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_et.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Ennetav abi</translation>
 <translation id="3285080554353377245">Videod Chrome'i kasutamise kohta</translation>
 <translation id="3288003805934695103">Laadige leht uuesti</translation>
-<translation id="3290991969712132877">Kiiremini siia jõudmiseks lisage see leht nupu Rohkem valikuid abil avakuvale</translation>
 <translation id="3297344142967351106">Häälabi</translation>
 <translation id="3303414029551471755">Kas soovite jätkata sisu allalaadimist?</translation>
 <translation id="3321367458490630980">Huvi lisati</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> vaheleht}other{<ph name="TAB_COUNT_MANY" /> vahelehte, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Ühendatud USB-kaabliga</translation>
-<translation id="4557685098773234337">Kiiremini siia jõudmiseks lisage see leht oma avakuvale</translation>
 <translation id="4558311620361989323">Veebilehe otseteed</translation>
 <translation id="4561730552726921821">Registreerumine õnnestus</translation>
 <translation id="4561979708150884304">Ühendus puudub</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb
index 81ef690..f42653c1 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_eu.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Laguntza proaktiboa</translation>
 <translation id="3285080554353377245">Chrome erabiltzeko argibideei buruzko bideoak</translation>
 <translation id="3288003805934695103">Orria berriro kargatu.</translation>
-<translation id="3290991969712132877">Hona azkarrago iristeko, gehitu orri hau hasierako pantailan "Aukera gehiago" botoia sakatuta</translation>
 <translation id="3297344142967351106">Ahozko laguntza</translation>
 <translation id="3303414029551471755">Aurrera egin eta edukia deskargatu nahi duzu?</translation>
 <translation id="3321367458490630980">Gehitu da interesa</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> fitxa}other{<ph name="TAB_COUNT_MANY" /> fitxa, ezkutuko moduko <ph name="TAB_COUNT_INCOGNITO" /> fitxa}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB kable baten bidez konektatuta</translation>
-<translation id="4557685098773234337">Hona azkarrago iristeko, gehitu orri hau hasierako pantailan</translation>
 <translation id="4558311620361989323">Web-orrietarako lasterbideak</translation>
 <translation id="4561730552726921821">Erregistratu da</translation>
 <translation id="4561979708150884304">Ez zaude konektatuta Internetera</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb
index 6e4506d..250c48e 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fa.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">کمک کنش‌گرایانه</translation>
 <translation id="3285080554353377245">‏ویدیوهایی درباره نحوه استفاده از Chrome</translation>
 <translation id="3288003805934695103">تازه‌سازی صفحه</translation>
-<translation id="3290991969712132877">برای اینکه سریع‌تر به اینجا دسترسی پیدا کنید، این صفحه را از دکمه گزینه‌های «بیشتر» به صفحه اصلی اضافه کنید</translation>
 <translation id="3297344142967351106">دستیار صوتی</translation>
 <translation id="3303414029551471755">ادامه می‌دهید و محتوا را بارگیری می‌کنید؟</translation>
 <translation id="3321367458490630980">علاقه اضافه شد</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> برگه}one{<ph name="TAB_COUNT_MANY" /> برگه، <ph name="TAB_COUNT_INCOGNITO" /> برگه ناشناس}other{<ph name="TAB_COUNT_MANY" /> برگه، <ph name="TAB_COUNT_INCOGNITO" /> برگه ناشناس}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">‏بااستفاده از سیم USB متصل است</translation>
-<translation id="4557685098773234337">برای اینکه سریع‌تر به اینجا دسترسی پیدا کنید، این صفحه را به صفحه اصلی اضافه کنید</translation>
 <translation id="4558311620361989323">میان‌برهای صفحه وب</translation>
 <translation id="4561730552726921821">ثبت انجام شد</translation>
 <translation id="4561979708150884304">اتصال برقرار نیست</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fi.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fi.xtb
index 5684f88..af2e783 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fi.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fi.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktiivinen avustus</translation>
 <translation id="3285080554353377245">Video-ohjeita Chromen käyttöön</translation>
 <translation id="3288003805934695103">Lataa sivu uudelleen.</translation>
-<translation id="3290991969712132877">Pääset tähän nopeammin, kun lisäät sivun aloitusnäytöllesi lisäasetuksista</translation>
 <translation id="3297344142967351106">Ääniapu</translation>
 <translation id="3303414029551471755">Jatketaanko sisällön lataamiseen?</translation>
 <translation id="3321367458490630980">Kiinnostuksen kohde lisätty</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> välilehti}other{<ph name="TAB_COUNT_MANY" /> välilehteä, <ph name="TAB_COUNT_INCOGNITO" /> incognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Yhdistetty USB-johdolla</translation>
-<translation id="4557685098773234337">Lisää tämä sivu aloitusnäytölle, niin pääset tähän nopeammin</translation>
 <translation id="4558311620361989323">Verkkosivun pikanäppäimet</translation>
 <translation id="4561730552726921821">Rekisteröinti onnistui</translation>
 <translation id="4561979708150884304">Ei yhteyttä</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fil.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fil.xtb
index d7b45f5..1800508 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fil.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fil.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proactive na Tulong</translation>
 <translation id="3285080554353377245">Mga video tungkol sa kung paano gamitin ang Chrome</translation>
 <translation id="3288003805934695103">I-reload ang page</translation>
-<translation id="3290991969712132877">Para mas mabilis na makapunta rito, idagdag ang page na ito sa iyong Home screen mula sa button na Higit pang opsyon</translation>
 <translation id="3297344142967351106">Tulong sa pamamagitan ng boses</translation>
 <translation id="3303414029551471755">Magpatuloy na i-download ang content?</translation>
 <translation id="3321367458490630980">Naidagdag ang interes</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> tab}one{<ph name="TAB_COUNT_MANY" /> tab, <ph name="TAB_COUNT_INCOGNITO" /> incognito}other{<ph name="TAB_COUNT_MANY" /> na tab, <ph name="TAB_COUNT_INCOGNITO" /> incognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Nakakonekta gamit ang USB cable</translation>
-<translation id="4557685098773234337">Para mas mabilis na makapunta rito, idagdag ang page na ito sa iyong Home screen</translation>
 <translation id="4558311620361989323">Mga shortcut ng webpage</translation>
 <translation id="4561730552726921821">Nagtagumpay ang pagpaparehistro</translation>
 <translation id="4561979708150884304">Walang koneksyon</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr-CA.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr-CA.xtb
index 5bc8ab44..59effcb 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr-CA.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr-CA.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Aide proactive</translation>
 <translation id="3285080554353377245">Vidéos sur l'utilisation de Chrome</translation>
 <translation id="3288003805934695103">D'actualiser la page</translation>
-<translation id="3290991969712132877">Pour revenir à cette page plus rapidement, ajoutez-la à votre écran d'accueil à l'aide du bouton Plus d'options</translation>
 <translation id="3297344142967351106">Assistance vocale</translation>
 <translation id="3303414029551471755">Lancer le téléchargement du contenu?</translation>
 <translation id="3321367458490630980">Centre d'intérêt ajouté</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> onglet}one{<ph name="TAB_COUNT_MANY" /> onglet, <ph name="TAB_COUNT_INCOGNITO" /> onglet de navigation privée}other{<ph name="TAB_COUNT_MANY" /> onglets, <ph name="TAB_COUNT_INCOGNITO" /> onglets de navigation privée}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Connecté à l'aide d'un câble USB</translation>
-<translation id="4557685098773234337">Pour revenir plus rapidement sur cette page, ajoutez-la à votre écran d'accueil</translation>
 <translation id="4558311620361989323">Raccourcis relatifs à la page Web</translation>
 <translation id="4561730552726921821">Inscription réussie</translation>
 <translation id="4561979708150884304">Aucune connexion</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
index 7857e56..164b4bb 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_fr.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Aide proactive</translation>
 <translation id="3285080554353377245">Vidéos sur l'utilisation de Chrome</translation>
 <translation id="3288003805934695103">Recharger la page</translation>
-<translation id="3290991969712132877">Pour accéder à ce site plus rapidement, ajoutez-le à l'écran d'accueil en cliquant sur le bouton "Plus d'options"</translation>
 <translation id="3297344142967351106">Assistance vocale</translation>
 <translation id="3303414029551471755">Poursuivre et télécharger le contenu ?</translation>
 <translation id="3321367458490630980">Centre d'intérêt ajouté</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> onglet}one{<ph name="TAB_COUNT_MANY" /> onglet, <ph name="TAB_COUNT_INCOGNITO" /> en navigation privée}other{<ph name="TAB_COUNT_MANY" /> onglets, <ph name="TAB_COUNT_INCOGNITO" /> en navigation privée}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Connecté avec un câble USB</translation>
-<translation id="4557685098773234337">Pour accéder à ce site plus rapidement, ajoutez-le à l'écran d'accueil</translation>
 <translation id="4558311620361989323">Raccourcis de pages Web</translation>
 <translation id="4561730552726921821">Enregistrement réussi</translation>
 <translation id="4561979708150884304">Aucune connexion</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gl.xtb
index c6c002d..e7cacaa 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gl.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gl.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Axuda proactiva</translation>
 <translation id="3285080554353377245">Vídeos sobre como usar Chrome</translation>
 <translation id="3288003805934695103">Volver cargar a páxina</translation>
-<translation id="3290991969712132877">Para chegar aquí máis axiña, engádelle esta páxina á pantalla de inicio a través do botón Máis opcións</translation>
 <translation id="3297344142967351106">Asistencia de voz</translation>
 <translation id="3303414029551471755">Queres continuar coa descarga do contido?</translation>
 <translation id="3321367458490630980">Engadiuse o interese</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> pestana}other{<ph name="TAB_COUNT_MANY" /> pestanas, <ph name="TAB_COUNT_INCOGNITO" /> no modo de incógnito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Teléfono conectado mediante un cable USB</translation>
-<translation id="4557685098773234337">Para chegar aquí máis axiña, engádelle esta páxina á pantalla de inicio</translation>
 <translation id="4558311620361989323">Atallos da páxina web</translation>
 <translation id="4561730552726921821">Realizouse o rexistro</translation>
 <translation id="4561979708150884304">Sen conexión</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb
index 8927067..659aaca 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_gu.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">સક્રિય સહાય</translation>
 <translation id="3285080554353377245">Chromeનો ઉપયોગ કેવી રીતે કરવો તે વિશેના વીડિયો</translation>
 <translation id="3288003805934695103">પેજ ફરીથી લોડ કરીને</translation>
-<translation id="3290991969712132877">અહીં ઝડપથી પહોંચવા માટે, 'વધુ વિકલ્પો'ના બટન વડે તમારી હોમ સ્ક્રીનમાં આ પેજ ઉમેરો</translation>
 <translation id="3297344142967351106">વૉઇસ સહાયતા</translation>
 <translation id="3303414029551471755">કન્ટેન્ટ ડાઉનલોડ કરવા માટે આગળ વધીએ?</translation>
 <translation id="3321367458490630980">રુચિઓ ઉમેરી</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ટૅબ}one{<ph name="TAB_COUNT_MANY" /> ટૅબ, <ph name="TAB_COUNT_INCOGNITO" /> છૂપી}other{<ph name="TAB_COUNT_MANY" /> ટૅબ, <ph name="TAB_COUNT_INCOGNITO" /> છૂપી}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB કેબલ સાથે કનેક્ટ કરેલો છે</translation>
-<translation id="4557685098773234337">અહીં ઝડપથી પહોંચવા માટે, તમારી હોમ સ્ક્રીનમાં આ પેજ ઉમેરો</translation>
 <translation id="4558311620361989323">વેબ પેજના શૉર્ટકટ</translation>
 <translation id="4561730552726921821">નોંધણી કરવામાં સફળ રહ્યાં</translation>
 <translation id="4561979708150884304">કોઈ કનેક્શન નથી</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hi.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hi.xtb
index 266655fd..cd487590 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hi.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hi.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">बिन मांगे मदद</translation>
 <translation id="3285080554353377245">Chrome को इस्तेमाल करने का तरीका बताने वाला वीडियो</translation>
 <translation id="3288003805934695103">पेज को पुनः लोड करें</translation>
-<translation id="3290991969712132877">इसे और जल्दी ऐक्सेस करने के लिए, 'ज़्यादा विकल्प' बटन पर क्लिक करके, इस पेज को अपनी होम स्क्रीन पर जोड़ें</translation>
 <translation id="3297344142967351106">आवाज़ से डिवाइस का इस्तेमाल करना</translation>
 <translation id="3303414029551471755">सामग्री डाउनलोड करने के लिए आगे बढ़ें?</translation>
 <translation id="3321367458490630980">पसंद का विषय जोड़ा गया</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> टैब}one{<ph name="TAB_COUNT_MANY" /> टैब, <ph name="TAB_COUNT_INCOGNITO" /> गुप्त टैब}other{<ph name="TAB_COUNT_MANY" /> टैब, <ph name="TAB_COUNT_INCOGNITO" /> गुप्त टैब}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">यूएसबी केबल की मदद से कनेक्ट किया गया</translation>
-<translation id="4557685098773234337">इसे और जल्दी ऐक्सेस करने के लिए, इस पेज को अपनी होम स्क्रीन पर जोड़ें</translation>
 <translation id="4558311620361989323">वेबपेज शॉर्टकट</translation>
 <translation id="4561730552726921821">रजिस्ट्रेशन हो गया</translation>
 <translation id="4561979708150884304">कोई कनेक्शन नहीं</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hr.xtb
index b8b2326..7b83c3a6 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hr.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hr.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktivna pomoć</translation>
 <translation id="3285080554353377245">Videozapisi o upotrebi Chromea</translation>
 <translation id="3288003805934695103">ponovo učitajte stranicu</translation>
-<translation id="3290991969712132877">Da biste brže otvorili ovu stranicu, dodajte je na početni zaslon pomoću gumba Više opcija</translation>
 <translation id="3297344142967351106">Glasovna pomoć</translation>
 <translation id="3303414029551471755">Želite li nastaviti s preuzimanjem sadržaja?</translation>
 <translation id="3321367458490630980">Interes je dodan</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> kartica}one{<ph name="TAB_COUNT_MANY" /> kartica, <ph name="TAB_COUNT_INCOGNITO" /> u anonimnom načinu}few{<ph name="TAB_COUNT_MANY" /> kartice, <ph name="TAB_COUNT_INCOGNITO" /> u anonimnom načinu}other{<ph name="TAB_COUNT_MANY" /> kartica, <ph name="TAB_COUNT_INCOGNITO" /> u anonimnom načinu}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Spojeno putem USB kabela</translation>
-<translation id="4557685098773234337">Da biste brže otvorili ovu stranicu, dodajte je na početni zaslon</translation>
 <translation id="4558311620361989323">Prečaci web-stranice</translation>
 <translation id="4561730552726921821">Registracija uspješna</translation>
 <translation id="4561979708150884304">Niste povezani</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hu.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hu.xtb
index 1e14dbc8..bcd0e2e 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hu.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hu.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktív segítség</translation>
 <translation id="3285080554353377245">Videók a Chrome használatával kapcsolatban</translation>
 <translation id="3288003805934695103">Az oldal frissítése</translation>
-<translation id="3290991969712132877">Adja hozzá ezt az oldalt a kezdőképernyőhöz a További lehetőségek gomb segítségével, hogy gyorsabban megnyithassa.</translation>
 <translation id="3297344142967351106">Hangalapú segítség</translation>
 <translation id="3303414029551471755">Biztosan letölti a tartalmat?</translation>
 <translation id="3321367458490630980">Érdeklődési kör hozzáadva</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> lap}other{<ph name="TAB_COUNT_MANY" /> lap, <ph name="TAB_COUNT_INCOGNITO" /> inkognitó módban}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Csatlakoztatva USB-kábellel</translation>
-<translation id="4557685098773234337">Adja hozzá ezt az oldalt a kezdőképernyőhöz, hogy gyorsabban megnyithassa</translation>
 <translation id="4558311620361989323">Weboldalakkal kapcsolatos billentyűparancsok</translation>
 <translation id="4561730552726921821">Sikeres regisztráció</translation>
 <translation id="4561979708150884304">Nincs kapcsolat</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hy.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hy.xtb
index ab71ba82..d4f7f2e 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_hy.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_hy.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Օգնություն՝ անհրաժեշտ պահին</translation>
 <translation id="3285080554353377245">Տեսանյութեր Chrome-ի օգտագործման մասին</translation>
 <translation id="3288003805934695103">Վերաբեռնել էջը</translation>
-<translation id="3290991969712132877">Այս էջն ավելի արագ բացելու համար ավելացրեք այն հիմնական էկրանին «Այլ ընտրանքներ» կոճակի օգնությամբ։</translation>
 <translation id="3297344142967351106">Ձայնային հուշումներ</translation>
 <translation id="3303414029551471755">Ներբեռնե՞լ բովանդակությունը:</translation>
 <translation id="3321367458490630980">Հետաքրքրությունն ավելացվեց</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ներդիր}one{<ph name="TAB_COUNT_MANY" /> ներդիր, <ph name="TAB_COUNT_INCOGNITO" /> ինկոգնիտո ներդիր}other{<ph name="TAB_COUNT_MANY" /> ներդիր, <ph name="TAB_COUNT_INCOGNITO" /> ինկոգնիտո ներդիր}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Միացված է USB մալուխով</translation>
-<translation id="4557685098773234337">Այս կայքն ավելի արագ բացելու համար ավելացրեք այն հիմնական էկրանին</translation>
 <translation id="4558311620361989323">Վեբէջերի դյուրանցումներ</translation>
 <translation id="4561730552726921821">Գրանցումը կատարվեց</translation>
 <translation id="4561979708150884304">Կապ չկա</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_id.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_id.xtb
index f718aed..99c0d59 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_id.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_id.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Bantuan Proaktif</translation>
 <translation id="3285080554353377245">Video tentang cara menggunakan Chrome</translation>
 <translation id="3288003805934695103">Memuat ulang halaman</translation>
-<translation id="3290991969712132877">Untuk membukanya lebih cepat, tambahkan halaman ini ke Layar utama dari tombol opsi Lainnya</translation>
 <translation id="3297344142967351106">Bantuan suara</translation>
 <translation id="3303414029551471755">Lanjutkan untuk mendownload konten?</translation>
 <translation id="3321367458490630980">Minat ditambahkan</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> tab}other{<ph name="TAB_COUNT_MANY" /> tab, <ph name="TAB_COUNT_INCOGNITO" /> samaran}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Terhubung dengan kabel USB</translation>
-<translation id="4557685098773234337">Untuk membukanya lebih cepat, tambahkan halaman ini ke Layar utama</translation>
 <translation id="4558311620361989323">Pintasan halaman web</translation>
 <translation id="4561730552726921821">Pendaftaran berhasil</translation>
 <translation id="4561979708150884304">Tidak ada koneksi</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_is.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_is.xtb
index 9b2edca..5c92bf7 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_is.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_is.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Hjálp að fyrra bragði</translation>
 <translation id="3285080554353377245">Myndskeið um hvernig á að nota Chrome</translation>
 <translation id="3288003805934695103">Endurhlaða síðuna</translation>
-<translation id="3290991969712132877">Bættu þessari síðu á heimaskjáinn með hnappinum „Fleiri valkostir“ til að komast þangað hraðar</translation>
 <translation id="3297344142967351106">Raddaðstoð</translation>
 <translation id="3303414029551471755">Viltu halda áfram og sækja efnið?</translation>
 <translation id="3321367458490630980">Áhugasviði bætt við</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> flipi}one{<ph name="TAB_COUNT_MANY" /> flipi, <ph name="TAB_COUNT_INCOGNITO" /> huliðsflipi}other{<ph name="TAB_COUNT_MANY" /> flipar, <ph name="TAB_COUNT_INCOGNITO" /> huliðsflipar}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Tengt með USB-snúru</translation>
-<translation id="4557685098773234337">Bættu þessari síðu við heimaskjáinn til að komast þangað hraðar</translation>
 <translation id="4558311620361989323">Flýtilyklar vefsíðu</translation>
 <translation id="4561730552726921821">Skráning tókst</translation>
 <translation id="4561979708150884304">Engin tenging</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_it.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_it.xtb
index f687de02..33c4b48 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_it.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_it.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Assistenza tempestiva</translation>
 <translation id="3285080554353377245">Video relativi all'utilizzo di Chrome</translation>
 <translation id="3288003805934695103">Ricaricare la pagina</translation>
-<translation id="3290991969712132877">Per potervi accedere più rapidamente, aggiungi questa pagina alla schermata Home dal pulsante Altre opzioni</translation>
 <translation id="3297344142967351106">Assistenza vocale</translation>
 <translation id="3303414029551471755">Procedere al download dei contenuti?</translation>
 <translation id="3321367458490630980">Interesse aggiunto</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> scheda}other{<ph name="TAB_COUNT_MANY" /> schede, <ph name="TAB_COUNT_INCOGNITO" /> in incognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Collegamento tramite cavo USB effettuato</translation>
-<translation id="4557685098773234337">Per accedervi più rapidamente, aggiungi questa pagina alla schermata Home</translation>
 <translation id="4558311620361989323">Scorciatoie delle pagine web</translation>
 <translation id="4561730552726921821">Registrazione effettuata</translation>
 <translation id="4561979708150884304">Nessuna connessione</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_iw.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_iw.xtb
index 739ccf3..12c3625 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_iw.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_iw.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">עזרה פרואקטיבית</translation>
 <translation id="3285080554353377245">‏סרטוני הסבר על השימוש ב-Chrome</translation>
 <translation id="3288003805934695103">הדף נטען מחדש</translation>
-<translation id="3290991969712132877">רוצה להגיע לכאן מהר יותר? ניתן להוסיף את הדף הזה למסך הבית דרך לחצן האפשרויות הנוספות</translation>
 <translation id="3297344142967351106">האסיסטנט</translation>
 <translation id="3303414029551471755">האם להוריד את התוכן?</translation>
 <translation id="3321367458490630980">תחום העניין נוסף</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{כרטיסייה אחת (<ph name="TAB_COUNT_ONE" />)}two{<ph name="TAB_COUNT_MANY" /> כרטיסיות, <ph name="TAB_COUNT_INCOGNITO" /> כרטיסיות של מצב אנונימי}many{<ph name="TAB_COUNT_MANY" /> כרטיסיות, <ph name="TAB_COUNT_INCOGNITO" /> כרטיסיות של מצב אנונימי}other{<ph name="TAB_COUNT_MANY" /> כרטיסיות, <ph name="TAB_COUNT_INCOGNITO" /> כרטיסיות של מצב אנונימי}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">‏הטלפון מחובר באמצעות כבל USB</translation>
-<translation id="4557685098773234337">רוצה להגיע לכאן מהר יותר? ניתן להוסיף את הדף הזה למסך הבית</translation>
 <translation id="4558311620361989323">קיצורי דרך בדפי אינטרנט</translation>
 <translation id="4561730552726921821">הרישום בוצע בהצלחה</translation>
 <translation id="4561979708150884304">אין חיבור</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb
index 31f76cd..46439ce 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ja.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">アクティブ サポート</translation>
 <translation id="3285080554353377245">Chrome の使い方に関する動画</translation>
 <translation id="3288003805934695103">ページを再読み込みする</translation>
-<translation id="3290991969712132877">このページにすばやくアクセスするには、[その他のオプション] からこのページをホーム画面に追加してください</translation>
 <translation id="3297344142967351106">音声アシスタント</translation>
 <translation id="3303414029551471755">コンテンツのダウンロードに進みますか?</translation>
 <translation id="3321367458490630980">興味 / 関心を追加しました</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> 個のタブ}other{<ph name="TAB_COUNT_MANY" /> 個のタブ、<ph name="TAB_COUNT_INCOGNITO" /> 個のシークレット タブ}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB ケーブルで接続しました</translation>
-<translation id="4557685098773234337">このページにすばやくアクセスするには、ホーム画面に追加してください</translation>
 <translation id="4558311620361989323">ウェブページのショートカット</translation>
 <translation id="4561730552726921821">登録が完了しました</translation>
 <translation id="4561979708150884304">接続されていません</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ka.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ka.xtb
index d61bcec0..b7cc8087 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ka.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ka.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">პროაქტიული დახმარება</translation>
 <translation id="3285080554353377245">ვიდეოები Chrome-ის გამოყენების წესის შესახებ</translation>
 <translation id="3288003805934695103">გვერდის გადატვირთვა</translation>
-<translation id="3290991969712132877">აქ სწრაფად რომ დაბრუნდეთ ხოლმე, დაამატეთ ეს გვერდი თქვენს მთავარ ეკრანს „სხვა ვარიანტების“ ღილაკის მეშვეობით</translation>
 <translation id="3297344142967351106">ხმოვანი დახმარება</translation>
 <translation id="3303414029551471755">გაგრძელდეს შინაარსის ჩამოტვირთვა?</translation>
 <translation id="3321367458490630980">ინტერესი დაემატა</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ჩანართი}other{<ph name="TAB_COUNT_MANY" /> ჩანართი, <ph name="TAB_COUNT_INCOGNITO" /> ინკოგნიტო}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">დაკავშირებულია USB კაბელით</translation>
-<translation id="4557685098773234337">აქ სწრაფად რომ დაბრუნდეთ ხოლმე, დაამატეთ ეს გვერდი თქვენს მთავარ ეკრანს</translation>
 <translation id="4558311620361989323">ვებგვერდის მალსახმობები</translation>
 <translation id="4561730552726921821">რეგისტრაცია წარმატებით შესრულდა</translation>
 <translation id="4561979708150884304">კავშირი არ არის</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb
index 5e0bc37e..0be35153 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_kk.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Қажетті көмек</translation>
 <translation id="3285080554353377245">Chrome браузерін қалай қолдану керегі туралы бейнелер</translation>
 <translation id="3288003805934695103">Бетті қайта жүктеу</translation>
-<translation id="3290991969712132877">Бұл жерге жылдамырақ кіру үшін осы бетті "Қосымша опциялар" түймесінен негізгі экранға енгізіңіз.</translation>
 <translation id="3297344142967351106">Дауыстық көмек</translation>
 <translation id="3303414029551471755">Мазмұн жүктеуді жалғастырасыз ба?</translation>
 <translation id="3321367458490630980">Қызығушылық қосылды.</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> қойынды}other{<ph name="TAB_COUNT_MANY" /> қойынды, <ph name="TAB_COUNT_INCOGNITO" /> инкогнито қойындысы}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB кабелімен жалғанды</translation>
-<translation id="4557685098773234337">Бұл жерге жылдамырақ кіру үшін осы бетті негізгі экранға енгізіңіз.</translation>
 <translation id="4558311620361989323">Веббет пернелер тіркесімдері</translation>
 <translation id="4561730552726921821">Тіркелдіңіз</translation>
 <translation id="4561979708150884304">Байланыс жоқ</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_km.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_km.xtb
index 852ddec..f75d468 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_km.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_km.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">ជំនួយ​បរិសកម្ម</translation>
 <translation id="3285080554353377245">វីដេអូអំពីរបៀបប្រើប្រាស់ Chrome</translation>
 <translation id="3288003805934695103">ដំណើរការទំព័រឡើងវិញ</translation>
-<translation id="3290991969712132877">ដើម្បីចូលមកទីនេះបានរហ័សជាងមុន សូមបញ្ចូលទំព័រនេះទៅក្នុងអេក្រង់ដើមរបស់អ្នកពីប៊ូតុង "ជម្រើសច្រើនទៀត"</translation>
 <translation id="3297344142967351106">ជំនួយជាសំឡេង</translation>
 <translation id="3303414029551471755">បន្តដើម្បីទាញយកមាតិកានេះ?</translation>
 <translation id="3321367458490630980">ចំណាប់អារម្មណ៍ត្រូវបានបញ្ចូល</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{ផ្ទាំង <ph name="TAB_COUNT_ONE" />}other{ផ្ទាំង <ph name="TAB_COUNT_MANY" />, ឯកជន <ph name="TAB_COUNT_INCOGNITO" />}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">បានភ្ជាប់ជាមួយខ្សែ USB</translation>
-<translation id="4557685098773234337">ដើម្បីចូលមកទីនេះបានរហ័សជាងមុន សូមបញ្ចូលទំព័រនេះទៅក្នុងអេក្រង់ដើមរបស់អ្នក</translation>
 <translation id="4558311620361989323">ផ្លូវកាត់គេហទំព័រ</translation>
 <translation id="4561730552726921821">បានចុះឈ្មោះ​ដោយជោគជ័យ</translation>
 <translation id="4561979708150884304">មិន​មាន​ការ​តភ្ជាប់</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_kn.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_kn.xtb
index 0f6d63b..fe33b472 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_kn.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_kn.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">ಪೂರ್ವಭಾವಿ ಸಹಾಯ</translation>
 <translation id="3285080554353377245">Chrome ಬಳಸುವ ಕುರಿತು ವೀಡಿಯೊಗಳು</translation>
 <translation id="3288003805934695103">ಪುಟ ಮರುಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ</translation>
-<translation id="3290991969712132877">ಇಲ್ಲಿಗೆ ತ್ವರಿತವಾಗಿ ತಲುಪಲು, ಇನ್ನಷ್ಟು ಆಯ್ಕೆಗಳು ಬಟನ್‌ನಿಂದ ಈ ಪುಟವನ್ನು ನಿಮ್ಮ ಮುಖಪುಟದ ಪರದೆಗೆ ಸೇರಿಸಿ</translation>
 <translation id="3297344142967351106">ಧ್ವನಿ ಸಹಾಯಕ</translation>
 <translation id="3303414029551471755">ವಿಷಯವನ್ನು ಡೌನ್‌ಲೊಡ್‌ ಮಾಡಲು ಮುಂದುವರಿಯುವುದೇ?</translation>
 <translation id="3321367458490630980">ಆಸಕ್ತಿಯನ್ನು ಸೇರಿಸಲಾಗಿದೆ</translation>
@@ -638,7 +637,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ಟ್ಯಾಬ್}one{<ph name="TAB_COUNT_MANY" /> ಟ್ಯಾಬ್‌ಗಳು, <ph name="TAB_COUNT_INCOGNITO" /> ಅಜ್ಞಾತ}other{<ph name="TAB_COUNT_MANY" /> ಟ್ಯಾಬ್‌ಗಳು, <ph name="TAB_COUNT_INCOGNITO" /> ಅಜ್ಞಾತ}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB ಕೇಬಲ್ ಬಳಸಿ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ</translation>
-<translation id="4557685098773234337">ಇಲ್ಲಿಗೆ ತ್ವರಿತವಾಗಿ ತಲುಪಲು, ಈ ಪುಟವನ್ನು ನಿಮ್ಮ ಮುಖಪುಟದ ಪರದೆಗೆ ಸೇರಿಸಿ</translation>
 <translation id="4558311620361989323">ವೆಬ್‌ಪುಟ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು</translation>
 <translation id="4561730552726921821">ನೋಂದಣಿ ಯಶಸ್ವಿಯಾಗಿದೆ</translation>
 <translation id="4561979708150884304">ಯಾವುದೇ ಸಂಪರ್ಕವಿಲ್ಲ</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ko.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ko.xtb
index 9b6ee68..31a75e2a 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ko.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ko.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">능동적 지원</translation>
 <translation id="3285080554353377245">Chrome 사용 방법에 관한 동영상</translation>
 <translation id="3288003805934695103">페이지 새로고침</translation>
-<translation id="3290991969712132877">신속하게 여기를 방문하려면 '옵션 더보기' 버튼을 눌러 이 페이지를 홈 화면에 추가하세요.</translation>
 <translation id="3297344142967351106">음성 지원</translation>
 <translation id="3303414029551471755">콘텐츠를 다운로드하시겠습니까?</translation>
 <translation id="3321367458490630980">관심분야 추가됨</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{탭 <ph name="TAB_COUNT_ONE" />개}other{탭 <ph name="TAB_COUNT_MANY" />개(시크릿 탭 <ph name="TAB_COUNT_INCOGNITO" />개)}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB 케이블로 연결됨</translation>
-<translation id="4557685098773234337">신속하게 여기를 방문하려면 이 페이지를 홈 화면에 추가하세요.</translation>
 <translation id="4558311620361989323">웹페이지 단축키</translation>
 <translation id="4561730552726921821">등록 성공</translation>
 <translation id="4561979708150884304">연결되지 않음</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ky.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ky.xtb
index 5252e8c..c0b37e7 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ky.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ky.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Керектүү учурда жардам алуу</translation>
 <translation id="3285080554353377245">Chrome'ду кантип колдонуу жөнүндө видеолор</translation>
 <translation id="3288003805934695103">Баракты кайра жүктөп көрүңүз</translation>
-<translation id="3290991969712132877">Бул баракты тезирээк ачуу үчүн "Дагы параметрлер" баскычынын жардамы менен аны башкы экранга кошуңуз</translation>
 <translation id="3297344142967351106">Үн жардамчысы</translation>
 <translation id="3303414029551471755">Мазмун жүктөлүп алына берсинби?</translation>
 <translation id="3321367458490630980">Кызыккан нерсе кошулду</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> өтмөк}other{<ph name="TAB_COUNT_MANY" /> өтмөк, <ph name="TAB_COUNT_INCOGNITO" /> жашыруун}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB кабели аркылуу туташты</translation>
-<translation id="4557685098773234337">Бул баракты тезирээк ачуу үчүн аны башкы экранга кошуңуз</translation>
 <translation id="4558311620361989323">Веб баракчасынын кыска жолдору</translation>
 <translation id="4561730552726921821">Ийгиликтүү катталды</translation>
 <translation id="4561979708150884304">Интернет жок</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb
index b0f4efc..51b25ac 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lo.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">ຄວາມຊ່ວຍເຫຼືອແບບບໍ່ຕ້ອງຮ້ອງຂໍ</translation>
 <translation id="3285080554353377245">ວິດີໂອກ່ຽວກັບວິທີໃຊ້ Chrome</translation>
 <translation id="3288003805934695103">ກຳລັງໂຫຼດໜ້າຄືນໃໝ່</translation>
-<translation id="3290991969712132877">ເພື່ອມາບ່ອນນີ້ໄດ້ໄວກວ່າ, ກະລຸນາເພີ່ມໜ້ານີ້ໃສ່ໜ້າຈໍຫຼັກຂອງທ່ານຈາກປຸມຕົວເລືອກເພີ່ມເຕີມ</translation>
 <translation id="3297344142967351106">ການຊ່ວຍເຫຼືອທາງສຽງ</translation>
 <translation id="3303414029551471755">ສືບ​ຕໍ່​ໄປດາວ​ໂຫຼດ​ເນື້ອ​ໃນ​ບໍ?</translation>
 <translation id="3321367458490630980">ເພີ່ມຄວາມສົນໃຈແລ້ວ</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ແຖບ}other{<ph name="TAB_COUNT_MANY" /> ແຖບ, <ph name="TAB_COUNT_INCOGNITO" /> ແຖບບໍ່ເປີດເຜີຍຕົວຕົນ}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">ເຊື່ອມຕໍ່ກັບສາຍ USB</translation>
-<translation id="4557685098773234337">ເພື່ອມາບ່ອນນີ້ໄດ້ໄວກວ່າ, ກະລຸນາເພີ່ມໜ້ານີ້ໃສ່ໜ້າຈໍຫຼັກຂອງທ່ານ</translation>
 <translation id="4558311620361989323">ທາງລັດໜ້າເວັບ</translation>
 <translation id="4561730552726921821">ລົງທະບຽນສຳເລັດແລ້ວ</translation>
 <translation id="4561979708150884304">ບໍ່ມີການເຊື່ອມຕໍ່</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lt.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lt.xtb
index 2f67eb7..2506dd8 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lt.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lt.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Aktyvi pagalba</translation>
 <translation id="3285080554353377245">Vaizdo įrašai apie „Chrome“ naudojimą</translation>
 <translation id="3288003805934695103">Iš naujo įkelti puslapį</translation>
-<translation id="3290991969712132877">Kad sparčiau čia patektumėte, šį puslapį pridėkite prie pagrindinio ekrano, spustelėję mygtuką „Daugiau parinkčių“</translation>
 <translation id="3297344142967351106">Pagalba balsu</translation>
 <translation id="3303414029551471755">Tęsti turinio atsisiuntimo procesą?</translation>
 <translation id="3321367458490630980">Pomėgis pridėtas</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> skirtukas}one{Skirtukų: <ph name="TAB_COUNT_MANY" />, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}few{Skirtukų: <ph name="TAB_COUNT_MANY" />, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}many{Skirtukų: <ph name="TAB_COUNT_MANY" />, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}other{Skirtukų: <ph name="TAB_COUNT_MANY" />, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Prijungta USB laidu</translation>
-<translation id="4557685098773234337">Kad sparčiau čia patektumėte, šį puslapį pridėkite prie pagrindinio ekrano.</translation>
 <translation id="4558311620361989323">Tinklalapių spartieji klavišai</translation>
 <translation id="4561730552726921821">Registracija sėkminga</translation>
 <translation id="4561979708150884304">Nėra ryšio</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lv.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lv.xtb
index 497b98ff..03a62f4 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_lv.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_lv.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Aktīva palīdzība</translation>
 <translation id="3285080554353377245">Video pamācības par Chrome lietošanu</translation>
 <translation id="3288003805934695103">Atkārtoti ielādējiet lapu.</translation>
-<translation id="3290991969712132877">Lai varētu šeit nokļūt ātrāk, pievienojiet šo lapu sākuma ekrānam, izmantojot pogu Citas opcijas</translation>
 <translation id="3297344142967351106">Balss palīgs</translation>
 <translation id="3303414029551471755">Vai turpināt ar satura lejupielādi?</translation>
 <translation id="3321367458490630980">Interese ir pievienota</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> cilne}zero{<ph name="TAB_COUNT_MANY" /> ciļņu, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}one{<ph name="TAB_COUNT_MANY" /> cilne, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}other{<ph name="TAB_COUNT_MANY" /> cilnes, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Pievienots ar USB vadu</translation>
-<translation id="4557685098773234337">Lai varētu šeit nokļūt ātrāk, pievienojiet šo lapu sākuma ekrānam</translation>
 <translation id="4558311620361989323">Tīmekļa lapu īsinājumtaustiņi</translation>
 <translation id="4561730552726921821">Reģistrēšanās sekmīga</translation>
 <translation id="4561979708150884304">Nav savienojuma</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mk.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mk.xtb
index a0c702d..9481d0c79 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mk.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mk.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Проактивна помош</translation>
 <translation id="3285080554353377245">Видеа за користењето на Chrome</translation>
 <translation id="3288003805934695103">Повторно да ја вчитате страницата</translation>
-<translation id="3290991969712132877">За побрз пристап до страницава, додајте ја на почетниот екран преку копчето „Повеќе опции“</translation>
 <translation id="3297344142967351106">Гласовна помош</translation>
 <translation id="3303414029551471755">Продолжете со преземање на содржината?</translation>
 <translation id="3321367458490630980">Интересот е додаден</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> картичка}one{<ph name="TAB_COUNT_MANY" /> картичка, <ph name="TAB_COUNT_INCOGNITO" /> инкогнито}other{<ph name="TAB_COUNT_MANY" /> картички, <ph name="TAB_COUNT_INCOGNITO" /> инкогнито}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Поврзано со USB-кабел</translation>
-<translation id="4557685098773234337">За побрз пристап до страницава, додајте ја на почетниот екран</translation>
 <translation id="4558311620361989323">Кратенки на веб-страница</translation>
 <translation id="4561730552726921821">Успешна регистрација</translation>
 <translation id="4561979708150884304">Нема интернет-врска</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ml.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ml.xtb
index 29b8e60..1c9a0e1 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ml.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ml.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">സമയോചിത സഹായം</translation>
 <translation id="3285080554353377245">Chrome എങ്ങനെ ഉപയോഗിക്കാം എന്നതിനെക്കുറിച്ചുള്ള വീഡിയോകൾ</translation>
 <translation id="3288003805934695103">പേജ് റീലോഡുചെയ്യുന്നു</translation>
-<translation id="3290991969712132877">ഇവിടെ വേഗത്തിൽ എത്താൻ, കൂടുതൽ ഓപ്ഷനുകൾ മെനുവിൽ പോയി നിങ്ങളുടെ ഹോം സ്‌ക്രീനിലേക്ക് ഈ പേജ് ചേർക്കുക</translation>
 <translation id="3297344142967351106">ശബ്ദ സഹായം</translation>
 <translation id="3303414029551471755">ഉള്ളടക്കം ഡൗൺലോഡ് ചെയ്യുന്നതിലേക്ക് തുടരണോ?</translation>
 <translation id="3321367458490630980">താൽപ്പര്യം ചേർത്തു</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ടാബ്}other{<ph name="TAB_COUNT_MANY" /> ടാബുകൾ, <ph name="TAB_COUNT_INCOGNITO" /> അദൃശ്യ മോഡ്}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB കേബിൾ ഉപയോഗിച്ച് കണക്റ്റ് ചെയ്തു</translation>
-<translation id="4557685098773234337">ഇവിടെ വേഗത്തിൽ എത്താൻ, നിങ്ങളുടെ ഹോം സ്ക്രീനിലേക്ക് ഈ പേജ് ചേർക്കുക</translation>
 <translation id="4558311620361989323">വെബ്‌പേജ് കുറുക്കുവഴികൾ</translation>
 <translation id="4561730552726921821">രജിസ്റ്റർ ചെയ്തു</translation>
 <translation id="4561979708150884304">കണക്ഷൻ ഇല്ല</translation>
@@ -921,7 +919,7 @@
 സ്വകാര്യതാ സാൻഡ്‌ബോക്‌സ് ട്രയലുകൾ ഇപ്പോഴും സജീവ വികസന ഘട്ടത്തിലാണ്, തിരഞ്ഞെടുത്ത പ്രദേശങ്ങളിൽ അത് ലഭ്യമാണ്. ഇപ്പോഴത്തേക്ക്, മൂന്നാം കക്ഷി കുക്കികൾ പോലുള്ള നിലവിലെ വെബ് സാങ്കേതിക വിദ്യകൾ ഉപയോഗിക്കുന്നത് തുടരുന്നതിനൊപ്പം സൈറ്റുകൾക്ക് സ്വകാര്യതാ സാൻഡ്‌ബോക്‌സ് പരീക്ഷിക്കാവുന്നതാണ്.</translation>
 <translation id="6039379616847168523">അടുത്ത ടാബിലേക്ക് പോകുക</translation>
 <translation id="6040143037577758943">അടയ്ക്കുക</translation>
-<translation id="604124094241169006">സ്വപ്രേരിതം</translation>
+<translation id="604124094241169006">സ്വയമേവ</translation>
 <translation id="6042308850641462728">കൂടുതൽ</translation>
 <translation id="604996488070107836">ഒരു അജ്ഞാതമായ പിശക് കാരണം <ph name="FILE_NAME" /> ഡൗൺലോഡ് ചെയ്യാനായില്ല.</translation>
 <translation id="605721222689873409">YY</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb
index 51e3a33..d6eaa91 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mn.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Идэвхтэй тусламж</translation>
 <translation id="3285080554353377245">Chrome-г хэрхэн ашиглах тухай видео</translation>
 <translation id="3288003805934695103">Хуудсыг дахин ачаалж байна</translation>
-<translation id="3290991969712132877">Энд илүү шуурхай очихын тулд энэ хуудсыг Бусад сонголт товчлуураас Үндсэн нүүрэндээ нэмнэ үү</translation>
 <translation id="3297344142967351106">Дуут тусламж</translation>
 <translation id="3303414029551471755">Контентыг татаж авах үйлдлийг эхлүүлэх үү?</translation>
 <translation id="3321367458490630980">Сонирхол нэмсэн</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> таб}other{<ph name="TAB_COUNT_MANY" /> таб, <ph name="TAB_COUNT_INCOGNITO" /> нууцлалтай}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB кабелиар холбогдсон</translation>
-<translation id="4557685098773234337">Энд илүү хурдан очихын тулд энэ хуудсыг Үндсэн нүүрэндээ нэмнэ үү</translation>
 <translation id="4558311620361989323">Веб хуудaсны товчлол</translation>
 <translation id="4561730552726921821">Бүртгэл амжилттай</translation>
 <translation id="4561979708150884304">Холболт алга</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb
index 62e009d..73f5f70 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_mr.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">प्रोअ‍ॅक्टिव्ह मदत</translation>
 <translation id="3285080554353377245">Chrome कसे वापरावे याबद्दल व्हिडिओ</translation>
 <translation id="3288003805934695103">पृष्ठ रीलोड करणे</translation>
-<translation id="3290991969712132877">येथे झटपट येण्यासाठी, आणखी पर्याय बटणावरून हे पेज तुमच्या होम स्क्रीनवर जोडा</translation>
 <translation id="3297344142967351106">व्हॉइस साहाय्य</translation>
 <translation id="3303414029551471755">आशय डाउनलोड करणे सुरू ठेवायचे?</translation>
 <translation id="3321367458490630980">स्वारस्य जोडले आहे</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> टॅब}other{<ph name="TAB_COUNT_MANY" /> टॅब, <ph name="TAB_COUNT_INCOGNITO" /> गुप्त मोड}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB केबल वापरून कनेक्ट केला</translation>
-<translation id="4557685098773234337">येथे झटपट येण्यासाठी, हे पेज तुमच्या होम स्क्रीनवर जोडा</translation>
 <translation id="4558311620361989323">वेबपेज शॉर्टकट</translation>
 <translation id="4561730552726921821">नोंदणी यशस्वीरीत्या पूर्ण केली</translation>
 <translation id="4561979708150884304">कनेक्शन नाही</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ms.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ms.xtb
index 02646ab..112b3e5 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ms.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ms.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Bantuan Proaktif</translation>
 <translation id="3285080554353377245">Video tentang cara menggunakan Chrome</translation>
 <translation id="3288003805934695103">Memuatkan semula halaman</translation>
-<translation id="3290991969712132877">Untuk melawati halaman ini dengan lebih cepat, tambahkan halaman ini pada skrin Utama anda daripada butang Lagi pilihan</translation>
 <translation id="3297344142967351106">Bantuan suara</translation>
 <translation id="3303414029551471755">Teruskan memuat turun kandungan?</translation>
 <translation id="3321367458490630980">Minat ditambah</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> tab}other{<ph name="TAB_COUNT_MANY" /> tab, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Disambungkan menggunakan kabel USB</translation>
-<translation id="4557685098773234337">Untuk melawati halaman ini dengan lebih cepat, tambahkan halaman ini pada skrin Utama anda</translation>
 <translation id="4558311620361989323">Pintasan halaman web</translation>
 <translation id="4561730552726921821">Pendaftaran berjaya</translation>
 <translation id="4561979708150884304">Tiada sambungan</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_my.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_my.xtb
index d020747..c664d6d 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_my.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_my.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">မေးစရာမလိုဘဲပြသော အကူအညီ</translation>
 <translation id="3285080554353377245">Chrome အသုံးပြုနည်းအကြောင်း ဗီဒီယိုများ</translation>
 <translation id="3288003805934695103">စာမျက်နှာကို ပြန်ဖွင့်နေသည်</translation>
-<translation id="3290991969712132877">ဤနေရာသို့အမြန်ဝင်ကြည့်ရန် ဤစာမျက်နှာကို 'နောက်ထပ်' ရွေးစရာများခလုတ်မှ သင့် 'ပင်မစာမျက်နှာ' သို့ ထည့်ပါ</translation>
 <translation id="3297344142967351106">အသံ အကူအညီ</translation>
 <translation id="3303414029551471755">အကြောင်းအရာအား ဒေါင်းလုပ်လုပ်ရန် ရှေ့ဆက်မလား?</translation>
 <translation id="3321367458490630980">စိတ်ဝင်စားမှု ထည့်လိုက်သည်</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{တဘ် <ph name="TAB_COUNT_ONE" /> ခု}other{တဘ် <ph name="TAB_COUNT_MANY" /> ခု, ရုပ်ဖျက်တဘ်<ph name="TAB_COUNT_INCOGNITO" /> ခု}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB ကြိုးနှင့် ချိတ်ဆက်ထားသည်</translation>
-<translation id="4557685098773234337">ဤနေရာသို့ ပိုမိုမြန်ဆန်စွာဝင်ကြည့်ရန် ဤစာမျက်နှာကို သင့် 'ပင်မစာမျက်နှာ' သို့ထည့်ပါ</translation>
 <translation id="4558311620361989323">ဝဘ်စာမျက်နှာ ဖြတ်လမ်းလင့်ခ်များ</translation>
 <translation id="4561730552726921821">မှတ်ပုံတင်ပြီးပြီ</translation>
 <translation id="4561979708150884304">ချိတ်ဆက်မှု မရှိပါ</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ne.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ne.xtb
index cb0d529..3847bb4 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ne.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ne.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">क्रियाशील मद्दत</translation>
 <translation id="3285080554353377245">Chrome प्रयोग गर्ने तरिका देखाउने भिडियोहरू</translation>
 <translation id="3288003805934695103">पृष्ठलाई पुनः लोड गर्नुहोस्</translation>
-<translation id="3290991969712132877">यही पेजमा अझ छिटो जान 'थप विकल्पहरू' बटनमा क्लिक गरी आफ्नो होम स्क्रिनमा सो पेज हाल्नुहोस्</translation>
 <translation id="3297344142967351106">आवाज सहायता</translation>
 <translation id="3303414029551471755">सामग्री डाउनलोड गर्न अगाडि बढ्ने हो?</translation>
 <translation id="3321367458490630980">रुचि थपियो</translation>
@@ -638,7 +637,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ट्याब}other{<ph name="TAB_COUNT_MANY" /> वटा ट्याब, <ph name="TAB_COUNT_INCOGNITO" /> वटा इन्कोग्निटो ट्याब}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB केबल प्रयोग गरी कनेक्ट गरिएको छ</translation>
-<translation id="4557685098773234337">यही पेजमा अझ छिटो जान आफ्नो होम स्क्रिनमा सो पेज हाल्नुहोस्</translation>
 <translation id="4558311620361989323">वेबपृष्ठका सर्टकटहरू</translation>
 <translation id="4561730552726921821">दर्ता गरियो</translation>
 <translation id="4561979708150884304">इन्टरनेट छैन</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb
index a3e8eb2..0b58ab8b5 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_nl.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proactieve hulp</translation>
 <translation id="3285080554353377245">Video's over hoe je Chrome kunt gebruiken</translation>
 <translation id="3288003805934695103">Laad de pagina opnieuw</translation>
-<translation id="3290991969712132877">Voeg deze pagina via de knop 'Meer opties' aan je startscherm toe om hier sneller te komen</translation>
 <translation id="3297344142967351106">Spraakassistent</translation>
 <translation id="3303414029551471755">Doorgaan met het downloaden van de content?</translation>
 <translation id="3321367458490630980">Interesse toegevoegd</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> tabblad}other{<ph name="TAB_COUNT_MANY" /> tabbladen, <ph name="TAB_COUNT_INCOGNITO" /> incognitotabbladen}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Aangesloten via USB-kabel</translation>
-<translation id="4557685098773234337">Voeg deze pagina toe aan je startscherm om hier sneller te komen</translation>
 <translation id="4558311620361989323">Sneltoetsen voor webpagina's</translation>
 <translation id="4561730552726921821">Registratie afgerond</translation>
 <translation id="4561979708150884304">Geen verbinding</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_no.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_no.xtb
index e6c6f0f..58f13218 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_no.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_no.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktiv hjelp</translation>
 <translation id="3285080554353377245">Videoer om hvordan du bruker Chrome</translation>
 <translation id="3288003805934695103">Last inn siden på nytt</translation>
-<translation id="3290991969712132877">For å komme hit raskere, legg til denne siden på startskjermen via Flere alternativer-knappen</translation>
 <translation id="3297344142967351106">Talehjelp</translation>
 <translation id="3303414029551471755">Vil du gå videre med å laste ned innholdet?</translation>
 <translation id="3321367458490630980">Interessen er lagt til</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> fane}other{<ph name="TAB_COUNT_MANY" /> faner, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Tilkoblet med USB-kabel</translation>
-<translation id="4557685098773234337">For å komme hit raskere, legg til denne siden på startskjermen</translation>
 <translation id="4558311620361989323">Hurtigtaster for nettsider</translation>
 <translation id="4561730552726921821">Registreringen var vellykket</translation>
 <translation id="4561979708150884304">Ingen tilkobling</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb
index d75705f..6ccc60d 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_or.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">ସକ୍ରିୟ ସହାୟତା</translation>
 <translation id="3285080554353377245">କିପରି Chrome ବ୍ୟବହାର କରିବେ ସେ ବିଷୟରେ ଭିଡିଓଗୁଡ଼ିକ</translation>
 <translation id="3288003805934695103">ପୃଷ୍ଠା ରିଲୋଡ୍ ହେଉଛି</translation>
-<translation id="3290991969712132877">ଏଠାକୁ ଶୀଘ୍ର ଯିବା ପାଇଁ, ଅଧିକ ବିକଳ୍ପ ବଟନରୁ ଆପଣଙ୍କ ମୂଳ ସ୍କ୍ରିନରେ ଏହି ପୃଷ୍ଠାକୁ ଯୋଗ କରନ୍ତୁ</translation>
 <translation id="3297344142967351106">ଭଏସ୍ ସହାୟତା</translation>
 <translation id="3303414029551471755">ବିଷୟବସ୍ତୁ ଡାଉନ୍‍‍ଲୋଡ୍ କରିବା ପାଇଁ ଆଗକୁ ବଢ଼ିବେ?</translation>
 <translation id="3321367458490630980">ରୁଚି ଯୋଗ କରାଯାଇଛି</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" />ଟି ଟାବ୍}other{<ph name="TAB_COUNT_MANY" />ଟି ଟାବ୍, <ph name="TAB_COUNT_INCOGNITO" />ଟି ଇନକଗ୍ନିଟୋ}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB କେବୁଲ ମାଧ୍ୟମରେ ସଂଯୋଗ କରାଯାଇଛି</translation>
-<translation id="4557685098773234337">ଏଠାକୁ ଶୀଘ୍ର ଯିବା ପାଇଁ, ଆପଣଙ୍କ ମୂଳ ସ୍କ୍ରିନରେ ଏହି ପୃଷ୍ଠାକୁ ଯୋଗ କରନ୍ତୁ</translation>
 <translation id="4558311620361989323">ୱେବ୍‍ପୃଷ୍ଟା ସର୍ଟକଟ୍</translation>
 <translation id="4561730552726921821">ପଞ୍ଜିକରଣ ସଫଳ ହୋଇଛି</translation>
 <translation id="4561979708150884304">କୌଣସି ସଂଯୋଗ ନାହିଁ</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pa.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pa.xtb
index 496011f..78fc00b 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pa.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pa.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">ਚੁਸਤ ਮਦਦ</translation>
 <translation id="3285080554353377245">Chrome ਨੂੰ ਵਰਤਣ ਦੇ ਤਰੀਕੇ ਬਾਰੇ ਵੀਡੀਓ</translation>
 <translation id="3288003805934695103">ਪੰਨਾ ਦੁਬਾਰਾ ਲੋਡ ਕਰੋ</translation>
-<translation id="3290991969712132877">ਇੱਥੇ ਤੇਜ਼ੀ ਨਾਲ ਪਹੁੰਚ ਕਰਨ ਲਈ, 'ਹੋਰ ਵਿਕਲਪ' ਬਟਨ ਤੋਂ ਇਸ ਪੰਨੇ ਨੂੰ ਆਪਣੀ ਹੋਮ ਸਕ੍ਰੀਨ ‘ਤੇ ਸ਼ਾਮਲ ਕਰੋ</translation>
 <translation id="3297344142967351106">ਅਵਾਜ਼ੀ ਸਹਾਇਕ</translation>
 <translation id="3303414029551471755">ਕੀ ਸਮੱਗਰੀ ਡਾਊਨਲੋਡ ਕਰਨਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?</translation>
 <translation id="3321367458490630980">ਦਿਲਚਸਪੀ ਸ਼ਾਮਲ ਕੀਤੀ ਗਈ</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ਟੈਬ}one{<ph name="TAB_COUNT_MANY" /> ਟੈਬ, <ph name="TAB_COUNT_INCOGNITO" /> ਇਨਕੋਗਨਿਟੋ}other{<ph name="TAB_COUNT_MANY" /> ਟੈਬਾਂ, <ph name="TAB_COUNT_INCOGNITO" /> ਇਨਕੋਗਨਿਟੋ}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB ਕੇਬਲ ਨਾਲ ਕਨੈਕਟ ਹੈ</translation>
-<translation id="4557685098773234337">ਇੱਥੇ ਵਧੇਰੇ ਤੇਜ਼ੀ ਨਾਲ ਪਹੁੰਚ ਕਰਨ ਲਈ, ਇਸ ਪੰਨੇ ਨੂੰ ਆਪਣੀ ਹੋਮ ਸਕ੍ਰੀਨ ‘ਤੇ ਸ਼ਾਮਲ ਕਰੋ</translation>
 <translation id="4558311620361989323">ਵੈੱਬ ਪੰਨੇ ਦੇ ਸ਼ਾਰਟਕੱਟ</translation>
 <translation id="4561730552726921821">ਰਜਿਸਟਰੇਸ਼ਨ ਕਰਨਾ ਸਫਲ ਰਿਹਾ</translation>
 <translation id="4561979708150884304">ਕੋਈ ਕਨੈਕਸ਼ਨ ਨਹੀਂ</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb
index 230e3ac..d79b1f133 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pl.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Aktywna pomoc</translation>
 <translation id="3285080554353377245">Filmy na temat korzystania z Chrome</translation>
 <translation id="3288003805934695103">Odśwież stronę</translation>
-<translation id="3290991969712132877">Aby móc szybciej otwierać tę stronę, dodaj ją do ekranu głównego, używając przycisku Więcej opcji.</translation>
 <translation id="3297344142967351106">Pomoc głosowa</translation>
 <translation id="3303414029551471755">Przejść do pobrania treści?</translation>
 <translation id="3321367458490630980">Zainteresowanie zostało dodane</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> karta}few{<ph name="TAB_COUNT_MANY" /> karty, <ph name="TAB_COUNT_INCOGNITO" /> incognito}many{<ph name="TAB_COUNT_MANY" /> kart, <ph name="TAB_COUNT_INCOGNITO" /> incognito}other{<ph name="TAB_COUNT_MANY" /> karty, <ph name="TAB_COUNT_INCOGNITO" /> incognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Podłączony za pomocą kabla USB</translation>
-<translation id="4557685098773234337">Aby móc szybciej otwierać tę stronę, dodaj ją do ekranu głównego.</translation>
 <translation id="4558311620361989323">Skróty stron internetowych</translation>
 <translation id="4561730552726921821">Rejestracja się udała</translation>
 <translation id="4561979708150884304">Brak połączenia</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb
index ab50462..60b14f54 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-BR.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Ajuda proativa</translation>
 <translation id="3285080554353377245">Vídeos sobre como usar o Chrome</translation>
 <translation id="3288003805934695103">Atualizar a página</translation>
-<translation id="3290991969712132877">Para chegar aqui mais rapidamente, adicione esta página à sua tela inicial usando o botão "Mais opções"</translation>
 <translation id="3297344142967351106">Assistente por voz</translation>
 <translation id="3303414029551471755">Continuar com o download do conteúdo?</translation>
 <translation id="3321367458490630980">Interesse adicionado</translation>
@@ -640,7 +639,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> guia}one{<ph name="TAB_COUNT_MANY" /> guia e <ph name="TAB_COUNT_INCOGNITO" /> guia anônima}other{<ph name="TAB_COUNT_MANY" /> guias e <ph name="TAB_COUNT_INCOGNITO" /> guia anônima}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Conectado com um cabo USB</translation>
-<translation id="4557685098773234337">Para chegar aqui mais rapidamente, adicione esta página à sua tela inicial</translation>
 <translation id="4558311620361989323">Atalhos de páginas da Web</translation>
 <translation id="4561730552726921821">Registro concluído</translation>
 <translation id="4561979708150884304">Sem conexão</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-PT.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-PT.xtb
index f9a3a08..b5081007 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-PT.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_pt-PT.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Ajuda proativa</translation>
 <translation id="3285080554353377245">Vídeos sobre como utilizar o Chrome</translation>
 <translation id="3288003805934695103">Atualizar a página</translation>
-<translation id="3290991969712132877">Para aceder aqui mais rapidamente, adicione esta página ao ecrã principal a partir do botão Mais opções.</translation>
 <translation id="3297344142967351106">Assistente de voz</translation>
 <translation id="3303414029551471755">Pretende transferir o conteúdo?</translation>
 <translation id="3321367458490630980">Interesse adicionado</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> separador}other{<ph name="TAB_COUNT_MANY" /> separadores, <ph name="TAB_COUNT_INCOGNITO" /> de navegação anónima}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Ligado com cabo USB</translation>
-<translation id="4557685098773234337">Adicione esta página ao ecrã principal para aceder à mesma mais rapidamente.</translation>
 <translation id="4558311620361989323">Atalhos da página Web</translation>
 <translation id="4561730552726921821">Registo efetuado com êxito</translation>
 <translation id="4561979708150884304">Sem ligação</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ro.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ro.xtb
index b90e2f0..f95d9d2 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ro.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ro.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Ajutor proactiv</translation>
 <translation id="3285080554353377245">Videoclipuri despre folosirea browserului Chrome</translation>
 <translation id="3288003805934695103">să reîncarci pagina;</translation>
-<translation id="3290991969712132877">Pentru a o accesa mai ușor, adaugă pagina pe ecranul de pornire, folosind butonul Mai multe opțiuni</translation>
 <translation id="3297344142967351106">Asistență vocală</translation>
 <translation id="3303414029551471755">Continui pentru descărcarea conținutului?</translation>
 <translation id="3321367458490630980">Categoria de interese a fost adăugată</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> filă}few{<ph name="TAB_COUNT_MANY" /> file, <ph name="TAB_COUNT_INCOGNITO" /> incognito}other{<ph name="TAB_COUNT_MANY" /> de file, <ph name="TAB_COUNT_INCOGNITO" /> incognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Conectat cu un cablu USB</translation>
-<translation id="4557685098773234337">Pentru o a accesa mai ușor, adaugă pagina pe ecranul de pornire</translation>
 <translation id="4558311620361989323">Comenzi rapide pentru pagini web</translation>
 <translation id="4561730552726921821">S-a realizat înregistrarea</translation>
 <translation id="4561979708150884304">Nicio conexiune</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ru.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ru.xtb
index 23848762..2f63f06 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ru.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ru.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Помощь в нужный момент</translation>
 <translation id="3285080554353377245">Видео о том, как пользоваться Chrome</translation>
 <translation id="3288003805934695103">Обновите страницу.</translation>
-<translation id="3290991969712132877">Для быстрого доступа добавьте эту страницу на главный экран, нажав кнопку настроек "Ещё".</translation>
 <translation id="3297344142967351106">Голосовой помощник</translation>
 <translation id="3303414029551471755">Скачать?</translation>
 <translation id="3321367458490630980">Интерес добавлен.</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> вкладка}one{Вкладок: <ph name="TAB_COUNT_MANY" />, <ph name="TAB_COUNT_INCOGNITO" /> вкладка инкогнито}few{Вкладок: <ph name="TAB_COUNT_MANY" />, <ph name="TAB_COUNT_INCOGNITO" /> вкладки инкогнито}many{Вкладок: <ph name="TAB_COUNT_MANY" />, <ph name="TAB_COUNT_INCOGNITO" /> вкладок инкогнито}other{Вкладок: <ph name="TAB_COUNT_MANY" />, <ph name="TAB_COUNT_INCOGNITO" /> вкладки инкогнито}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Подключено с помощью USB-кабеля</translation>
-<translation id="4557685098773234337">Для быстрого доступа добавьте эту страницу на главный экран</translation>
 <translation id="4558311620361989323">Работа с веб-страницами</translation>
 <translation id="4561730552726921821">Регистрация выполнена</translation>
 <translation id="4561979708150884304">Нет подключения</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_si.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_si.xtb
index dce3f05..6a744be8 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_si.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_si.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">කල්තියා උදවු</translation>
 <translation id="3285080554353377245">Chrome භාවිත කරන ආකාරය පිළිබඳ වීඩියෝ</translation>
 <translation id="3288003805934695103">පිටුව නැවත පූරණය කරමින්</translation>
-<translation id="3290991969712132877">ඉක්මණින් මෙහි පැමිණීමට, තවත් විකල්ප බොත්තමෙන් මෙම පිටුව ඔබගේ මුල් තිරයට එක් කරන්න</translation>
 <translation id="3297344142967351106">හඬ සහාය</translation>
 <translation id="3303414029551471755">අන්තර්ගතය බාගැනීම අරඹන්නද?</translation>
 <translation id="3321367458490630980">ලැදිකම එක් කරන ලදි</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{ටැබ <ph name="TAB_COUNT_ONE" />}one{ටැබ <ph name="TAB_COUNT_MANY" />, අප්‍රකට <ph name="TAB_COUNT_INCOGNITO" />}other{ටැබ <ph name="TAB_COUNT_MANY" />, අප්‍රකට <ph name="TAB_COUNT_INCOGNITO" />}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB කේබලය සමගින් සම්බන්ධයි</translation>
-<translation id="4557685098773234337">ඉක්මණින් මෙහි පැමිණීමට, මෙම පිටුව ඔබගේ මුල් තිරයට එක් කරන්න</translation>
 <translation id="4558311620361989323">වෙබ් පිටු කෙටි මං</translation>
 <translation id="4561730552726921821">ලියාපදිංචිය සාර්ථක විය</translation>
 <translation id="4561979708150884304">සබැඳුමක් නැත</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb
index 5899012..7582899e 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sk.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktívna pomoc</translation>
 <translation id="3285080554353377245">Videá, ako používať Chrome</translation>
 <translation id="3288003805934695103">Opätovne načítať stránku</translation>
-<translation id="3290991969712132877">Ak sa sem chcete dostať rýchlejšie, pridajte si túto stránku na plochu z tlačidla Ďalšie možnosti</translation>
 <translation id="3297344142967351106">Hlasová pomoc</translation>
 <translation id="3303414029551471755">Pokračovať a stiahnuť obsah?</translation>
 <translation id="3321367458490630980">Bol pridaný záujem</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> karta}few{<ph name="TAB_COUNT_MANY" /> karty, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}many{<ph name="TAB_COUNT_MANY" /> tabs, <ph name="TAB_COUNT_INCOGNITO" /> incognito}other{<ph name="TAB_COUNT_MANY" /> kariet, <ph name="TAB_COUNT_INCOGNITO" /> inkognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Pripojené káblom USB</translation>
-<translation id="4557685098773234337">Ak sa sem chcete dostať rýchlejšie, pridajte si túto stránku na plochu</translation>
 <translation id="4558311620361989323">Skratky pre webové stránky</translation>
 <translation id="4561730552726921821">Registrácia je úspešná</translation>
 <translation id="4561979708150884304">Bez pripojenia</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sl.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sl.xtb
index 14b227f..b50810d 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sl.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sl.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktivna pomoč</translation>
 <translation id="3285080554353377245">Videoposnetki o uporabi Chroma</translation>
 <translation id="3288003805934695103">znova naložiti stran</translation>
-<translation id="3290991969712132877">Če želite do te strani dostopati hitreje, jo z gumbom za več možnosti dodajte na začetni zaslon.</translation>
 <translation id="3297344142967351106">Glasovna pomoč</translation>
 <translation id="3303414029551471755">Ali želite prenesti vsebino?</translation>
 <translation id="3321367458490630980">Zanimanje je dodano.</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> zavihek}one{<ph name="TAB_COUNT_MANY" /> zavihek, št. anonimnih zavihkov: <ph name="TAB_COUNT_INCOGNITO" />}two{<ph name="TAB_COUNT_MANY" /> zavihka, št. anonimnih zavihkov: <ph name="TAB_COUNT_INCOGNITO" />}few{<ph name="TAB_COUNT_MANY" /> zavihki, št. anonimnih zavihkov: <ph name="TAB_COUNT_INCOGNITO" />}other{<ph name="TAB_COUNT_MANY" /> zavihkov, št. anonimnih zavihkov: <ph name="TAB_COUNT_INCOGNITO" />}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Povezano s kablom USB</translation>
-<translation id="4557685098773234337">Za hitrejši dostop dodajte to stran na začetni zaslon.</translation>
 <translation id="4558311620361989323">Bližnjice za spletne strani</translation>
 <translation id="4561730552726921821">Registracija je uspela</translation>
 <translation id="4561979708150884304">Ni povezave</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sq.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sq.xtb
index ff5648f..2a92ac1 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sq.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sq.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Ndihmë proaktive</translation>
 <translation id="3285080554353377245">Video rreth mënyrës se si të përdorësh Chrome</translation>
 <translation id="3288003805934695103">Të ringarkosh faqen</translation>
-<translation id="3290991969712132877">Për të ardhur më shpejt këtu, shtoje këtë faqe në "Ekranin tënd bazë" nga butoni "Opsione të tjera"</translation>
 <translation id="3297344142967351106">Ndihma zanore</translation>
 <translation id="3303414029551471755">Të vazhdohet me shkarkimin e përmbajtjes?</translation>
 <translation id="3321367458490630980">Interesi u shtua</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> skedë}other{<ph name="TAB_COUNT_MANY" /> skeda, <ph name="TAB_COUNT_INCOGNITO" /> të fshehta}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">I lidhur me kabllo USB</translation>
-<translation id="4557685098773234337">Për të ardhur këtu më shpejt, shtoje këtë faqe në "Ekranin tënd bazë"</translation>
 <translation id="4558311620361989323">Shkurtoret e faqes së uebit</translation>
 <translation id="4561730552726921821">Regjistrimi ishte i suksesshëm</translation>
 <translation id="4561979708150884304">Nuk ka lidhje</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sr-Latn.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sr-Latn.xtb
index a703608..66b5d0f 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sr-Latn.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sr-Latn.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktivna pomoć</translation>
 <translation id="3285080554353377245">Video snimci o tome kako da koristite Chrome</translation>
 <translation id="3288003805934695103">da ponovo učitate stranicu</translation>
-<translation id="3290991969712132877">Da brže pristupali ovoj stranici, dodajte je na početni ekran pomoću dugmeta Još opcija</translation>
 <translation id="3297344142967351106">Glasovna pomoć</translation>
 <translation id="3303414029551471755">Želite li da nastavite sa preuzimanjem sadržaja?</translation>
 <translation id="3321367458490630980">Interesovanje je dodato</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> kartica}one{<ph name="TAB_COUNT_MANY" /> kartica, <ph name="TAB_COUNT_INCOGNITO" /> bez arhiviranja}few{<ph name="TAB_COUNT_MANY" /> kartice, <ph name="TAB_COUNT_INCOGNITO" /> bez arhiviranja}other{<ph name="TAB_COUNT_MANY" /> kartica, <ph name="TAB_COUNT_INCOGNITO" /> bez arhiviranja}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Povezani ste pomoću USB kabla</translation>
-<translation id="4557685098773234337">Da biste brže pristupali ovoj stranici, dodajte je na početni ekran</translation>
 <translation id="4558311620361989323">Prečice za veb-stranice</translation>
 <translation id="4561730552726921821">Registracija je uspela</translation>
 <translation id="4561979708150884304">Veza nije uspostavljena</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sr.xtb
index 11b5904..80e647d 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sr.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sr.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Проактивна помоћ</translation>
 <translation id="3285080554353377245">Видео снимци о томе како да користите Chrome</translation>
 <translation id="3288003805934695103">да поново учитате страницу</translation>
-<translation id="3290991969712132877">Да брже приступали овој страници, додајте је на почетни екран помоћу дугмета Још опција</translation>
 <translation id="3297344142967351106">Гласовна помоћ</translation>
 <translation id="3303414029551471755">Желите ли да наставите са преузимањем садржаја?</translation>
 <translation id="3321367458490630980">Интересовање је додато</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> картица}one{<ph name="TAB_COUNT_MANY" /> картица, <ph name="TAB_COUNT_INCOGNITO" /> без архивирања}few{<ph name="TAB_COUNT_MANY" /> картице, <ph name="TAB_COUNT_INCOGNITO" /> без архивирања}other{<ph name="TAB_COUNT_MANY" /> картица, <ph name="TAB_COUNT_INCOGNITO" /> без архивирања}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Повезани сте помоћу USB кабла</translation>
-<translation id="4557685098773234337">Да бисте брже приступали овој страници, додајте је на почетни екран</translation>
 <translation id="4558311620361989323">Пречице за веб-странице</translation>
 <translation id="4561730552726921821">Регистрација је успела</translation>
 <translation id="4561979708150884304">Веза није успостављена</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb
index 9ea5b80..2fbcdff 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sv.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktiv hjälp</translation>
 <translation id="3285080554353377245">Videor om hur du använder Chrome</translation>
 <translation id="3288003805934695103">läsa in sidan igen</translation>
-<translation id="3290991969712132877">Lägg till sidan på startskärmen med knappen Fler alternativ, så att du kommer åt den snabbare</translation>
 <translation id="3297344142967351106">Rösthjälp</translation>
 <translation id="3303414029551471755">Vill du ladda ned innehållet?</translation>
 <translation id="3321367458490630980">Intresset har lagts till</translation>
@@ -640,7 +639,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> flik}other{<ph name="TAB_COUNT_MANY" /> flikar, <ph name="TAB_COUNT_INCOGNITO" /> inkognitoflikar}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Ansluten med USB-kabel</translation>
-<translation id="4557685098773234337">Lägg till sidan på startskärmen så att du kommer åt den snabbare</translation>
 <translation id="4558311620361989323">Kortkommandon på webbsidor</translation>
 <translation id="4561730552726921821">Registreringen lyckades</translation>
 <translation id="4561979708150884304">Ingen anslutning</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sw.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sw.xtb
index 7afbf542b..14a2c97 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_sw.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_sw.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Usaidizi Hima</translation>
 <translation id="3285080554353377245">Video kuhusu jinsi ya kutumia Chrome</translation>
 <translation id="3288003805934695103">Kupakia upya ukurasa</translation>
-<translation id="3290991969712132877">Ili uweze kuufikia ukurasa huu kwa haraka zaidi, uweke kwenye Skrini yako ya kwanza kupitia kitufe cha Chaguo zaidi</translation>
 <translation id="3297344142967351106">Usaidizi wa kutumia sauti</translation>
 <translation id="3303414029551471755">Ungependa kuendelea kupakua maudhui?</translation>
 <translation id="3321367458490630980">Jambo linalokuvutia limewekwa</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{Kichupo <ph name="TAB_COUNT_ONE" />}other{Vichupo <ph name="TAB_COUNT_MANY" />, <ph name="TAB_COUNT_INCOGNITO" /> fiche}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Imeunganishwa kwa kutumia kebo ya USB</translation>
-<translation id="4557685098773234337">Ili uweze kuufikia ukurasa huu kwa haraka zaidi, uweke kwenye Skrini yako ya kwanza</translation>
 <translation id="4558311620361989323">Njia za mikato za ukurasa wa wavuti</translation>
 <translation id="4561730552726921821">Imesajiliwa</translation>
 <translation id="4561979708150884304">Hakuna muunganisho</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ta.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ta.xtb
index 67ae12b..15e8d01 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ta.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ta.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">முன்கூட்டிய உதவி</translation>
 <translation id="3285080554353377245">Chromeமை எப்படிப் பயன்படுத்துவது என்பது குறித்த வீடியோக்கள்</translation>
 <translation id="3288003805934695103">பக்கத்தை மீண்டும் ஏற்றுதல்</translation>
-<translation id="3290991969712132877">விரைவாக இந்தப் பக்கத்தை அணுக, கூடுதல் விருப்பத்தேர்வுகள் பட்டனைப் பயன்படுத்தி இதை உங்கள் முகப்புத் திரையில் சேர்க்கவும்</translation>
 <translation id="3297344142967351106">குரல் உதவி</translation>
 <translation id="3303414029551471755">உள்ளடக்கத்தைப் பதிவிறக்குவதைத் தொடரவா?</translation>
 <translation id="3321367458490630980">ஆர்வம் சேர்க்கப்பட்டது</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> பக்கம்}other{<ph name="TAB_COUNT_MANY" /> பக்கங்கள், <ph name="TAB_COUNT_INCOGNITO" /> மறைநிலை}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB கேபிள் மூலம் இணைக்கப்பட்டது</translation>
-<translation id="4557685098773234337">இந்தப் பக்கத்தை விரைவாக அணுக, இதை உங்கள் முகப்புத் திரையில் சேர்க்கவும்</translation>
 <translation id="4558311620361989323">இணையப் பக்கக் ஷார்ட்கட்கள்</translation>
 <translation id="4561730552726921821">பதிவுசெய்துவிட்டீர்கள்</translation>
 <translation id="4561979708150884304">இணைப்பு இல்லை</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb
index 80d04d4..833e12b 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_te.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">తనకు తానుగా సహాయం</translation>
 <translation id="3285080554353377245">Chromeను ఎలా ఉపయోగించాలనే దానికి సంబంధించిన వీడియోలు</translation>
 <translation id="3288003805934695103">పేజీని మళ్లీ లోడ్ చేయడం</translation>
-<translation id="3290991969712132877">ఈ పేజీని త్వరగా యాక్సెస్ చేయడానికి, 'మరిన్ని ఎంపికలు' బటన్ నుండి మీ మొదటి స్క్రీన్‌కు దీనిని జోడించండి</translation>
 <translation id="3297344142967351106">వాయిస్ సహాయం</translation>
 <translation id="3303414029551471755">కంటెంట్‌ను డౌన్‌లోడ్ చేయడం కొనసాగించాలా?</translation>
 <translation id="3321367458490630980">ఆసక్తి ఉన్న అంశం జోడించబడింది</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ట్యాబ్}other{<ph name="TAB_COUNT_MANY" /> ట్యాబ్‌లు, <ph name="TAB_COUNT_INCOGNITO" /> అజ్ఞాత ట్యాబ్}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB కేబుల్‌తో కనెక్ట్ చేయబడింది</translation>
-<translation id="4557685098773234337">ఇక్కడికి త్వరగా చేరుకోవడనికి, ఈ పేజీని మీ మొదటి స్క్రీన్‌కు జోడించండి</translation>
 <translation id="4558311620361989323">వెబ్‌పేజీ షార్ట్‌క‌ట్‌లు</translation>
 <translation id="4561730552726921821">రిజిస్ట్రేషన్ విజయవంతమైంది</translation>
 <translation id="4561979708150884304">కనెక్షన్ లేదు</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_th.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_th.xtb
index a10d256a..68aad77 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_th.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_th.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">ความช่วยเหลือแบบเสนอโดยไม่ต้องขอ</translation>
 <translation id="3285080554353377245">วิดีโอเกี่ยวกับวิธีใช้ Chrome</translation>
 <translation id="3288003805934695103">โหลดหน้าใหม่</translation>
-<translation id="3290991969712132877">หากต้องการไปที่หน้านี้ให้เร็วขึ้น ให้เพิ่มลงในหน้าจอหลักโดยใช้ปุ่ม "ตัวเลือกเพิ่มเติม"</translation>
 <translation id="3297344142967351106">เสียงผู้ช่วย</translation>
 <translation id="3303414029551471755">ต้องการดำเนินการดาวน์โหลดเนื้อหานี้ไหม</translation>
 <translation id="3321367458490630980">เพิ่มความสนใจแล้ว</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> แท็บ}other{<ph name="TAB_COUNT_MANY" /> แท็บ <ph name="TAB_COUNT_INCOGNITO" /> แท็บที่ไม่ระบุตัวตน}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">เชื่อมต่อด้วยสาย USB แล้ว</translation>
-<translation id="4557685098773234337">หากต้องการไปที่นี่ให้เร็วขึ้น ให้เพิ่มหน้านี้ในหน้าจอหลัก</translation>
 <translation id="4558311620361989323">แป้นพิมพ์ลัดสำหรับหน้าเว็บ</translation>
 <translation id="4561730552726921821">ลงทะเบียนสำเร็จ</translation>
 <translation id="4561979708150884304">ไม่มีการเชื่อมต่อ</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_tr.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_tr.xtb
index ffbea907..ba99462a 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_tr.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_tr.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Proaktif Yardım</translation>
 <translation id="3285080554353377245">Chrome'un nasıl kullanılacağıyla ilgili videolar</translation>
 <translation id="3288003805934695103">Sayfayı yeniden yükleme</translation>
-<translation id="3290991969712132877">Buraya daha hızlı ulaşmak için bu sayfayı Diğer seçenekler düğmesinden Ana ekranınıza ekleyin</translation>
 <translation id="3297344142967351106">Sesli yardım</translation>
 <translation id="3303414029551471755">İçeriği indirme işlemine başlansın mı?</translation>
 <translation id="3321367458490630980">İlgi alanı eklendi</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> sekme}other{<ph name="TAB_COUNT_MANY" /> sekme, <ph name="TAB_COUNT_INCOGNITO" /> gizli mod}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB kablosuyla bağlandı</translation>
-<translation id="4557685098773234337">Buraya daha hızlı ulaşmak için bu sayfayı ana ekranınıza ekleyin</translation>
 <translation id="4558311620361989323">Web sayfası kısayolları</translation>
 <translation id="4561730552726921821">Kayıt başarılı oldu</translation>
 <translation id="4561979708150884304">Bağlantı yok</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_uk.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_uk.xtb
index c425f2e..7ee0d147 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_uk.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_uk.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Активна допомога</translation>
 <translation id="3285080554353377245">Відеоінструкції щодо користування веб-переглядачем Chrome</translation>
 <translation id="3288003805934695103">перезавантажити сторінку</translation>
-<translation id="3290991969712132877">Щоб швидше переходити на цю сторінку, додайте її на головний екран через кнопку "Більше опцій"</translation>
 <translation id="3297344142967351106">Голосова допомога</translation>
 <translation id="3303414029551471755">Завантажити вміст?</translation>
 <translation id="3321367458490630980">Інтерес додано</translation>
@@ -572,7 +571,7 @@
 <translation id="4137746084635924146">Поточна мова пристрою</translation>
 <translation id="4141536112466364990">Ознайомтеся з Chrome</translation>
 <translation id="4162867837470729563">Список параметрів спільного доступу відкрито на всю висоту.</translation>
-<translation id="4165986682804962316">Налаштування сайту</translation>
+<translation id="4165986682804962316">Налаштування сайтів</translation>
 <translation id="4170011742729630528">Служба не доступна. Повторіть спробу пізніше.</translation>
 <translation id="4177222230309051052">Переглядайте всі закладки</translation>
 <translation id="4181841719683918333">Мови</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> вкладка}one{<ph name="TAB_COUNT_MANY" /> вкладка, <ph name="TAB_COUNT_INCOGNITO" /> анонімно}few{<ph name="TAB_COUNT_MANY" /> вкладки, <ph name="TAB_COUNT_INCOGNITO" /> анонімно}many{<ph name="TAB_COUNT_MANY" /> вкладок, <ph name="TAB_COUNT_INCOGNITO" /> анонімно}other{<ph name="TAB_COUNT_MANY" /> вкладки, <ph name="TAB_COUNT_INCOGNITO" /> анонімно}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Підключено за допомогою кабелю USB</translation>
-<translation id="4557685098773234337">Щоб швидше переходити на цю сторінку, додайте її на головний екран</translation>
 <translation id="4558311620361989323">Комбінації клавіш для роботи з веб-сторінками</translation>
 <translation id="4561730552726921821">Реєстрацію виконано</translation>
 <translation id="4561979708150884304">Немає з’єднання</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ur.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ur.xtb
index d96c05e..91c36b0f 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ur.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ur.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">فعال مدد</translation>
 <translation id="3285080554353377245">‏Chrome استعمال کرنے کے طریقے سے متعلق ویڈیوز</translation>
 <translation id="3288003805934695103">صفحہ دوبارہ لوڈ ہو رہا ہے</translation>
-<translation id="3290991969712132877">یہاں تیزی سے پہنچنے کے لئے، مزید اختیارات کے بٹن سے اس صفحے کو اپنی ہوم اسکرین میں شامل کریں</translation>
 <translation id="3297344142967351106">صوتی معاونت</translation>
 <translation id="3303414029551471755">مواد ڈاؤن لوڈ کرنے کیلئے آگے بڑھیں؟</translation>
 <translation id="3321367458490630980">دلچسپی کو شامل کیا گیا</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ٹیب}other{<ph name="TAB_COUNT_MANY" /> ٹیبز، <ph name="TAB_COUNT_INCOGNITO" /> پوشیدگی}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">‏USB کیبل کے ساتھ منسلک ہے</translation>
-<translation id="4557685098773234337">یہاں تیزی سے پہنچنے کے لئے اس صفحے کو اپنی ہوم اسکرین میں شامل کریں</translation>
 <translation id="4558311620361989323">ویب صفحہ شارٹ کٹس</translation>
 <translation id="4561730552726921821">رجسٹریشن مکمل ہو گئی</translation>
 <translation id="4561979708150884304">کوئی کنکشن نہیں</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_uz.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_uz.xtb
index 080502d..36748edc 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_uz.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_uz.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Kerakli paytda yordam</translation>
 <translation id="3285080554353377245">Chrome qanday ishlatilishi haqida video</translation>
 <translation id="3288003805934695103">Sahifani yangilash</translation>
-<translation id="3290991969712132877">Bu sahifani tezroq ochish uchun Yana tugmasi orqali Bosh ekranga chiqaring</translation>
 <translation id="3297344142967351106">Ovozli yordam</translation>
 <translation id="3303414029551471755">Yuklab olinsinmi?</translation>
 <translation id="3321367458490630980">Qiziqish kiritildi</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> ta varaq}other{<ph name="TAB_COUNT_MANY" /> ta varaq, <ph name="TAB_COUNT_INCOGNITO" /> tasi inkognito}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">USB kabel bilan ulangan</translation>
-<translation id="4557685098773234337">Bu sahifani tezroq ochish uchun uni Bosh ekranga chiqaring</translation>
 <translation id="4558311620361989323">Veb-sahifalar bilan ishlash</translation>
 <translation id="4561730552726921821">Registratsiya qilindi</translation>
 <translation id="4561979708150884304">Internetga ulanmagansiz</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_vi.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_vi.xtb
index 641c791..a6577a4 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_vi.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_vi.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Trợ giúp chủ động</translation>
 <translation id="3285080554353377245">Video về cách sử dụng Chrome</translation>
 <translation id="3288003805934695103">Đang tải lại trang</translation>
-<translation id="3290991969712132877">Để truy cập nhanh hơn, hãy thêm trang này vào Màn hình chính từ nút Tùy chọn khác</translation>
 <translation id="3297344142967351106">Trợ lý thoại</translation>
 <translation id="3303414029551471755">Tiếp tục tải xuống nội dung?</translation>
 <translation id="3321367458490630980">Đã thêm mối quan tâm</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> thẻ}other{<ph name="TAB_COUNT_MANY" /> thẻ, <ph name="TAB_COUNT_INCOGNITO" /> ẩn danh}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Đã kết nối bằng cáp USB</translation>
-<translation id="4557685098773234337">Để truy cập trang này nhanh hơn, hãy thêm trang vào Màn hình chính</translation>
 <translation id="4558311620361989323">Phím tắt cho trang web</translation>
 <translation id="4561730552726921821">Đã đăng ký thành công</translation>
 <translation id="4561979708150884304">Không có kết nối</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb
index 0366229..b63b550 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-CN.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">主动帮助</translation>
 <translation id="3285080554353377245">介绍如何使用 Chrome 的视频</translation>
 <translation id="3288003805934695103">重新加载网页</translation>
-<translation id="3290991969712132877">若要更快速地访问该网页,请通过“更多选项”按钮将它添加到主屏幕</translation>
 <translation id="3297344142967351106">语音助理</translation>
 <translation id="3303414029551471755">要开始下载该内容吗?</translation>
 <translation id="3321367458490630980">添加了兴趣</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> 个标签页}other{<ph name="TAB_COUNT_MANY" /> 个标签页,<ph name="TAB_COUNT_INCOGNITO" /> 个无痕式标签页}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">已使用 USB 线连接到手机</translation>
-<translation id="4557685098773234337">若要更快速地访问该网页,请将它添加到主屏幕</translation>
 <translation id="4558311620361989323">网页快捷键</translation>
 <translation id="4561730552726921821">注册成功</translation>
 <translation id="4561979708150884304">无网络连接</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb
index ed1cbb4..2b6521e 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">主動提供協助</translation>
 <translation id="3285080554353377245">關於如何使用 Chrome 的影片</translation>
 <translation id="3288003805934695103">重新載入網頁</translation>
-<translation id="3290991969712132877">如要更快速開啟此網頁,請使用「更多選項」按鈕將此網頁新增到主畫面</translation>
 <translation id="3297344142967351106">語音助手</translation>
 <translation id="3303414029551471755">繼續下載內容?</translation>
 <translation id="3321367458490630980">已新增興趣</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> 個分頁}other{<ph name="TAB_COUNT_MANY" /> 個分頁、<ph name="TAB_COUNT_INCOGNITO" /> 個無痕式分頁}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">已使用 USB 連接線連接</translation>
-<translation id="4557685098773234337">如要迅速開啟此網頁,請將此網頁新增至主畫面</translation>
 <translation id="4558311620361989323">網頁快速鍵</translation>
 <translation id="4561730552726921821">註冊成功</translation>
 <translation id="4561979708150884304">沒有連線</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-TW.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-TW.xtb
index b54bac1..cba044c 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-TW.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-TW.xtb
@@ -436,7 +436,6 @@
 <translation id="3284510035090979597">主動提供協助</translation>
 <translation id="3285080554353377245">關於如何使用 Chrome 的影片</translation>
 <translation id="3288003805934695103">重新載入網頁</translation>
-<translation id="3290991969712132877">如要更快速地前往這個網頁,請透過「更多」選項按鈕,將網頁新增到主畫面</translation>
 <translation id="3297344142967351106">語音協助</translation>
 <translation id="3303414029551471755">繼續下載這項內容?</translation>
 <translation id="3321367458490630980">已新增感興趣的主題</translation>
@@ -638,7 +637,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{<ph name="TAB_COUNT_ONE" /> 個分頁}other{<ph name="TAB_COUNT_MANY" /> 個分頁、<ph name="TAB_COUNT_INCOGNITO" /> 個無痕分頁}}</translation>
 <translation id="4549903594034243526">chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">已透過 USB 傳輸線連線</translation>
-<translation id="4557685098773234337">如要更快速地前往這個網頁,請將網頁新增至主畫面</translation>
 <translation id="4558311620361989323">網頁快速鍵</translation>
 <translation id="4561730552726921821">註冊成功</translation>
 <translation id="4561979708150884304">沒有網路連線</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zu.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zu.xtb
index d96d7e04..bdec8e0 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zu.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zu.xtb
@@ -437,7 +437,6 @@
 <translation id="3284510035090979597">Usizo Olusebenzayo</translation>
 <translation id="3285080554353377245">Amavidiyo wendlela yokusebenzisa i-Chrome</translation>
 <translation id="3288003805934695103">Ilayisha kabusha ikhasi</translation>
-<translation id="3290991969712132877">Ukuze ufike lapha ngokushesha, engeza leli khasi Kusikrini sakho sasekhaya kusuka kwinkinobho yezinketho Zokuningi</translation>
 <translation id="3297344142967351106">Umsizi wezwi</translation>
 <translation id="3303414029551471755">Qhubeka ngokulanda okuqukethwe?</translation>
 <translation id="3321367458490630980">Intshisekelo ingeziwe</translation>
@@ -639,7 +638,6 @@
 <translation id="4547551584605870320">{TAB_COUNT,plural, =1{ithebhu <ph name="TAB_COUNT_ONE" />}one{amathebhu <ph name="TAB_COUNT_MANY" />, i-incognito <ph name="TAB_COUNT_INCOGNITO" />}other{amathebhu <ph name="TAB_COUNT_MANY" />, i-incognito <ph name="TAB_COUNT_INCOGNITO" />}}</translation>
 <translation id="4549903594034243526">i-chrome_emotion_gif_<ph name="CURRENT_TIMESTAMP_MS" /></translation>
 <translation id="4554077758708533499">Ixhunywe ngekhebula le-USB</translation>
-<translation id="4557685098773234337">Ukuze ufike lapha ngokushesha, engeza leli khasi Kusikrini sakho sasekhaya</translation>
 <translation id="4558311620361989323">Izinqamuleli zekhasi lewebhu</translation>
 <translation id="4561730552726921821">Ukubhalisa kuphumelele</translation>
 <translation id="4561979708150884304">Alukho uxhumano</translation>
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonController.java
index 13631ed..c078e9f 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonController.java
@@ -41,11 +41,6 @@
  */
 public class VoiceToolbarButtonController
         implements ButtonDataProvider, ConfigurationChangedObserver {
-    /**
-     * Default minimum width to show the voice search button.
-     */
-    public static final int DEFAULT_MIN_WIDTH_DP = 360;
-
     private static final String IPH_PROMO_PARAM = "generic_message";
 
     private final Supplier<Tab> mActiveTabSupplier;
@@ -60,7 +55,6 @@
     private final ButtonDataImpl mButtonData;
     private final ObserverList<ButtonDataObserver> mObservers = new ObserverList<>();
 
-    private Integer mMinimumWidthDp;
     private int mScreenWidthDp;
 
     /**
@@ -188,10 +182,7 @@
         }
 
         IPHCommandBuilder iphCommandBuilder = null;
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR)
-                && ChromeFeatureList.isEnabled(ChromeFeatureList.TOOLBAR_MIC_IPH_ANDROID)) {
-            iphCommandBuilder = createVoiceButtonIPHCommandBuilder(tab);
-        } else if (AdaptiveToolbarFeatures.isCustomizationEnabled()) {
+        if (AdaptiveToolbarFeatures.isCustomizationEnabled()) {
             iphCommandBuilder = createCustomizationIPHCommandBuilder(tab);
         } else {
             // No IPH features enabled.
@@ -202,18 +193,12 @@
     }
 
     private boolean shouldShowVoiceButton(Tab tab) {
-        if (!isToolbarMicEnabled() || tab == null || tab.isIncognito()
-                || !mVoiceSearchDelegate.isVoiceSearchEnabled()) {
+        if (tab == null || tab.isIncognito() || !mVoiceSearchDelegate.isVoiceSearchEnabled()) {
             return false;
         }
 
-        if (mMinimumWidthDp == null) {
-            mMinimumWidthDp = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
-                    ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR, "minimum_width_dp",
-                    DEFAULT_MIN_WIDTH_DP);
-        }
-
-        boolean isDeviceWideEnough = mScreenWidthDp >= mMinimumWidthDp;
+        boolean isDeviceWideEnough =
+                mScreenWidthDp >= AdaptiveToolbarFeatures.getDeviceMinimumWidthForShowingButton();
         if (!isDeviceWideEnough) return false;
 
         return UrlUtilities.isHttpOrHttps(tab.getUrl());
@@ -222,10 +207,7 @@
     /** Returns whether the feature flags allow showing the mic icon in the toolbar. */
     public static boolean isToolbarMicEnabled() {
         if (!FeatureList.isInitialized()) return false;
-        return AdaptiveToolbarFeatures.isSingleVariantModeEnabled()
-                && AdaptiveToolbarFeatures.getSingleVariantMode()
-                        == AdaptiveToolbarButtonVariant.VOICE
-                || AdaptiveToolbarFeatures.isCustomizationEnabled();
+        return AdaptiveToolbarFeatures.isCustomizationEnabled();
     }
 
     private void notifyObservers(boolean hint) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonControllerUnitTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonControllerUnitTest.java
index e0388eb..f86f849 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonControllerUnitTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonControllerUnitTest.java
@@ -39,7 +39,6 @@
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
 import org.chromium.chrome.browser.user_education.IPHCommandBuilder;
 import org.chromium.chrome.test.util.browser.Features;
-import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.feature_engagement.EventConstants;
 import org.chromium.components.feature_engagement.FeatureConstants;
@@ -102,7 +101,7 @@
         MockitoAnnotations.initMocks(this);
         ShadowChromeFeatureList.reset();
 
-        mConfiguration.screenWidthDp = VoiceToolbarButtonController.DEFAULT_MIN_WIDTH_DP;
+        mConfiguration.screenWidthDp = AdaptiveToolbarFeatures.DEFAULT_MIN_WIDTH_DP;
         doReturn(mConfiguration).when(mResources).getConfiguration();
         doReturn(mResources).when(mContext).getResources();
 
@@ -125,33 +124,25 @@
     }
 
     @Test
-    @DisableFeatures({ChromeFeatureList.TOOLBAR_MIC_IPH_ANDROID,
-            ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR,
-            ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2,
-            ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR})
-    @EnableFeatures({ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR})
-    public void
-    onConfigurationChanged_screenWidthChanged() {
+    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
+    public void onConfigurationChanged_screenWidthChanged() {
         assertTrue(mVoiceToolbarButtonController.get(mTab).canShow());
 
         // Screen width shrinks below the threshold (e.g. screen rotated).
-        mConfiguration.screenWidthDp = VoiceToolbarButtonController.DEFAULT_MIN_WIDTH_DP - 1;
+        mConfiguration.screenWidthDp = AdaptiveToolbarFeatures.DEFAULT_MIN_WIDTH_DP - 1;
         mVoiceToolbarButtonController.onConfigurationChanged(mConfiguration);
 
         assertFalse(mVoiceToolbarButtonController.get(mTab).canShow());
 
         // Make sure the opposite works as well.
-        mConfiguration.screenWidthDp = VoiceToolbarButtonController.DEFAULT_MIN_WIDTH_DP;
+        mConfiguration.screenWidthDp = AdaptiveToolbarFeatures.DEFAULT_MIN_WIDTH_DP;
         mVoiceToolbarButtonController.onConfigurationChanged(mConfiguration);
 
         assertTrue(mVoiceToolbarButtonController.get(mTab).canShow());
     }
 
     @Test
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2,
-            ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR,
-            ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR})
-    @EnableFeatures({ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR,
+    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2,
             ChromeFeatureList.TOOLBAR_MIC_IPH_ANDROID})
     public void
     testIPHCommandHelper() {
@@ -170,11 +161,8 @@
     }
 
     @Test
-    @DisableFeatures({ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR,
-            ChromeFeatureList.TOOLBAR_MIC_IPH_ANDROID})
     @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void
-    testIPHEvent() {
+    public void testIPHEvent() {
         doReturn(true).when(mTracker).shouldTriggerHelpUI(
                 FeatureConstants.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_VOICE_SEARCH_FEATURE);
 
@@ -186,26 +174,7 @@
     }
 
     @Test
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    public void isToolbarMicEnabled_adaptiveButtons_nonVoice() {
-        ShadowChromeFeatureList.sParamValues.put("mode", AdaptiveToolbarFeatures.ALWAYS_NEW_TAB);
-        assertFalse(VoiceToolbarButtonController.isToolbarMicEnabled());
-    }
-
-    @Test
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    public void isToolbarMicEnabled_adaptiveButtons_voice() {
-        ShadowChromeFeatureList.sParamValues.put("mode", AdaptiveToolbarFeatures.ALWAYS_VOICE);
-        assertTrue(VoiceToolbarButtonController.isToolbarMicEnabled());
-    }
-
-    @Test
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2,
-            ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR,
-            ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR})
-    @EnableFeatures({ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR})
+    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
     // clang-format off
     public void isToolbarMicEnabled_toolbarMic() {
         // clang-format on
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
index 17a0a0b..a56e341 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
@@ -219,11 +219,7 @@
 
     @Override
     public void onFinishNativeInitialization() {
-        if (AdaptiveToolbarFeatures.isSingleVariantModeEnabled()) {
-            @AdaptiveToolbarButtonVariant
-            int variant = AdaptiveToolbarFeatures.getSingleVariantMode();
-            setSingleProvider(mButtonDataProviderMap.get(variant));
-        } else if (AdaptiveToolbarFeatures.isCustomizationEnabled()) {
+        if (AdaptiveToolbarFeatures.isCustomizationEnabled()) {
             mAdaptiveToolbarStatePredictor.recomputeUiState(uiState -> {
                 setSingleProvider(uiState.canShowUi
                                 ? mButtonDataProviderMap.get(uiState.toolbarButtonState)
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonControllerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonControllerTest.java
index e877e095..be5a843 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonControllerTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonControllerTest.java
@@ -45,7 +45,6 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.toolbar.ButtonData;
 import org.chromium.chrome.browser.toolbar.ButtonData.ButtonSpec;
 import org.chromium.chrome.browser.toolbar.ButtonDataImpl;
 import org.chromium.chrome.browser.toolbar.ButtonDataProvider;
@@ -68,9 +67,7 @@
                 AdaptiveToolbarButtonControllerTest.ShadowChromeFeatureList.class,
                 AdaptiveToolbarButtonControllerTest.ShadowVoiceRecognitionHandler.class})
 @RunWith(BaseRobolectricTestRunner.class)
-@EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR,
-        ChromeFeatureList.VOICE_SEARCH_AUDIO_CAPTURE_POLICY})
-@DisableFeatures(ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2)
+@EnableFeatures(ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2)
 public class AdaptiveToolbarButtonControllerTest {
     // TODO(crbug.com/1199025): Remove this shadow.
     @Implements(ChromeFeatureList.class)
@@ -137,182 +134,6 @@
 
     @Test
     @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testDestroy_alwaysNone() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_NONE);
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.destroy();
-
-        verify(mShareButtonController).destroy();
-        verify(mVoiceToolbarButtonController).destroy();
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testDestroy_alwaysNewTab() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_NEW_TAB);
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-        adaptiveToolbarButtonController.destroy();
-
-        verify(mNewTabButtonController).destroy();
-        verify(mNewTabButtonController).removeObserver(adaptiveToolbarButtonController);
-        verify(mShareButtonController).destroy();
-        verify(mVoiceToolbarButtonController).destroy();
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testDestroy_alwaysShare() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_SHARE);
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-        adaptiveToolbarButtonController.destroy();
-
-        verify(mNewTabButtonController).destroy();
-        verify(mShareButtonController).destroy();
-        verify(mShareButtonController).removeObserver(adaptiveToolbarButtonController);
-        verify(mVoiceToolbarButtonController).destroy();
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testDestroy_alwaysVoice() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_VOICE);
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-        adaptiveToolbarButtonController.destroy();
-
-        verify(mNewTabButtonController).destroy();
-        verify(mShareButtonController).destroy();
-        verify(mVoiceToolbarButtonController).destroy();
-        verify(mVoiceToolbarButtonController).removeObserver(adaptiveToolbarButtonController);
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testGet_alwaysShare() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_SHARE);
-        mButtonData.setButtonSpec(makeButtonSpec(AdaptiveToolbarButtonVariant.SHARE));
-
-        when(mShareButtonController.get(any())).thenReturn(mButtonData);
-
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-        ButtonData buttonData = adaptiveToolbarButtonController.get(mTab);
-        adaptiveToolbarButtonController.destroy();
-
-        Assert.assertEquals(101, buttonData.getButtonSpec().getContentDescriptionResId());
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testGet_alwaysVoice() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_VOICE);
-        mButtonData.setButtonSpec(makeButtonSpec(AdaptiveToolbarButtonVariant.VOICE));
-
-        when(mVoiceToolbarButtonController.get(any())).thenReturn(mButtonData);
-
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-        ButtonData buttonData = adaptiveToolbarButtonController.get(mTab);
-        adaptiveToolbarButtonController.destroy();
-
-        Assert.assertEquals(101, buttonData.getButtonSpec().getContentDescriptionResId());
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testMetrics() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_SHARE);
-        mButtonData.setCanShow(true);
-        mButtonData.setEnabled(true);
-        mButtonData.setButtonSpec(makeButtonSpec(AdaptiveToolbarButtonVariant.SHARE));
-        when(mShareButtonController.get(any())).thenReturn(mButtonData);
-
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-        ButtonData buttonData = adaptiveToolbarButtonController.get(mTab);
-
-        Assert.assertEquals(1,
-                ShadowRecordHistogram.getHistogramValueCountForTesting(
-                        "Android.AdaptiveToolbarButton.SessionVariant",
-                        AdaptiveToolbarButtonVariant.SHARE));
-        Assert.assertEquals(1,
-                ShadowRecordHistogram.getHistogramTotalCountForTesting(
-                        "Android.AdaptiveToolbarButton.SessionVariant"));
-
-        View view = mock(View.class);
-        buttonData.getButtonSpec().getOnClickListener().onClick(view);
-        buttonData.getButtonSpec().getOnClickListener().onClick(view);
-
-        Assert.assertEquals(2,
-                ShadowRecordHistogram.getHistogramValueCountForTesting(
-                        "Android.AdaptiveToolbarButton.Clicked",
-                        AdaptiveToolbarButtonVariant.SHARE));
-        Assert.assertEquals(2,
-                ShadowRecordHistogram.getHistogramTotalCountForTesting(
-                        "Android.AdaptiveToolbarButton.Clicked"));
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testAddObserver_alwaysShare() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_SHARE);
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-        adaptiveToolbarButtonController.destroy();
-
-        verify(mShareButtonController).addObserver(adaptiveToolbarButtonController);
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testAddObserver_alwaysVoice() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_VOICE);
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-        adaptiveToolbarButtonController.destroy();
-
-        verify(mVoiceToolbarButtonController).addObserver(adaptiveToolbarButtonController);
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void testButtonDataChanged() {
-        setModeParam(AdaptiveToolbarFeatures.ALWAYS_VOICE);
-        ButtonDataObserver observer = mock(ButtonDataObserver.class);
-
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-        adaptiveToolbarButtonController.addObserver(observer);
-        adaptiveToolbarButtonController.buttonDataChanged(true);
-        adaptiveToolbarButtonController.destroy();
-
-        verify(observer).buttonDataChanged(true);
-    }
-
-    @Test
-    @SmallTest
     @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
     @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR})
     public void testCustomization_newTab() {
@@ -450,40 +271,6 @@
                 .launchSettingsActivity(activity, AdaptiveToolbarPreferenceFragment.class);
     }
 
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR,
-            ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2,
-            ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR})
-    public void
-    testLegacyVoiceToolbarFeature() {
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-
-        Assert.assertEquals(mVoiceToolbarButtonController,
-                adaptiveToolbarButtonController.getSingleProviderForTesting());
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR,
-            ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2,
-            ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR})
-    public void
-    testLegacyShareToolbarFeature() {
-        AdaptiveToolbarButtonController adaptiveToolbarButtonController = buildController();
-        adaptiveToolbarButtonController.onFinishNativeInitialization();
-
-        Assert.assertEquals(mShareButtonController,
-                adaptiveToolbarButtonController.getSingleProviderForTesting());
-    }
-
-    private static void setModeParam(String modeValue) {
-        ShadowChromeFeatureList.sParamValues.put("mode", modeValue);
-    }
-
     private AdaptiveToolbarButtonController buildController() {
         AdaptiveToolbarButtonController adaptiveToolbarButtonController =
                 new AdaptiveToolbarButtonController(mock(Activity.class),
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
index c06bfdc..71b81617 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
@@ -16,20 +16,8 @@
 
 /**
  * A utility class for handling feature flags used by {@link AdaptiveToolbarButtonController}.
- *
- * <p>TODO(shaktisahu): This class supports both the data collection and the customization
- * experiment. Cleanup once the former is no longer needed.
  */
 public class AdaptiveToolbarFeatures {
-    /** Adaptive toolbar button is always empty. */
-    public static final String ALWAYS_NONE = "always-none";
-    /** Adaptive toolbar button opens a new tab. */
-    public static final String ALWAYS_NEW_TAB = "always-new-tab";
-    /** Adaptive toolbar button shares the current tab. */
-    public static final String ALWAYS_SHARE = "always-share";
-    /** Adaptive toolbar button opens voice search. */
-    public static final String ALWAYS_VOICE = "always-voice";
-
     /** Finch default group for new tab variation. */
     static final String NEW_TAB = "new-tab";
     /** Finch default group for share variation. */
@@ -42,7 +30,6 @@
     private static final String VARIATION_PARAM_DISABLE_UI = "disable_ui";
     private static final String VARIATION_PARAM_IGNORE_SEGMENTATION_RESULTS =
             "ignore_segmentation_results";
-    private static final String VARIATION_PARAM_SINGLE_VARIANT_MODE = "mode";
     private static final String VARIATION_PARAM_SHOW_UI_ONLY_AFTER_READY =
             "show_ui_only_after_ready";
     @VisibleForTesting
@@ -58,6 +45,11 @@
     /** Default value to use in case finch param isn't available for default segment. */
     private static final String DEFAULT_PARAM_VALUE_DEFAULT_SEGMENT = NEW_TAB;
 
+    /**
+     * Default minimum width to show the optional button.
+     */
+    public static final int DEFAULT_MIN_WIDTH_DP = 360;
+
     @AdaptiveToolbarButtonVariant
     private static Integer sButtonVariant;
 
@@ -106,21 +98,6 @@
     }
 
     /**
-     * Returns whether the adaptive toolbar is enabled in single variant mode. Returns true also to
-     * provide legacy support for feature flags {@code ShareButtonInTopToolbar} and {@code
-     * VoiceButtonInTopToolbar}.
-     *
-     * <p>Must be called with the {@link FeatureList} initialized.
-     */
-    public static boolean isSingleVariantModeEnabled() {
-        if (isCustomizationEnabled()) return false;
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR)) {
-            return true;
-        }
-        return isLegacyShareButtonEnabled() || isLegacyVoiceButtonEnabled();
-    }
-
-    /**
      * Returns whether the adaptive toolbar is enabled with segmentation and customization.
      *
      * <p>Must be called with the {@link FeatureList} initialized.
@@ -152,57 +129,11 @@
     }
 
     /**
-     * When the adaptive toolbar is configured in a single button variant mode, returns the {@link
-     * AdaptiveToolbarButtonVariant} being used.
-     *
-     * <p>This methods avoids parsing param strings more than once. Tests need to call {@link
-     * #clearParsedParamsForTesting()} to clear the cached values.
-     *
-     * <p>Must be called with the {@link FeatureList} initialized.
-     *
-     * <p>TODO(shaktisahu): Have a similar method for segmentation.
-     */
-    @AdaptiveToolbarButtonVariant
-    public static int getSingleVariantMode() {
-        assert isSingleVariantModeEnabled();
-        if (sButtonVariant != null) return sButtonVariant;
-        if (isLegacyShareButtonEnabled()) {
-            sButtonVariant = AdaptiveToolbarButtonVariant.SHARE;
-        } else if (isLegacyVoiceButtonEnabled()) {
-            sButtonVariant = AdaptiveToolbarButtonVariant.VOICE;
-        }
-        if (sButtonVariant != null) return sButtonVariant;
-
-        String mode = ChromeFeatureList.getFieldTrialParamByFeature(
-                ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR,
-                VARIATION_PARAM_SINGLE_VARIANT_MODE);
-        switch (mode) {
-            case ALWAYS_NONE:
-                sButtonVariant = AdaptiveToolbarButtonVariant.NONE;
-                break;
-            case ALWAYS_NEW_TAB:
-                sButtonVariant = AdaptiveToolbarButtonVariant.NEW_TAB;
-                break;
-            case ALWAYS_SHARE:
-                sButtonVariant = AdaptiveToolbarButtonVariant.SHARE;
-                break;
-            case ALWAYS_VOICE:
-                sButtonVariant = AdaptiveToolbarButtonVariant.VOICE;
-                break;
-            default:
-                sButtonVariant = AdaptiveToolbarButtonVariant.UNKNOWN;
-                break;
-        }
-        return sButtonVariant;
-    }
-
-    /**
      * Returns the default variant to be shown in segmentation experiment when the backend results
      * are unavailable or not configured.
      */
     @AdaptiveToolbarButtonVariant
     static int getSegmentationDefault() {
-        assert !isSingleVariantModeEnabled();
         assert isCustomizationEnabled();
         if (sButtonVariant != null) return sButtonVariant;
         String defaultSegment = getDefaultSegment();
@@ -266,7 +197,7 @@
 
         return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
                 ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2,
-                VARIATION_PARAM_SHOW_UI_ONLY_AFTER_READY, false);
+                VARIATION_PARAM_SHOW_UI_ONLY_AFTER_READY, true);
     }
 
     @VisibleForTesting
@@ -298,33 +229,12 @@
         sShowUiOnlyAfterReadyForTesting = null;
     }
 
-    /**
-     * Returns whether the adaptive toolbar is providing legacy support for the feature flag {@code
-     * VoiceButtonInTopToolbar}.
-     *
-     * <p>Must be called with the {@link FeatureList} initialized.
-     */
-    private static boolean isLegacyShareButtonEnabled() {
-        if (isCustomizationEnabled()) return false;
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR)) {
-            return false;
-        }
-        return ChromeFeatureList.isEnabled(ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR);
-    }
-
-    /**
-     * Returns whether the adaptive toolbar is providing legacy support for the feature flag {@code
-     * ShareButtonInTopToolbar}.
-     *
-     * <p>Must be called with the {@link FeatureList} initialized.
-     */
-    private static boolean isLegacyVoiceButtonEnabled() {
-        if (isCustomizationEnabled()) return false;
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR)) {
-            return false;
-        }
-        return ChromeFeatureList.isEnabled(ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR);
-    }
-
     private AdaptiveToolbarFeatures() {}
+
+    /** @return The minimum device width below which the toolbar button isn't shown. */
+    public static int getDeviceMinimumWidthForShowingButton() {
+        return ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
+                ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2,
+                "minimum_width_dp", DEFAULT_MIN_WIDTH_DP);
+    }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
index 206eeb9..e1733f4 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
@@ -31,6 +31,7 @@
     private static final String ADAPTIVE_TOOLBAR_SEGMENTATION_KEY = "adaptive_toolbar";
 
     private static Pair<Boolean, Integer> sSegmentationResultsForTesting;
+    private static Integer sToolbarStateForTesting;
 
     @Nullable
     private final AndroidPermissionDelegate mAndroidPermissionDelegate;
@@ -87,14 +88,16 @@
      * @param callback The callback containing the result.
      */
     public void recomputeUiState(Callback<UiState> callback) {
+        if (sToolbarStateForTesting != null) {
+            UiState uiState = new UiState(isValidSegment(sToolbarStateForTesting),
+                    sToolbarStateForTesting, sToolbarStateForTesting, sToolbarStateForTesting);
+            callback.onResult(uiState);
+            return;
+        }
+
         // Early return if the feature isn't enabled.
         if (!AdaptiveToolbarFeatures.isCustomizationEnabled()) {
-            boolean canShowUi = AdaptiveToolbarFeatures.isSingleVariantModeEnabled();
-            @AdaptiveToolbarButtonVariant
-            int toolbarButtonState = AdaptiveToolbarFeatures.isSingleVariantModeEnabled()
-                    ? AdaptiveToolbarFeatures.getSingleVariantMode()
-                    : AdaptiveToolbarButtonVariant.UNKNOWN;
-            callback.onResult(new UiState(canShowUi, toolbarButtonState,
+            callback.onResult(new UiState(false, AdaptiveToolbarButtonVariant.UNKNOWN,
                     AdaptiveToolbarButtonVariant.UNKNOWN, AdaptiveToolbarButtonVariant.UNKNOWN));
             return;
         }
@@ -241,4 +244,10 @@
     public static void setSegmentationResultsForTesting(Pair<Boolean, Integer> results) {
         sSegmentationResultsForTesting = results;
     }
+
+    /** For testing only. */
+    @VisibleForTesting
+    public static void setToolbarStateForTesting(Integer toolbarState) {
+        sToolbarStateForTesting = toolbarState;
+    }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictorTest.java
index 12cc92e..71c286e 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictorTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictorTest.java
@@ -109,21 +109,6 @@
 
     @Test
     @SmallTest
-    @EnableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR,
-            ChromeFeatureList.VOICE_SEARCH_AUDIO_CAPTURE_POLICY})
-    @DisableFeatures({ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2})
-    public void
-    testWorksWithDataCollectionFeatureFlag() {
-        ShadowChromeFeatureList.sParamValues.put("mode", "always-voice");
-        AdaptiveToolbarStatePredictor statePredictor = buildStatePredictor(
-                true, AdaptiveToolbarButtonVariant.VOICE, true, AdaptiveToolbarButtonVariant.SHARE);
-        UiState expected = new UiState(true, AdaptiveToolbarButtonVariant.VOICE,
-                AdaptiveToolbarButtonVariant.UNKNOWN, AdaptiveToolbarButtonVariant.UNKNOWN);
-        statePredictor.recomputeUiState(verifyResultCallback(expected));
-    }
-
-    @Test
-    @SmallTest
     public void testManualOverride() {
         AdaptiveToolbarFeatures.setDefaultSegmentForTesting(AdaptiveToolbarFeatures.SHARE);
         AdaptiveToolbarFeatures.setIgnoreSegmentationResultsForTesting(false);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java
index 5f2d976..78150baf 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonController.java
@@ -77,9 +77,6 @@
         }
     }
 
-    /** Minimum width to show the new tab button. */
-    public static final int MIN_WIDTH_DP = 360;
-
     /** Context used for fetching resources and window size. */
     private final Context mContext;
     private final Delegate mDelegate;
@@ -203,7 +200,7 @@
             return false;
         }
         // The screen is too narrow to fit the icon.
-        if (mScreenWidthDp < MIN_WIDTH_DP) {
+        if (mScreenWidthDp < AdaptiveToolbarFeatures.getDeviceMinimumWidthForShowingButton()) {
             return false;
         }
         // On tablets a new tab button is shown on the tab strip.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerUnitTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerUnitTest.java
index b052a787..3566b2b 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerUnitTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/OptionalNewTabButtonControllerUnitTest.java
@@ -82,7 +82,7 @@
 
         doReturn(mContext).when(mTab).getContext();
 
-        mConfiguration.screenWidthDp = OptionalNewTabButtonController.MIN_WIDTH_DP + WIDTH_DELTA;
+        mConfiguration.screenWidthDp = AdaptiveToolbarFeatures.DEFAULT_MIN_WIDTH_DP + WIDTH_DELTA;
         doReturn(mConfiguration).when(mResources).getConfiguration();
 
         doReturn(mTabCreator).when(mTabCreatorManager).getTabCreator(anyBoolean());
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBottomSheetContent.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBottomSheetContent.java
index 345b4c52..aaa1c1f 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBottomSheetContent.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBottomSheetContent.java
@@ -9,6 +9,7 @@
 
 import androidx.annotation.Nullable;
 
+import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.ItemProperties;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
@@ -22,7 +23,9 @@
 public class AccountSelectionBottomSheetContent implements BottomSheetContent {
     private final View mContentView;
     private final Supplier<Integer> mScrollOffsetSupplier;
-    private @Nullable Supplier<Boolean> mBackPressHandler;
+    private @Nullable Runnable mBackPressHandler;
+    private final ObservableSupplierImpl<Boolean> mBackPressStateChangedSupplier =
+            new ObservableSupplierImpl<>();
 
     /**
      * Constructs the AccountSelection bottom sheet view.
@@ -32,8 +35,15 @@
         mScrollOffsetSupplier = scrollOffsetSupplier;
     }
 
-    public void setBackPressHandler(Supplier<Boolean> backPressHandler) {
+    /**
+     * Updates the sheet content back press handling behavior. This should be invoked during an
+     * event that updates the back press handling behavior of the sheet content.
+     * @param backPressHandler A runnable that will be invoked by the sheet content to handle a back
+     *         press. A null value indicates that back press will not be handled by the content.
+     */
+    public void setCustomBackPressBehavior(@Nullable Runnable backPressHandler) {
         mBackPressHandler = backPressHandler;
+        mBackPressStateChangedSupplier.set(backPressHandler != null);
     }
 
     public void focusForAccessibility(PropertyKey focusItem) {
@@ -112,7 +122,21 @@
 
     @Override
     public boolean handleBackPress() {
-        return mBackPressHandler != null && mBackPressHandler.get();
+        if (mBackPressHandler != null) {
+            mBackPressHandler.run();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public ObservableSupplierImpl<Boolean> getBackPressStateChangedSupplier() {
+        return mBackPressStateChangedSupplier;
+    }
+
+    @Override
+    public void onBackPressed() {
+        handleBackPress();
     }
 
     @Override
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java
index 45a0427e..108db4d 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java
@@ -94,8 +94,6 @@
         mBottomSheetController = bottomSheetController;
         mBottomSheetContent = bottomSheetContent;
 
-        mBottomSheetContent.setBackPressHandler(() -> { return handleBackPress(); });
-
         mBottomSheetObserver = new EmptyBottomSheetObserver() {
             // TODO(majidvp): We should override #onSheetStateChanged() and react to HIDDEN state
             // since closed is a legacy fixture that can get out of sync with the state is some
@@ -115,14 +113,17 @@
         };
     }
 
-    private boolean handleBackPress() {
-        if (!mWasDismissed && mSelectedAccount != null && mAccounts.size() != 1) {
-            mSelectedAccount = null;
-            showAccountsInternal(mRpForDisplay, mIdpForDisplay, mAccounts, mIdpMetadata,
-                    mClientMetadata, /*isAutoSignIn=*/false, /*focusItem=*/ItemProperties.HEADER);
-            return true;
-        }
-        return false;
+    private void updateBackPressBehavior() {
+        mBottomSheetContent.setCustomBackPressBehavior(
+                !mWasDismissed && mSelectedAccount != null && mAccounts.size() != 1
+                        ? this::handleBackPress
+                        : null);
+    }
+
+    private void handleBackPress() {
+        mSelectedAccount = null;
+        showAccountsInternal(mRpForDisplay, mIdpForDisplay, mAccounts, mIdpMetadata,
+                mClientMetadata, /*isAutoSignIn=*/false, /*focusItem=*/ItemProperties.HEADER);
     }
 
     private PropertyModel createHeaderItem(HeaderType headerType, String rpForDisplay,
@@ -211,6 +212,7 @@
 
         mHeaderType = isAutoSignIn ? HeaderType.AUTO_SIGN_IN : HeaderType.SIGN_IN;
         updateSheet(accounts, /*areAccountsClickable=*/mSelectedAccount == null, focusItem);
+        updateBackPressBehavior();
     }
 
     private void updateSheet(
@@ -281,6 +283,7 @@
         KeyboardVisibilityDelegate.getInstance().removeKeyboardVisibilityListener(
                 mKeyboardVisibilityListener);
         mBottomSheetController.hideContent(mBottomSheetContent, true);
+        updateBackPressBehavior();
     }
 
     private void requestAvatarImage(PropertyModel accountModel) {
@@ -321,6 +324,7 @@
 
         mDelegate.onAccountSelected(selectedAccount);
         showVerifySheet(selectedAccount);
+        updateBackPressBehavior();
     }
 
     void onDismissed(boolean shouldEmbargo) {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index 572eec6..9679eda 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -86,6 +86,14 @@
 constexpr char kVPNProvider[] = "vpnprovider";
 constexpr char kPermissionStateGranted[] = "granted";
 constexpr char kPermissionStateManaged[] = "managed";
+constexpr char kWebAppInfo[] = "web_app_info";
+constexpr char kTitle[] = "title";
+constexpr char kStartUrl[] = "start_url";
+constexpr char kScopeUrl[] = "scope_url";
+constexpr char kThemeColor[] = "theme_color";
+constexpr char kIsWebOnlyTwa[] = "is_web_only_twa";
+constexpr char kCertificateSha256Fingerprint[] =
+    "certificate_sha256_fingerprint";
 constexpr char kWindowLayout[] = "window_layout";
 constexpr char kWindowSizeType[] = "window_layout_type";
 constexpr char kWindowResizability[] = "window_resizability";
@@ -776,12 +784,30 @@
     }
   }
 
+  arc::mojom::WebAppInfoPtr web_app_info;
+  if (const base::Value* web_app_info_value = package->Find(kWebAppInfo)) {
+    const base::Value::Dict& web_app_info_dict = web_app_info_value->GetDict();
+    web_app_info = arc::mojom::WebAppInfo::New();
+    web_app_info->title = *web_app_info_dict.FindString(kTitle);
+    web_app_info->start_url = *web_app_info_dict.FindString(kStartUrl);
+    web_app_info->scope_url = *web_app_info_dict.FindString(kScopeUrl);
+    bool must_convert_to_int = base::StringToInt64(
+        *web_app_info_dict.FindString(kThemeColor), &web_app_info->theme_color);
+    DCHECK(must_convert_to_int);
+    web_app_info->is_web_only_twa = *web_app_info_dict.FindBool(kIsWebOnlyTwa);
+    if (const std::string* fingerprint =
+            web_app_info_dict.FindString(kCertificateSha256Fingerprint)) {
+      web_app_info->certificate_sha256_fingerprint = *fingerprint;
+    }
+  }
+
   return std::make_unique<PackageInfo>(
       package_name, package->FindInt(kPackageVersion).value_or(0),
       last_backup_android_id, last_backup_time,
       package->FindBool(kShouldSync).value_or(false),
       package->FindBool(kSystem).value_or(false),
-      package->FindBool(kVPNProvider).value_or(false), std::move(permissions));
+      package->FindBool(kVPNProvider).value_or(false), std::move(permissions),
+      std::move(web_app_info));
 }
 
 bool ArcAppListPrefs::IsPackageInstalled(
@@ -1650,6 +1676,21 @@
     package_dict.Remove(kPermissionStates);
   }
 
+  if (package.web_app_info) {
+    const arc::mojom::WebAppInfo& web_app_info = *package.web_app_info;
+    base::Value::Dict web_app_info_dict;
+    web_app_info_dict.Set(kTitle, web_app_info.title);
+    web_app_info_dict.Set(kStartUrl, web_app_info.start_url);
+    web_app_info_dict.Set(kScopeUrl, web_app_info.scope_url);
+    web_app_info_dict.Set(kThemeColor,
+                          base::NumberToString(web_app_info.theme_color));
+    web_app_info_dict.Set(kIsWebOnlyTwa, web_app_info.is_web_only_twa);
+    if (const auto& fingerprint = web_app_info.certificate_sha256_fingerprint) {
+      web_app_info_dict.Set(kCertificateSha256Fingerprint, *fingerprint);
+    }
+    package_dict.Set(kWebAppInfo, std::move(web_app_info_dict));
+  }
+
   if (old_package_version == -1 ||
       old_package_version == package.package_version) {
     return;
@@ -2363,7 +2404,8 @@
     bool system,
     bool vpn_provider,
     base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr>
-        permissions)
+        permissions,
+    arc::mojom::WebAppInfoPtr web_app_info)
     : package_name(package_name),
       package_version(package_version),
       last_backup_android_id(last_backup_android_id),
@@ -2371,7 +2413,8 @@
       should_sync(should_sync),
       system(system),
       vpn_provider(vpn_provider),
-      permissions(std::move(permissions)) {}
+      permissions(std::move(permissions)),
+      web_app_info(std::move(web_app_info)) {}
 
 // Need to add explicit destructor for chromium style checker error:
 // Complex class/struct needs an explicit out-of-line destructor
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
index f628b95..58b3320 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -161,7 +161,8 @@
                 bool system,
                 bool vpn_provider,
                 base::flat_map<arc::mojom::AppPermission,
-                               arc::mojom::PermissionStatePtr> permissions);
+                               arc::mojom::PermissionStatePtr> permissions,
+                arc::mojom::WebAppInfoPtr web_app_info);
     ~PackageInfo();
 
     std::string package_name;
@@ -174,6 +175,7 @@
     // Maps app permission to permission states
     base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr>
         permissions;
+    arc::mojom::WebAppInfoPtr web_app_info;
   };
 
   class Observer : public base::CheckedObserver {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_test.cc b/chrome/browser/ui/app_list/arc/arc_app_test.cc
index f7076705..9cfdffbf 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_test.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_test.cc
@@ -40,7 +40,14 @@
 constexpr char kPackageName1[] = "fake.package.name1";
 constexpr char kPackageName2[] = "fake.package.name2";
 constexpr char kPackageName3[] = "fake.package.name3";
-}
+constexpr char kPackageName4[] = "fake.package.name4";
+
+constexpr char kWebAppInfoTitle4[] = "package4";
+constexpr char kWebAppInfoStartURL4[] = "https://example.com/app?start";
+constexpr char kWebAppInfoScope4[] = "https://example.com/app";
+constexpr char kWebAppInfoCertificateFingerprint4[] = "abc";
+
+}  // namespace
 
 // static
 std::string ArcAppTest::GetAppId(const arc::mojom::AppInfo& app_info) {
@@ -230,6 +237,25 @@
       nullptr /* web_app_info */, absl::nullopt, std::move(permissions3),
       absl::nullopt /* version_name */));
 
+  base::flat_map<arc::mojom::AppPermission, arc::mojom::PermissionStatePtr>
+      permissions4;
+  fake_packages_.emplace_back(arc::mojom::ArcPackageInfo::New(
+      kPackageName4,
+      /*package_version=*/4,
+      /*last_backup_android_id=*/4,
+      /*last_backup_time=*/4,
+      /*sync=*/false,
+      /*system=*/false,
+      /*vpn_provider=*/false,
+      /*web_app_info=*/
+      arc::mojom::WebAppInfo::New(kWebAppInfoTitle4, kWebAppInfoStartURL4,
+                                  kWebAppInfoScope4,
+                                  /*theme_color=*/0, /*is_web_only_twa=*/true,
+                                  kWebAppInfoCertificateFingerprint4),
+      /*deprecated_permissions=*/absl::nullopt,
+      /*permission_states=*/std::move(permissions4),
+      /*version_name=*/absl::nullopt));
+
   for (int i = 0; i < 3; ++i) {
     arc::mojom::ShortcutInfo shortcut_info;
     shortcut_info.name = base::StringPrintf("Fake Shortcut %d", i);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
index 71856ea..1ac4726e 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -651,6 +651,23 @@
       EXPECT_EQ(package->last_backup_time, package_info->last_backup_time);
       EXPECT_EQ(package->sync, package_info->should_sync);
       EXPECT_EQ(package->permission_states, package_info->permissions);
+      EXPECT_EQ(package->web_app_info.is_null(),
+                package_info->web_app_info.is_null());
+      if (!package->web_app_info.is_null() &&
+          !package_info->web_app_info.is_null()) {
+        EXPECT_EQ(package->web_app_info->title,
+                  package_info->web_app_info->title);
+        EXPECT_EQ(package->web_app_info->start_url,
+                  package_info->web_app_info->start_url);
+        EXPECT_EQ(package->web_app_info->scope_url,
+                  package_info->web_app_info->scope_url);
+        EXPECT_EQ(package->web_app_info->theme_color,
+                  package_info->web_app_info->theme_color);
+        EXPECT_EQ(package->web_app_info->is_web_only_twa,
+                  package_info->web_app_info->is_web_only_twa);
+        EXPECT_EQ(package->web_app_info->certificate_sha256_fingerprint,
+                  package_info->web_app_info->certificate_sha256_fingerprint);
+      }
     }
   }
 
@@ -2145,6 +2162,10 @@
                             &arc::mojom::ArcPackageInfo::package_name,
                             fake_packages()[2]->package_name)))
       .Times(1);
+  EXPECT_CALL(observer, OnPackageInstalled(testing::Field(
+                            &arc::mojom::ArcPackageInfo::package_name,
+                            fake_packages()[3]->package_name)))
+      .Times(1);
   app_instance()->SendRefreshPackageList(
       ArcAppTest::ClonePackages(fake_packages()));
 
@@ -2159,6 +2180,9 @@
   EXPECT_CALL(observer,
               OnPackageRemoved(fake_packages()[2]->package_name, false))
       .Times(1);
+  EXPECT_CALL(observer,
+              OnPackageRemoved(fake_packages()[3]->package_name, false))
+      .Times(1);
 
   std::vector<arc::mojom::ArcPackageInfoPtr> packages;
   packages.push_back(fake_packages()[0].Clone());
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 e7a799f..58e8252 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -63,7 +63,6 @@
 constexpr size_t kMinimumReservedAppsContainerCapacity = 60U;
 
 // Parameters for FuzzyTokenizedStringMatch.
-constexpr bool kUsePrefixOnly = false;
 constexpr bool kUseWeightedRatio = false;
 constexpr bool kUseEditDistance = false;
 constexpr double kRelevanceThreshold = 0.32;
@@ -221,8 +220,8 @@
       FuzzyTokenizedStringMatch match;
       for (auto& curr_text : tokenized_indexed_searchable_text_) {
         if (match.IsRelevant(query, *curr_text, kRelevanceThreshold,
-                             kUsePrefixOnly, kUseWeightedRatio,
-                             kUseEditDistance, kPartialMatchPenaltyRate) &&
+                             kUseWeightedRatio, kUseEditDistance,
+                             kPartialMatchPenaltyRate) &&
             match.relevance() >= relevance_threshold()) {
           return true;
         }
@@ -608,7 +607,7 @@
     } else {
       FuzzyTokenizedStringMatch match;
       if (match.IsRelevant(query_terms, *indexed_name, kRelevanceThreshold,
-                           kUsePrefixOnly, kUseWeightedRatio, kUseEditDistance,
+                           kUseWeightedRatio, kUseEditDistance,
                            kPartialMatchPenaltyRate) ||
           app->MatchSearchableText(query_terms, use_exact_match)) {
         std::unique_ptr<AppResult> result = app->data_source()->CreateResult(
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 787e860..f86116ef 100644
--- a/chrome/browser/ui/app_list/search/games/game_provider.cc
+++ b/chrome/browser/ui/app_list/search/games/game_provider.cc
@@ -33,7 +33,6 @@
 using chromeos::string_matching::TokenizedString;
 
 // Parameters for FuzzyTokenizedStringMatch.
-constexpr bool kUsePrefixOnly = false;
 constexpr bool kUseWeightedRatio = false;
 constexpr bool kUseEditDistance = false;
 constexpr double kRelevanceThreshold = 0.32;
@@ -64,7 +63,7 @@
   // The return parameter is ignored here, but this method also implicitly
   // calculates the match relevance.
   match.IsRelevant(tokenized_query, tokenized_title, kRelevanceThreshold,
-                   kUsePrefixOnly, kUseWeightedRatio, kUseEditDistance,
+                   kUseWeightedRatio, kUseEditDistance,
                    kPartialMatchPenaltyRate);
   return match.relevance();
 }
diff --git a/chrome/browser/ui/ash/clipboard_history_browsertest.cc b/chrome/browser/ui/ash/clipboard_history_browsertest.cc
index 803567d..9e724afc 100644
--- a/chrome/browser/ui/ash/clipboard_history_browsertest.cc
+++ b/chrome/browser/ui/ash/clipboard_history_browsertest.cc
@@ -1497,7 +1497,7 @@
   EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing());
 
   // Lock the screen.
-  chromeos::SessionManagerClient::Get()->RequestLockScreen();
+  ash::SessionManagerClient::Get()->RequestLockScreen();
   ash::SessionStateWaiter(session_manager::SessionState::LOCKED).Wait();
 
   // Verify that the item was not pasted.
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_browsertest_base.cc b/chrome/browser/ui/ash/holding_space/holding_space_browsertest_base.cc
index 9cff470..810528e8 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_browsertest_base.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_browsertest_base.cc
@@ -174,7 +174,7 @@
   if (session_manager::SessionManager::Get()->IsScreenLocked())
     return;
 
-  chromeos::SessionManagerClient::Get()->RequestLockScreen();
+  SessionManagerClient::Get()->RequestLockScreen();
   SessionStateWaiter(session_manager::SessionState::LOCKED).Wait();
 }
 
diff --git a/chrome/browser/ui/ash/network/mobile_data_notifications_unittest.cc b/chrome/browser/ui/ash/network/mobile_data_notifications_unittest.cc
index cff2be94..75e1c42 100644
--- a/chrome/browser/ui/ash/network/mobile_data_notifications_unittest.cc
+++ b/chrome/browser/ui/ash/network/mobile_data_notifications_unittest.cc
@@ -18,10 +18,10 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_connect.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
diff --git a/chrome/browser/ui/ash/network/network_state_notifier_unittest.cc b/chrome/browser/ui/ash/network/network_state_notifier_unittest.cc
index 5c729e9..7a9c239b 100644
--- a/chrome/browser/ui/ash/network/network_state_notifier_unittest.cc
+++ b/chrome/browser/ui/ash/network/network_state_notifier_unittest.cc
@@ -16,14 +16,14 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/ash/components/network/cellular_metrics_logger.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/hermes/hermes_clients.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/platform_test.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/chrome/browser/ui/ash/session_controller_client_impl.cc b/chrome/browser/ui/ash/session_controller_client_impl.cc
index 18a0674..f2f42df 100644
--- a/chrome/browser/ui/ash/session_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/session_controller_client_impl.cc
@@ -280,7 +280,7 @@
   // purely by emitting D-Bus signals, and thus has to be run whenever Ash is
   // started so Ash (DetachableBaseHandler in particular) gets the proper view
   // of the current detachable base state.
-  chromeos::SessionManagerClient::Get()->EmitAshInitialized();
+  ash::SessionManagerClient::Get()->EmitAshInitialized();
 }
 
 PrefService* SessionControllerClientImpl::GetSigninScreenPrefService() {
@@ -411,7 +411,7 @@
     return;
 
   VLOG(1) << "Requesting screen lock from SessionControllerClientImpl";
-  chromeos::SessionManagerClient::Get()->RequestLockScreen();
+  ash::SessionManagerClient::Get()->RequestLockScreen();
 }
 
 // static
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
index 04b7bf6..8d7c0cd3 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
@@ -460,9 +460,14 @@
 
 void AppServiceShelfContextMenu::BuildChromeAppMenu(
     ui::SimpleMenuModel* menu_model) {
-  if (!BrowserShortcutShelfItemController::IsListOfActiveBrowserEmpty(
-          controller()->shelf_model()) ||
-      item().type == ash::TYPE_DIALOG || controller()->IsOpen(item().id)) {
+  // Don't check list of active browsers for lacros app because the list of
+  // browsers only tracks in-process browsers (i.e. instances of ash-chrome).
+  const bool has_active_browsers =
+      item().id.app_id != app_constants::kLacrosAppId &&
+      !BrowserShortcutShelfItemController::IsListOfActiveBrowserEmpty(
+          controller()->shelf_model());
+  if (has_active_browsers || item().type == ash::TYPE_DIALOG ||
+      controller()->IsOpen(item().id)) {
     AddContextMenuOption(menu_model, ash::MENU_CLOSE,
                          IDS_SHELF_CONTEXT_MENU_CLOSE);
   }
diff --git a/chrome/browser/ui/certificate_dialogs.cc b/chrome/browser/ui/certificate_dialogs.cc
index 15cfe72..de86b731a 100644
--- a/chrome/browser/ui/certificate_dialogs.cc
+++ b/chrome/browser/ui/certificate_dialogs.cc
@@ -46,10 +46,9 @@
 };
 
 void WriterCallback(const base::FilePath& path, const std::string& data) {
-  int bytes_written = base::WriteFile(path, data.data(), data.size());
-  if (bytes_written != static_cast<ssize_t>(data.size())) {
-    LOG(ERROR) << "Writing " << path.value() << " (" << data.size()
-               << "B) returned " << bytes_written;
+  if (!base::WriteFile(path, data)) {
+    LOG(ERROR) << "Error writing " << path.value() << " (" << data.size()
+               << "B)";
   }
 }
 
diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc
index 40222c009..462f3d9 100644
--- a/chrome/browser/ui/color/chrome_color_mixer.cc
+++ b/chrome/browser/ui/color/chrome_color_mixer.cc
@@ -291,7 +291,6 @@
   mixer[kColorInfoBarForeground] = {kColorToolbarText};
   mixer[kColorIntentPickerItemBackgroundHovered] = ui::SetAlpha(
       ui::GetColorWithMaxContrast(ui::kColorDialogBackground), 0x0F);  // 6%.
-  // TODO(crbug.com/1330183): Improve selection color.
   mixer[kColorIntentPickerItemBackgroundSelected] = ui::BlendForMinContrast(
       ui::kColorDialogBackground, ui::kColorDialogBackground, ui::kColorAccent,
       1.2);
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index aef444c..8f7bd9b6 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -54,7 +54,6 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/test/base/interactive_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/sessions/core/tab_restore_service.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
@@ -221,7 +220,6 @@
 
       // Launch app in a window.
       app_browser_ = web_app::LaunchWebAppBrowser(profile(), app_id_);
-      ui_test_utils::BrowserActivationWaiter(app_browser_).WaitForActivation();
     }
 
     ASSERT_FALSE(app_id_.empty());
@@ -375,7 +373,13 @@
 }
 
 // Tests that Ctrl + Clicking a link opens a foreground tab.
-IN_PROC_BROWSER_TEST_P(HostedOrWebAppTest, CtrlClickLink) {
+// TODO(crbug.com/1190448): Flaky on Linux.
+#if BUILDFLAG(IS_LINUX)
+#define MAYBE_CtrlClickLink DISABLED_CtrlClickLink
+#else
+#define MAYBE_CtrlClickLink CtrlClickLink
+#endif
+IN_PROC_BROWSER_TEST_P(HostedOrWebAppTest, MAYBE_CtrlClickLink) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   // Set up an app which covers app.com URLs.
diff --git a/chrome/browser/ui/passwords/settings/password_manager_presenter.cc b/chrome/browser/ui/passwords/settings/password_manager_presenter.cc
index 31a1375..4832383 100644
--- a/chrome/browser/ui/passwords/settings/password_manager_presenter.cc
+++ b/chrome/browser/ui/passwords/settings/password_manager_presenter.cc
@@ -44,7 +44,6 @@
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
 #include "components/password_manager/core/browser/ui/password_undo_helper.h"
-#include "components/password_manager/core/browser/ui/plaintext_reason.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/driver/sync_service.h"
@@ -107,20 +106,6 @@
   return result;
 }
 
-#if !BUILDFLAG(IS_ANDROID)
-password_manager::metrics_util::AccessPasswordInSettingsEvent
-ConvertPlaintextReason(password_manager::PlaintextReason reason) {
-  switch (reason) {
-    case password_manager::PlaintextReason::kCopy:
-      return password_manager::metrics_util::ACCESS_PASSWORD_COPIED;
-    case password_manager::PlaintextReason::kView:
-      return password_manager::metrics_util::ACCESS_PASSWORD_VIEWED;
-    case password_manager::PlaintextReason::kEdit:
-      return password_manager::metrics_util::ACCESS_PASSWORD_EDITED;
-  }
-}
-#endif
-
 }  // namespace
 
 PasswordManagerPresenter::PasswordManagerPresenter(
@@ -303,41 +288,6 @@
           kExplicitlyTriggeredInSettings);
 }
 
-#if !BUILDFLAG(IS_ANDROID)  // This is never called on Android.
-void PasswordManagerPresenter::RequestPlaintextPassword(
-    const std::string& sort_key,
-    password_manager::PlaintextReason reason,
-    base::OnceCallback<void(absl::optional<std::u16string>)> callback) const {
-  auto it = password_map_.find(sort_key);
-  if (it == password_map_.end()) {
-    std::move(callback).Run(absl::nullopt);
-    return;
-  }
-
-  DCHECK(!it->second.empty());
-  const auto& form = *it->second[0];
-  syncer::SyncService* sync_service = nullptr;
-  if (SyncServiceFactory::HasSyncService(password_view_->GetProfile())) {
-    sync_service =
-        SyncServiceFactory::GetForProfile(password_view_->GetProfile());
-  }
-  if (password_manager::sync_util::IsSyncAccountCredential(
-          form.url, form.username_value, sync_service,
-          IdentityManagerFactory::GetForProfile(
-              password_view_->GetProfile()))) {
-    base::RecordAction(
-        base::UserMetricsAction("PasswordManager_SyncCredentialShown"));
-  }
-
-  // Call back the front end to reveal the password.
-  std::move(callback).Run(form.password_value);
-  UMA_HISTOGRAM_ENUMERATION(
-      "PasswordManager.AccessPasswordInSettings",
-      ConvertPlaintextReason(reason),
-      password_manager::metrics_util::ACCESS_PASSWORD_COUNT);
-}
-#endif
-
 bool PasswordManagerPresenter::TryRemovePasswordEntries(
     PasswordFormMap* form_map,
     size_t index) {
diff --git a/chrome/browser/ui/passwords/settings/password_manager_presenter.h b/chrome/browser/ui/passwords/settings/password_manager_presenter.h
index 57255ce..1059872 100644
--- a/chrome/browser/ui/passwords/settings/password_manager_presenter.h
+++ b/chrome/browser/ui/passwords/settings/password_manager_presenter.h
@@ -20,7 +20,6 @@
 #include "components/password_manager/core/browser/password_store_consumer.h"
 #include "components/password_manager/core/browser/password_store_interface.h"
 #include "components/password_manager/core/browser/ui/credential_provider_interface.h"
-#include "components/password_manager/core/browser/ui/plaintext_reason.h"
 #include "components/prefs/pref_member.h"
 #include "components/undo/undo_manager.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -112,18 +111,6 @@
       const std::vector<std::string>& sort_keys,
       password_manager::PasswordManagerClient* client);
 
-#if !BUILDFLAG(IS_ANDROID)
-  // Requests to reveal the plain text password corresponding to |sort_key|. If
-  // |sort_key| is a valid key into |password_map_|, runs |callback| with the
-  // corresponding value, or nullopt otherwise.
-  // TODO(https://crbug.com/778146): Update this method to take a DisplayEntry
-  // instead.
-  void RequestPlaintextPassword(
-      const std::string& sort_key,
-      password_manager::PlaintextReason reason,
-      base::OnceCallback<void(absl::optional<std::u16string>)> callback) const;
-#endif
-
  private:
   // Convenience typedef for a map containing PasswordForms grouped into
   // equivalence classes. Each equivalence class corresponds to one entry shown
diff --git a/chrome/browser/ui/passwords/settings/password_manager_presenter_unittest.cc b/chrome/browser/ui/passwords/settings/password_manager_presenter_unittest.cc
index 5a96ea6d..e6b2cac4 100644
--- a/chrome/browser/ui/passwords/settings/password_manager_presenter_unittest.cc
+++ b/chrome/browser/ui/passwords/settings/password_manager_presenter_unittest.cc
@@ -33,7 +33,6 @@
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
 #include "components/password_manager/core/browser/test_password_store.h"
-#include "components/password_manager/core/browser/ui/plaintext_reason.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/sync/driver/test_sync_service.h"
@@ -59,10 +58,7 @@
 constexpr char kPassword2[] = "pass2";
 constexpr char kUsername[] = "user";
 constexpr char kUsername2[] = "user2";
-#if !BUILDFLAG(IS_ANDROID)
-constexpr char kHistogramName[] = "PasswordManager.AccessPasswordInSettings";
-constexpr char16_t kPassword16[] = u"pass";
-#endif
+
 MATCHER(IsNotBlocked, "") {
   return !arg->blocked_by_user;
 }
@@ -321,50 +317,6 @@
   EXPECT_EQ(kSameOrigin, passwords_for_export[0]->url);
 }
 
-#if !BUILDFLAG(IS_ANDROID)
-TEST_F(PasswordManagerPresenterTest, TestRequestPlaintextPassword) {
-  base::HistogramTester histogram_tester;
-  password_manager::PasswordForm form =
-      AddPasswordEntry(GURL(kExampleCom), kUsername, kPassword);
-
-  EXPECT_CALL(GetUIController(), SetPasswordList(SizeIs(1)));
-  EXPECT_CALL(GetUIController(), SetPasswordExceptionList(IsEmpty()));
-  UpdatePasswordLists();
-  base::MockOnceCallback<void(absl::optional<std::u16string>)>
-      password_callback;
-  EXPECT_CALL(password_callback, Run(testing::Eq(kPassword16)));
-  std::string sort_key = password_manager::CreateSortKey(form);
-  GetUIController().GetPasswordManagerPresenter()->RequestPlaintextPassword(
-      sort_key, password_manager::PlaintextReason::kView,
-      password_callback.Get());
-
-  histogram_tester.ExpectUniqueSample(
-      kHistogramName, password_manager::metrics_util::ACCESS_PASSWORD_VIEWED,
-      1);
-}
-
-TEST_F(PasswordManagerPresenterTest, TestRequestPlaintextPasswordEdit) {
-  base::HistogramTester histogram_tester;
-  password_manager::PasswordForm form =
-      AddPasswordEntry(GURL(kExampleCom), kUsername, kPassword);
-
-  EXPECT_CALL(GetUIController(), SetPasswordList(SizeIs(1)));
-  EXPECT_CALL(GetUIController(), SetPasswordExceptionList(IsEmpty()));
-  UpdatePasswordLists();
-  base::MockOnceCallback<void(absl::optional<std::u16string>)>
-      password_callback;
-  EXPECT_CALL(password_callback, Run(testing::Eq(kPassword16)));
-  std::string sort_key = password_manager::CreateSortKey(form);
-  GetUIController().GetPasswordManagerPresenter()->RequestPlaintextPassword(
-      sort_key, password_manager::PlaintextReason::kEdit,
-      password_callback.Get());
-
-  histogram_tester.ExpectUniqueSample(
-      kHistogramName, password_manager::metrics_util::ACCESS_PASSWORD_EDITED,
-      1);
-}
-#endif
-
 TEST_F(PasswordManagerPresenterTest, TestPasswordRemovalAndUndo) {
   password_manager::PasswordForm password1 =
       AddPasswordEntry(GURL(kExampleCom), kUsername, kPassword);
diff --git a/chrome/browser/ui/popup_browsertest.cc b/chrome/browser/ui/popup_browsertest.cc
index 6c74ce14..0076eb4 100644
--- a/chrome/browser/ui/popup_browsertest.cc
+++ b/chrome/browser/ui/popup_browsertest.cc
@@ -32,6 +32,12 @@
 #include "ui/display/test/display_manager_test_api.h"  // nogncheck
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+#if BUILDFLAG(IS_MAC)
+#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/display/display_observer.h"
+#include "ui/display/mac/test/virtual_display_mac_util.h"
+#endif  // BUILDFLAG(IS_MAC)
+
 namespace {
 
 // Tests of window placement for popup browser windows. Test fixtures are run
@@ -118,6 +124,31 @@
   base::RunLoop run_loop_;
 };
 
+#if BUILDFLAG(IS_MAC)
+// A helper class to wait for another display added.
+class TestDisplayObserver : public display::DisplayObserver {
+ public:
+  // display::DisplayObserver:
+  MOCK_METHOD2(OnDisplayMetricsChanged,
+               void(const display::Display&, uint32_t));
+  void OnDisplayAdded(const display::Display& new_display) override {
+    run_loop_.Quit();
+  }
+  MOCK_METHOD1(OnDisplayRemoved, void(const display::Display& old_display));
+
+  // Wait for changes to occur, or return immediately if they already have.
+  void Wait() {
+    if (display::Screen::GetScreen()->GetNumDisplays() > 1) {
+      return;
+    }
+    run_loop_.Run();
+  }
+
+ private:
+  base::RunLoop run_loop_;
+};
+#endif  // BUILDFLAG(IS_MAC)
+
 // Ensure popups are opened in the available space of the opener's display.
 // TODO(crbug.com/1211516): Flaky.
 IN_PROC_BROWSER_TEST_P(PopupBrowserTest, DISABLED_OpenClampedToCurrentDisplay) {
@@ -240,9 +271,9 @@
   }
 }
 
-// TODO(crbug.com/1183791): Disabled on non-ChromeOS because of races with
-// SetScreenInstance and observers not being notified.
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
+// TODO(crbug.com/1183791): Disabled everywhere except ChromeOS and Mac because
+// of races with SetScreenInstance and observers not being notified.
+#if !(BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC))
 #define MAYBE_AboutBlankCrossScreenPlacement \
   DISABLED_AboutBlankCrossScreenPlacement
 #else
@@ -253,6 +284,15 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager())
       .UpdateDisplay("100+100-801x802,901+100-802x802");
+#elif BUILDFLAG(IS_MAC)
+  if (display::test::VirtualDisplayMacUtil::ShouldSkip()) {
+    GTEST_SKIP() << "Skipping test for MacOS 10.13 and older.";
+  }
+  TestDisplayObserver display_observer;
+  display::Screen::GetScreen()->AddObserver(&display_observer);
+  display::test::VirtualDisplayMacUtil::AddDisplay(2, {800, 800});
+  display_observer.Wait();
+  display::Screen::GetScreen()->RemoveObserver(&display_observer);
 #else
   display::ScreenBase test_screen;
   test_screen.display_list().AddDisplay({1, gfx::Rect(100, 100, 801, 802)},
@@ -301,8 +341,12 @@
   auto original_popup_display = GetDisplayNearestBrowser(popup);
   EXPECT_EQ(opener_display, original_popup_display);
 
+  const auto second_display = screen->GetAllDisplays()[1];
+  const std::string move_popup_to_the_second_screen_script = base::StringPrintf(
+      "w.moveTo(%d, %d);", second_display.work_area().x() + 100,
+      second_display.work_area().y() + 100);
   // Have the opener try to move the popup to the second screen.
-  content::ExecuteScriptAsync(opener, "w.moveTo(999, 199);");
+  content::ExecuteScriptAsync(opener, move_popup_to_the_second_screen_script);
 
   // Wait for the substantial move, widgets may move during initialization.
   auto* widget = views::Widget::GetWidgetForNativeWindow(
@@ -311,11 +355,16 @@
   auto new_popup_display = GetDisplayNearestBrowser(popup);
   // The popup only moves to the second screen with Window Placement permission.
   EXPECT_EQ(GetParam(), original_popup_display != new_popup_display);
+  EXPECT_EQ(GetParam(), second_display == new_popup_display);
   // The popup is always constrained to the bounds of the target display.
   auto popup_bounds = popup->window()->GetBounds();
   EXPECT_TRUE(new_popup_display.work_area().Contains(popup_bounds))
       << " work_area: " << new_popup_display.work_area().ToString()
       << " popup: " << popup_bounds.ToString();
+
+#if BUILDFLAG(IS_MAC)
+  display::test::VirtualDisplayMacUtil::RemoveDisplay(2);
+#endif  // BUILDFLAG(IS_MAC)
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc b/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc
index 3426320a..8918059 100644
--- a/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc
+++ b/chrome/browser/ui/side_search/side_search_tab_contents_helper.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/side_search/side_search_tab_contents_helper.h"
 
+#include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_initialize.h"
 #include "chrome/browser/profiles/profile.h"
@@ -13,6 +14,8 @@
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
 #include "chrome/browser/ui/side_search/side_search_config.h"
 #include "chrome/browser/ui/side_search/side_search_utils.h"
+#include "chrome/browser/ui/side_search/unified_side_search_helper.h"
+#include "chrome/browser/ui/ui_features.h"
 #include "components/sessions/content/session_tab_helper.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_controller.h"
@@ -198,6 +201,9 @@
     : content::WebContentsObserver(web_contents),
       content::WebContentsUserData<SideSearchTabContentsHelper>(*web_contents) {
   config_observation_.Observe(GetConfig());
+  if (base::FeatureList::IsEnabled(features::kUnifiedSidePanel)) {
+    CreateUnifiedSideSearchController(web_contents);
+  }
 }
 
 SideSearchSideContentsHelper*
diff --git a/chrome/browser/ui/side_search/unified_side_search_helper.h b/chrome/browser/ui/side_search/unified_side_search_helper.h
new file mode 100644
index 0000000..6a2ea97
--- /dev/null
+++ b/chrome/browser/ui/side_search/unified_side_search_helper.h
@@ -0,0 +1,14 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_SIDE_SEARCH_UNIFIED_SIDE_SEARCH_HELPER_H_
+#define CHROME_BROWSER_UI_SIDE_SEARCH_UNIFIED_SIDE_SEARCH_HELPER_H_
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+void CreateUnifiedSideSearchController(content::WebContents* web_contents);
+
+#endif  // CHROME_BROWSER_UI_SIDE_SEARCH_UNIFIED_SIDE_SEARCH_HELPER_H_
diff --git a/chrome/browser/ui/startup/lacros_first_run_service.cc b/chrome/browser/ui/startup/lacros_first_run_service.cc
index 4969902..3a7e7499 100644
--- a/chrome/browser/ui/startup/lacros_first_run_service.cc
+++ b/chrome/browser/ui/startup/lacros_first_run_service.cc
@@ -12,7 +12,6 @@
 #include "base/callback_forward.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
-#include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
@@ -37,7 +36,6 @@
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/base/consent_level.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "google_apis/gaia/core_account_id.h"
 
@@ -202,12 +200,6 @@
 bool LacrosFirstRunService::ShouldOpenFirstRun() const {
   DCHECK(IsFirstRunEligibleProfile(profile_));
 
-  if (!base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-    // Sync is already always forced, no point showing the FRE to ask the user
-    // to sync.
-    return false;
-  }
-
   const base::CommandLine* command_line =
       base::CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kNoFirstRun))
diff --git a/chrome/browser/ui/startup/lacros_first_run_service_browsertest.cc b/chrome/browser/ui/startup/lacros_first_run_service_browsertest.cc
index ad3a0ce..7a08d0e 100644
--- a/chrome/browser/ui/startup/lacros_first_run_service_browsertest.cc
+++ b/chrome/browser/ui/startup/lacros_first_run_service_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/feature_list.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/lacros/device_settings_lacros.h"
 #include "chrome/browser/lacros/lacros_prefs.h"
@@ -29,7 +28,6 @@
 #include "components/account_manager_core/chromeos/account_manager.h"
 #include "components/account_manager_core/chromeos/account_manager_facade_factory.h"
 #include "components/prefs/pref_service.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
@@ -74,9 +72,6 @@
   }
 
  private:
-  base::test::ScopedFeatureList feature_list_{
-      switches::kLacrosNonSyncingProfiles};
-
   std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
       identity_test_env_adaptor_;
   base::CallbackListSubscription create_services_subscription_;
diff --git a/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.cc b/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.cc
index fe28fa6..8974bf9 100644
--- a/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.cc
+++ b/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.cc
@@ -200,6 +200,9 @@
   got_frame_callback_.Run(cropped_frame, frame_id);
 }
 
+void BackgroundThumbnailVideoCapturer::OnNewCropVersion(uint32_t crop_version) {
+}
+
 void BackgroundThumbnailVideoCapturer::OnFrameWithEmptyRegionCapture() {}
 
 void BackgroundThumbnailVideoCapturer::OnStopped() {}
diff --git a/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.h b/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.h
index 58ba923..eecc9c9 100644
--- a/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.h
+++ b/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.h
@@ -46,6 +46,7 @@
       const gfx::Rect& content_rect,
       mojo::PendingRemote<::viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
           callbacks) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnStopped() override;
   void OnLog(const std::string& /*message*/) override;
diff --git a/chrome/browser/ui/views/certificate_selector.cc b/chrome/browser/ui/views/certificate_selector.cc
index 4ea63ad..dd21c607 100644
--- a/chrome/browser/ui/views/certificate_selector.cc
+++ b/chrome/browser/ui/views/certificate_selector.cc
@@ -278,8 +278,9 @@
   net::ClientCertIdentity* const cert = GetSelectedCert();
   if (!cert)
     return;
-  ShowCertificateViewer(web_contents_, web_contents_->GetTopLevelNativeWindow(),
-                        cert->certificate());
+  ShowCertificateViewerForClientAuth(web_contents_,
+                                     web_contents_->GetTopLevelNativeWindow(),
+                                     cert->certificate());
 }
 
 void CertificateSelector::OnSelectionChanged() {
diff --git a/chrome/browser/ui/views/certificate_viewer_fuchsia.cc b/chrome/browser/ui/views/certificate_viewer_fuchsia.cc
deleted file mode 100644
index c0f1065..0000000
--- a/chrome/browser/ui/views/certificate_viewer_fuchsia.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/certificate_viewer.h"
-
-#include "base/notreached.h"
-
-void ShowCertificateViewer(content::WebContents* web_contents,
-                           gfx::NativeWindow parent,
-                           net::X509Certificate* cert) {
-  // TODO(crbug.com/1234748)
-  NOTIMPLEMENTED_LOG_ONCE();
-}
diff --git a/chrome/browser/ui/views/certificate_viewer_mac_views.mm b/chrome/browser/ui/views/certificate_viewer_mac_views.mm
index 0284395..d0bfb2a 100644
--- a/chrome/browser/ui/views/certificate_viewer_mac_views.mm
+++ b/chrome/browser/ui/views/certificate_viewer_mac_views.mm
@@ -8,9 +8,9 @@
 #include "components/remote_cocoa/browser/window.h"
 #include "components/remote_cocoa/common/native_widget_ns_window.mojom.h"
 
-void ShowCertificateViewer(content::WebContents* web_contents,
-                           gfx::NativeWindow parent,
-                           net::X509Certificate* cert) {
+void ShowCertificateViewerForClientAuth(content::WebContents* web_contents,
+                                        gfx::NativeWindow parent,
+                                        net::X509Certificate* cert) {
   // The certificate viewer on macOS uses the OS viewer rather than the Views
   // implementation (see https://crbug.com/953425), so go through a Mojo
   // interface. This calls the platform APIs from the right process in PWAs.
diff --git a/chrome/browser/ui/views/certificate_viewer_win.cc b/chrome/browser/ui/views/certificate_viewer_win.cc
index e7d9e19..da41c8d 100644
--- a/chrome/browser/ui/views/certificate_viewer_win.cc
+++ b/chrome/browser/ui/views/certificate_viewer_win.cc
@@ -25,15 +25,16 @@
 
 // Shows a Windows certificate viewer dialog on a background thread to avoid
 // nested run loops.
-class CertificateViewerDialog : public ui::BaseShellDialogImpl {
+class CertificateViewerDialogWin : public ui::BaseShellDialogImpl {
  public:
-  CertificateViewerDialog() {}
+  CertificateViewerDialogWin() {}
 
-  CertificateViewerDialog(const CertificateViewerDialog&) = delete;
-  CertificateViewerDialog& operator=(const CertificateViewerDialog&) = delete;
+  CertificateViewerDialogWin(const CertificateViewerDialogWin&) = delete;
+  CertificateViewerDialogWin& operator=(const CertificateViewerDialogWin&) =
+      delete;
 
   // Shows the dialog and calls |callback| when the dialog closes. The caller
-  // must ensure the CertificateViewerDialog remains valid until then.
+  // must ensure the CertificateViewerDialogWin remains valid until then.
   void Show(HWND parent,
             net::X509Certificate* cert,
             base::RepeatingClosure callback) {
@@ -48,10 +49,10 @@
         run_state->dialog_task_runner;
     task_runner->PostTaskAndReply(
         FROM_HERE,
-        base::BindOnce(&CertificateViewerDialog::ShowOnDialogThread,
+        base::BindOnce(&CertificateViewerDialogWin::ShowOnDialogThread,
                        base::Unretained(this), parent,
                        base::WrapRefCounted(cert)),
-        base::BindOnce(&CertificateViewerDialog::OnDialogClosed,
+        base::BindOnce(&CertificateViewerDialogWin::OnDialogClosed,
                        base::Unretained(this), std::move(run_state), callback));
   }
 
@@ -96,19 +97,19 @@
 };
 
 // static
-bool CertificateViewerDialog::mock_certificate_viewer_for_testing = false;
+bool CertificateViewerDialogWin::mock_certificate_viewer_for_testing = false;
 
 }  // namespace
 
-void ShowCertificateViewer(content::WebContents* web_contents,
-                           gfx::NativeWindow parent,
-                           net::X509Certificate* cert) {
-  CertificateViewerDialog* dialog = new CertificateViewerDialog;
+void ShowCertificateViewerForClientAuth(content::WebContents* web_contents,
+                                        gfx::NativeWindow parent,
+                                        net::X509Certificate* cert) {
+  CertificateViewerDialogWin* dialog = new CertificateViewerDialogWin;
   dialog->Show(parent->GetHost()->GetAcceleratedWidget(), cert,
                base::BindRepeating(
-                   &base::DeletePointer<CertificateViewerDialog>, dialog));
+                   &base::DeletePointer<CertificateViewerDialogWin>, dialog));
 }
 
 void MockCertificateViewerForTesting() {
-  CertificateViewerDialog::mock_certificate_viewer_for_testing = true;
+  CertificateViewerDialogWin::mock_certificate_viewer_for_testing = true;
 }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
index e1ee11b..bbb2e07 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -257,15 +257,18 @@
 DesktopMediaPickerDialogView::DisplaySurfaceCategory::DisplaySurfaceCategory(
     DesktopMediaList::Type type,
     std::unique_ptr<DesktopMediaListController> controller,
+    bool audio_offered,
     bool audio_checked)
     : type(type),
       controller(std::move(controller)),
+      audio_offered(audio_offered),
       audio_checked(audio_checked) {}
 
 DesktopMediaPickerDialogView::DisplaySurfaceCategory::DisplaySurfaceCategory(
     DesktopMediaPickerDialogView::DisplaySurfaceCategory&& other)
     : type(other.type),
       controller(std::move(other.controller)),
+      audio_offered(other.audio_offered),
       audio_checked(other.audio_checked) {}
 
 DesktopMediaPickerDialogView::DisplaySurfaceCategory::
@@ -278,6 +281,9 @@
     : web_contents_(params.web_contents),
       audio_requested_(params.request_audio),
       parent_(parent) {
+  DCHECK(!params.force_audio_checkboxes_to_default_checked ||
+         !params.exclude_system_audio);
+
   SetModalType(params.modality);
   SetButtonLabel(ui::DIALOG_BUTTON_OK,
                  l10n_util::GetStringUTF16(IDS_DESKTOP_MEDIA_PICKER_SHARE));
@@ -345,8 +351,12 @@
             this, std::move(source_list));
         screen_scroll_view->SetContents(list_controller->CreateView(
             kGenericScreenStyle, kSingleScreenStyle, screen_title_text));
+        const bool audio_offered =
+            !params.exclude_system_audio &&
+            AudioSupported(DesktopMediaList::Type::kScreen);
         categories_.emplace_back(
             DesktopMediaList::Type::kScreen, std::move(list_controller),
+            audio_offered,
             /*audio_checked=*/params.force_audio_checkboxes_to_default_checked);
 
         screen_scroll_view->ClipHeightTo(
@@ -379,6 +389,7 @@
             kWindowStyle, kWindowStyle, window_title_text));
         categories_.emplace_back(
             DesktopMediaList::Type::kWindow, std::move(list_controller),
+            /*audio_offered=*/AudioSupported(DesktopMediaList::Type::kWindow),
             /*audio_checked=*/params.force_audio_checkboxes_to_default_checked);
 
         window_scroll_view->ClipHeightTo(kWindowStyle.item_size.height(),
@@ -401,9 +412,11 @@
             this, std::move(source_list));
         panes.push_back(
             std::make_pair(title, list_controller->CreateTabListView(title)));
-        categories_.emplace_back(DesktopMediaList::Type::kWebContents,
-                                 std::move(list_controller),
-                                 /*audio_checked=*/true);
+        categories_.emplace_back(
+            DesktopMediaList::Type::kWebContents, std::move(list_controller),
+            /*audio_offered=*/
+            AudioSupported(DesktopMediaList::Type::kWebContents),
+            /*audio_checked=*/true);
         break;
       }
       case DesktopMediaList::Type::kCurrentTab: {
@@ -423,9 +436,11 @@
             this, std::move(source_list));
         window_scroll_view->SetContents(list_controller->CreateView(
             kCurrentTabStyle, kCurrentTabStyle, title));
-        categories_.emplace_back(DesktopMediaList::Type::kCurrentTab,
-                                 std::move(list_controller),
-                                 /*audio_checked=*/true);
+        categories_.emplace_back(
+            DesktopMediaList::Type::kCurrentTab, std::move(list_controller),
+            /*audio_offered=*/
+            AudioSupported(DesktopMediaList::Type::kWebContents),
+            /*audio_checked=*/true);
         window_scroll_view->ClipHeightTo(
             kCurrentTabStyle.item_size.height(),
             kCurrentTabStyle.item_size.height() * 2);
@@ -538,7 +553,7 @@
   }
 
   if (audio_share_checkbox_ &&
-      AudioSupported(categories_[previously_selected_category_].type)) {
+      categories_[previously_selected_category_].audio_offered) {
     // Store pre-change audio checkbox state.
     // Note: Current-tab and and any-tab are both tab-based captures,
     // and therefore share their audio checkbox's state.
@@ -553,11 +568,11 @@
 
   DisplaySurfaceCategory& category = categories_[index];
 
-  if (AudioSupported(categories_[index].type)) {
+  if (category.audio_offered) {
     std::unique_ptr<views::Checkbox> audio_share_checkbox =
         std::make_unique<views::Checkbox>(
             GetLabelForAudioCheckbox(category.type));
-    audio_share_checkbox->SetVisible(AudioSupported(category.type));
+    audio_share_checkbox->SetVisible(true);
     audio_share_checkbox->SetChecked(category.audio_checked);
     audio_share_checkbox_ = SetExtraView(std::move(audio_share_checkbox));
   } else {
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
index 6b22a6a..ec587f41 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
@@ -73,6 +73,7 @@
     DisplaySurfaceCategory(
         DesktopMediaList::Type type,
         std::unique_ptr<DesktopMediaListController> controller,
+        bool audio_offered,
         bool audio_checked);
 
     DisplaySurfaceCategory(DisplaySurfaceCategory&& other);
@@ -81,7 +82,8 @@
 
     DesktopMediaList::Type type;
     std::unique_ptr<DesktopMediaListController> controller;
-    bool audio_checked;
+    bool audio_offered;  // Whether the audio-checkbox should be visible.
+    bool audio_checked;  // Whether the audio-checkbox is checked.
   };
 
   static bool AudioSupported(DesktopMediaList::Type type);
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
index 9d59503..db1db9e 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
@@ -99,7 +99,7 @@
         switches::kDisableModalAnimations);
 #endif
     DesktopMediaPickerManager::Get()->AddObserver(&observer_);
-    CreatePickerViews();
+    CreatePickerViews(/*request_audio=*/true, /*exclude_system_audio=*/false);
   }
 
   void TearDown() override {
@@ -109,7 +109,7 @@
     DesktopMediaPickerManager::Get()->RemoveObserver(&observer_);
   }
 
-  void CreatePickerViews() {
+  void CreatePickerViews(bool request_audio, bool exclude_system_audio) {
     widget_destroyed_waiter_.reset();
     picker_views_.reset();
 
@@ -124,7 +124,8 @@
     picker_params.context = test_helper_.GetContext();
     picker_params.app_name = kAppName;
     picker_params.target_name = kAppName;
-    picker_params.request_audio = true;
+    picker_params.request_audio = request_audio;
+    picker_params.exclude_system_audio = exclude_system_audio;
 
     std::vector<std::unique_ptr<DesktopMediaList>> source_lists;
     for (auto type : source_types_) {
@@ -503,6 +504,65 @@
   EXPECT_EQ(kFakeId, WaitForPickerDone());
 }
 
+class DesktopMediaPickerViewsSystemAudioTest
+    : public DesktopMediaPickerViewsTestBase {
+ public:
+  DesktopMediaPickerViewsSystemAudioTest()
+      : DesktopMediaPickerViewsTestBase(
+            GetSourceTypes(/*should_prefer_current_tab=*/false)) {}
+  ~DesktopMediaPickerViewsSystemAudioTest() override = default;
+
+  void SetUp() override {
+#if BUILDFLAG(IS_MAC)
+    // These tests create actual child Widgets, which normally have a closure
+    // animation on Mac; inhibit it here to avoid the tests flakily hanging.
+    base::CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kDisableModalAnimations);
+#endif
+    DesktopMediaPickerManager::Get()->AddObserver(&observer_);
+    // CreatePickerViews() called  directly from tests.
+  }
+};
+
+TEST_F(DesktopMediaPickerViewsSystemAudioTest,
+       SystemAudioCheckboxVisibleIfExcludeSystemAudioNotSpecified) {
+  CreatePickerViews(/*request_audio=*/true, /*exclude_system_audio=*/false);
+
+  test_api_.SelectTabForSourceType(DesktopMediaList::Type::kScreen);
+
+  // System audio checkbox shown to the user iff the platform supports it.
+  EXPECT_EQ(DesktopMediaPickerViews::kScreenAudioShareSupportedOnPlatform,
+            test_api_.GetAudioShareCheckbox() != nullptr);
+}
+
+TEST_F(DesktopMediaPickerViewsSystemAudioTest,
+       SystemAudioCheckboxInvisibleIfExcludeSystemAudioSpecified) {
+  CreatePickerViews(/*request_audio=*/true, /*exclude_system_audio=*/true);
+
+  test_api_.SelectTabForSourceType(DesktopMediaList::Type::kScreen);
+
+  // Main expectation: System audio checkbox not shown to the user.
+  EXPECT_EQ(test_api_.GetAudioShareCheckbox(), nullptr);
+
+  // Secondary expectation: No effect on the tab-audio checkbox.
+  test_api_.SelectTabForSourceType(DesktopMediaList::Type::kWebContents);
+  EXPECT_NE(test_api_.GetAudioShareCheckbox(), nullptr);
+}
+
+TEST_F(DesktopMediaPickerViewsSystemAudioTest,
+       IfAudioNotRequestedThenExcludeSystemAudioHasNoEffect) {
+  CreatePickerViews(/*request_audio=*/false, /*exclude_system_audio=*/true);
+
+  test_api_.SelectTabForSourceType(DesktopMediaList::Type::kScreen);
+
+  // Main expectation: System audio checkbox not shown to the user.
+  EXPECT_EQ(test_api_.GetAudioShareCheckbox(), nullptr);
+
+  // Secondary expectation: No effect on the tab-audio checkbox.
+  test_api_.SelectTabForSourceType(DesktopMediaList::Type::kWebContents);
+  EXPECT_EQ(test_api_.GetAudioShareCheckbox(), nullptr);  // Not requested.
+}
+
 // Creates a single pane DesktopMediaPickerViews that only has a tab list.
 class DesktopMediaPickerViewsSingleTabPaneTest
     : public DesktopMediaPickerViewsTestBase {
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
index c45ee7ce..8636a31 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
@@ -197,11 +197,7 @@
   }
 }
 
-DownloadBubbleRowView::~DownloadBubbleRowView() {
-  if (model_.get()) {
-    model_->RemoveObserver(this);
-  }
-}
+DownloadBubbleRowView::~DownloadBubbleRowView() = default;
 
 DownloadBubbleRowView::DownloadBubbleRowView(
     DownloadUIModel::DownloadUIModelPtr model,
@@ -215,7 +211,7 @@
       row_list_view_(row_list_view),
       bubble_controller_(bubble_controller),
       navigation_handler_(navigation_handler) {
-  model_->AddObserver(this);
+  model_->SetDelegate(this);
   SetBorder(views::CreateEmptyBorder(kDownloadBubbleRowInsets));
 
   const int icon_label_spacing = ChromeLayoutProvider::Get()->GetDistanceMetric(
@@ -484,7 +480,7 @@
   bubble_controller_->RemoveContentIdFromPartialView(model_->GetContentId());
 }
 
-void DownloadBubbleRowView::OnDownloadDestroyed() {
+void DownloadBubbleRowView::OnDownloadDestroyed(const ContentId& id) {
   // This will return ownership and destroy this object at the end of the
   // method.
   std::unique_ptr<DownloadBubbleRowView> row_view_ptr =
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
index 0a26c62..9825051 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
@@ -31,7 +31,7 @@
 
 class DownloadBubbleRowView : public views::View,
                               public views::ContextMenuController,
-                              public DownloadUIModel::Observer {
+                              public DownloadUIModel::Delegate {
  public:
   METADATA_HEADER(DownloadBubbleRowView);
 
@@ -52,10 +52,10 @@
   bool OnMouseDragged(const ui::MouseEvent& event) override;
   void OnMouseCaptureLost() override;
 
-  // Overrides DownloadUIModel::Observer:
+  // Overrides DownloadUIModel::Delegate:
   void OnDownloadOpened() override;
   void OnDownloadUpdated() override;
-  void OnDownloadDestroyed() override;
+  void OnDownloadDestroyed(const ContentId& id) override;
 
   // Overrides views::ContextMenuController:
   void ShowContextMenuForViewImpl(View* source,
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
index 99477a63..95aefc1 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
@@ -38,6 +38,22 @@
       &DownloadBubbleSecurityView::deep_scan_button_},
      {DownloadCommands::BYPASS_DEEP_SCANNING,
       &DownloadBubbleSecurityView::bypass_deep_scan_button_}});
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class DownloadBubbleSubpageAction {
+  kShown = 0,
+  kShownCheckbox = 1,
+  kShownFirstButton = 2,
+  kShownSecondButton = 3,
+  kPressedBackButton = 4,
+  kClosedSubpage = 5,
+  kClickedCheckbox = 6,
+  kPressedFirstButton = 7,
+  kPressedSecondButton = 8,
+  kMaxValue = kPressedSecondButton
+};
+const char kSubpageActionHistogram[] = "Download.Bubble.SubpageAction";
 }  // namespace
 
 void DownloadBubbleSecurityView::AddHeader() {
@@ -51,9 +67,8 @@
 
   back_button_ =
       header->AddChildView(views::CreateVectorImageButtonWithNativeTheme(
-          base::BindRepeating(
-              &DownloadBubbleNavigationHandler::OpenPrimaryDialog,
-              base::Unretained(navigation_handler_)),
+          base::BindRepeating(&DownloadBubbleSecurityView::BackButtonPressed,
+                              base::Unretained(this)),
           vector_icons::kArrowBackIcon, GetLayoutConstant(DOWNLOAD_ICON_SIZE)));
   views::InstallCircleHighlightPathGenerator(back_button_);
   back_button_->SetTooltipText(l10n_util::GetStringUTF16(IDS_ACCNAME_BACK));
@@ -86,6 +101,12 @@
                             views::LayoutAlignment::kStart);
 }
 
+void DownloadBubbleSecurityView::BackButtonPressed() {
+  navigation_handler_->OpenPrimaryDialog();
+  base::UmaHistogramEnumeration(
+      kSubpageActionHistogram, DownloadBubbleSubpageAction::kPressedBackButton);
+}
+
 void DownloadBubbleSecurityView::UpdateHeader() {
   title_->SetText(download_row_view_->model()
                       ->GetFileNameToReportUser()
@@ -93,12 +114,17 @@
 }
 
 void DownloadBubbleSecurityView::CloseBubble() {
+  // CloseDialog will delete the object. Do not access any members below.
   navigation_handler_->CloseDialog(
       views::Widget::ClosedReason::kCloseButtonClicked);
+  base::UmaHistogramEnumeration(kSubpageActionHistogram,
+                                DownloadBubbleSubpageAction::kClosedSubpage);
 }
 
 void DownloadBubbleSecurityView::OnCheckboxClicked() {
   first_button_->SetEnabled(checkbox_->GetChecked());
+  base::UmaHistogramEnumeration(kSubpageActionHistogram,
+                                DownloadBubbleSubpageAction::kClickedCheckbox);
 }
 
 void DownloadBubbleSecurityView::UpdateIconAndText() {
@@ -126,6 +152,8 @@
 
   checkbox_->SetVisible(ui_info.has_checkbox);
   if (ui_info.has_checkbox) {
+    base::UmaHistogramEnumeration(kSubpageActionHistogram,
+                                  DownloadBubbleSubpageAction::kShownCheckbox);
     checkbox_->SetChecked(false);
     checkbox_->SetText(ui_info.checkbox_label);
   }
@@ -201,6 +229,10 @@
   navigation_handler_->OpenPrimaryDialog();
   bubble_controller_->ProcessDownloadButtonPress(download_row_view_->model(),
                                                  command);
+  base::UmaHistogramEnumeration(
+      kSubpageActionHistogram,
+      is_first_button ? DownloadBubbleSubpageAction::kPressedFirstButton
+                      : DownloadBubbleSubpageAction::kPressedSecondButton);
 }
 
 views::MdTextButton* DownloadBubbleSecurityView::GetButtonForCommand(
@@ -229,6 +261,9 @@
         download_row_view_->ui_info().secondary_color));
     first_button_->SetEnabled(!ui_info.has_checkbox);
     first_button_->SetVisible(true);
+    base::UmaHistogramEnumeration(
+        kSubpageActionHistogram,
+        DownloadBubbleSubpageAction::kShownFirstButton);
   }
   if (ui_info.subpage_buttons.size() > 1) {
     views::MdTextButton* second_button =
@@ -240,6 +275,9 @@
     second_button->SetText(ui_info.subpage_buttons[1].label);
     second_button->SetVisible(true);
     second_button->SetProminent(ui_info.subpage_buttons[1].is_prominent);
+    base::UmaHistogramEnumeration(
+        kSubpageActionHistogram,
+        DownloadBubbleSubpageAction::kShownSecondButton);
   }
 }
 
@@ -297,6 +335,8 @@
   UpdateHeader();
   UpdateIconAndText();
   UpdateButtons();
+  base::UmaHistogramEnumeration(kSubpageActionHistogram,
+                                DownloadBubbleSubpageAction::kShown);
 }
 
 void DownloadBubbleSecurityView::UpdateAccessibilityTextAndFocus() {
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h
index 8e164b6..e381a13d5 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h
@@ -48,6 +48,7 @@
   raw_ptr<views::MdTextButton> deep_scan_button_ = nullptr;
 
  private:
+  void BackButtonPressed();
   void UpdateHeader();
   void AddHeader();
   void CloseBubble();
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 2a9145e..82c84b9 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -300,7 +300,7 @@
                               base::Unretained(this))),
       current_scale_(/*AddedToWidget() set the right DPI*/ 1.0f) {
   views::InstallRectHighlightPathGenerator(this);
-  observation_.Observe(this->model());
+  model_->SetDelegate(this);
 
   // TODO(pkasting): Use bespoke file-scope subclasses for some of these child
   // views to localize functionality and simplify this class.
@@ -540,7 +540,8 @@
   shelf_->AutoClose();
 }
 
-void DownloadItemView::OnDownloadDestroyed() {
+void DownloadItemView::OnDownloadDestroyed(const ContentId& id) {
+  context_menu_.OnDownloadDestroyed();
   shelf_->RemoveDownloadView(this);  // This will delete us!
 }
 
diff --git a/chrome/browser/ui/views/download/download_item_view.h b/chrome/browser/ui/views/download/download_item_view.h
index a9b1250e..2ab47c9 100644
--- a/chrome/browser/ui/views/download/download_item_view.h
+++ b/chrome/browser/ui/views/download/download_item_view.h
@@ -13,7 +13,6 @@
 #include "base/files/file_path.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/scoped_observation.h"
 #include "base/task/cancelable_task_tracker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
@@ -67,7 +66,7 @@
 // DownloadController that receives / writes data which lives in the Renderer.
 class DownloadItemView : public views::View,
                          public views::ContextMenuController,
-                         public DownloadUIModel::Observer,
+                         public DownloadUIModel::Delegate,
                          public views::AnimationDelegateViews {
  public:
   METADATA_HEADER(DownloadItemView);
@@ -92,10 +91,10 @@
                                   const gfx::Point& point,
                                   ui::MenuSourceType source_type) override;
 
-  // DownloadUIModel::Observer:
+  // DownloadUIModel::Delegate:
   void OnDownloadUpdated() override;
   void OnDownloadOpened() override;
-  void OnDownloadDestroyed() override;
+  void OnDownloadDestroyed(const ContentId& id) override;
 
   // views::AnimationDelegateViews:
   void AnimationProgressed(const gfx::Animation* animation) override;
@@ -317,9 +316,6 @@
 
   float current_scale_;
 
-  base::ScopedObservation<DownloadUIModel, DownloadUIModel::Observer>
-      observation_{this};
-
   // Whether or not a histogram has been emitted recording that the dropdown
   // button shown.
   bool dropdown_button_shown_recorded_ = false;
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_layout_linux_native_unittest.cc b/chrome/browser/ui/views/frame/browser_frame_view_layout_linux_native_unittest.cc
index fe67314b..057bc7f 100644
--- a/chrome/browser/ui/views/frame/browser_frame_view_layout_linux_native_unittest.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_view_layout_linux_native_unittest.cc
@@ -55,6 +55,8 @@
   }
   bool ShouldShowCaptionButtons() const override { return true; }
   bool IsRegularOrGuestSession() const override { return true; }
+  bool CanMaximize() const override { return true; }
+  bool CanMinimize() const override { return true; }
   bool IsMaximized() const override { return false; }
   bool IsMinimized() const override { return false; }
   bool IsFullscreen() const override { return false; }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc
index c4c48cf..69275cc 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc
@@ -50,6 +50,7 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/profiles/profile_io_data.h"
@@ -88,7 +89,6 @@
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -164,12 +164,12 @@
     switch (GetThemeChangeTestMode()) {
       case ThemeChangeTestMode::kSWA: {
         system_web_app_installation_ =
-            web_app::TestSystemWebAppInstallation::SetUpAppWithColors(
+            ash::TestSystemWebAppInstallation::SetUpAppWithColors(
                 /*theme_color=*/SK_ColorWHITE,
                 /*dark_mode_theme_color=*/SK_ColorBLACK,
                 /*background_color=*/SK_ColorWHITE,
                 /*dark_mode_background_color=*/SK_ColorBLACK);
-        auto* delegate = static_cast<web_app::UnittestingSystemAppDelegate*>(
+        auto* delegate = static_cast<ash::UnittestingSystemAppDelegate*>(
             system_web_app_installation_->GetDelegate());
         delegate->SetPreferManifestBackgroundColor(
             PreferManifestBackgroundColor());
@@ -242,7 +242,7 @@
   Profile* profile() { return browser()->profile(); }
 
  private:
-  std::unique_ptr<web_app::TestSystemWebAppInstallation>
+  std::unique_ptr<ash::TestSystemWebAppInstallation>
       system_web_app_installation_;
   std::unique_ptr<net::EmbeddedTestServer> test_server_;
 };
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index bb25f03..b71bf95 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -894,12 +894,12 @@
   contents_container_ = AddChildView(std::move(contents_container));
   set_contents_view(contents_container_);
 
-    right_aligned_side_panel_ = AddChildView(std::make_unique<SidePanel>(this));
-    right_aligned_side_panel_separator_ =
-        AddChildView(std::make_unique<ContentsSeparator>());
-    if (base::FeatureList::IsEnabled(features::kUnifiedSidePanel)) {
-      side_panel_coordinator_ = std::make_unique<SidePanelCoordinator>(this);
-    }
+  right_aligned_side_panel_ = AddChildView(std::make_unique<SidePanel>(this));
+  right_aligned_side_panel_separator_ =
+      AddChildView(std::make_unique<ContentsSeparator>());
+  if (base::FeatureList::IsEnabled(features::kUnifiedSidePanel)) {
+    side_panel_coordinator_ = std::make_unique<SidePanelCoordinator>(this);
+  }
 
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
   if (lens::features::IsLensSidePanelEnabled()) {
@@ -912,12 +912,13 @@
 #endif
 
   if (browser_->is_type_normal() && IsSideSearchEnabled(browser_->profile())) {
-    side_search_side_panel_ = AddChildView(std::make_unique<SidePanel>(this));
-    left_aligned_side_panel_separator_ =
-        AddChildView(std::make_unique<ContentsSeparator>());
-
-    side_search_controller_ = std::make_unique<SideSearchBrowserController>(
-        side_search_side_panel_, this);
+    if (!base::FeatureList::IsEnabled(features::kUnifiedSidePanel)) {
+      side_search_side_panel_ = AddChildView(std::make_unique<SidePanel>(this));
+      left_aligned_side_panel_separator_ =
+          AddChildView(std::make_unique<ContentsSeparator>());
+      side_search_controller_ = std::make_unique<SideSearchBrowserController>(
+          side_search_side_panel_, this);
+    }
   }
 
   // InfoBarContainer needs to be added as a child here for drop-shadow, but
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index 8058e39..ca28063 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -488,6 +488,14 @@
   return browser_view()->GetRegularOrGuestSession();
 }
 
+bool OpaqueBrowserFrameView::CanMaximize() const {
+  return browser_view()->CanMaximize();
+}
+
+bool OpaqueBrowserFrameView::CanMinimize() const {
+  return browser_view()->CanMinimize();
+}
+
 bool OpaqueBrowserFrameView::IsMaximized() const {
   return frame()->IsMaximized();
 }
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
index a7cd472..0654c16 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -95,6 +95,8 @@
   gfx::Size GetBrowserViewMinimumSize() const override;
   bool ShouldShowCaptionButtons() const override;
   bool IsRegularOrGuestSession() const override;
+  bool CanMaximize() const override;
+  bool CanMinimize() const override;
   bool IsMaximized() const override;
   bool IsMinimized() const override;
   bool IsFullscreen() const override;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
index 8881bd77..ea38cd7 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -322,8 +322,8 @@
     }
   }
 
-  for (const auto& button : buttons_not_shown)
-    HideButton(button);
+  for (const auto& button_id : buttons_not_shown)
+    HideButton(button_id);
 }
 
 void OpaqueBrowserFrameViewLayout::LayoutTitleBar() {
@@ -434,22 +434,31 @@
                                                    ButtonAlignment alignment) {
   switch (button_id) {
     case views::FrameButton::kMinimize: {
-      SetViewVisibility(minimize_button_, true);
-      SetBoundsForButton(button_id, minimize_button_, alignment);
+      if (delegate_->CanMinimize()) {
+        SetViewVisibility(minimize_button_, true);
+        SetBoundsForButton(button_id, minimize_button_, alignment);
+      } else {
+        HideButton(button_id);
+      }
       break;
     }
     case views::FrameButton::kMaximize: {
-      // When the window is restored, we show a maximized button; otherwise, we
-      // show a restore button.
-      bool is_restored = !delegate_->IsMaximized() && !delegate_->IsMinimized();
-      views::Button* invisible_button =
-          is_restored ? restore_button_ : maximize_button_;
-      SetViewVisibility(invisible_button, false);
+      if (delegate_->CanMaximize()) {
+        // When the window is restored, we show a maximized button; otherwise,
+        // we show a restore button.
+        bool is_restored =
+            !delegate_->IsMaximized() && !delegate_->IsMinimized();
+        views::Button* invisible_button =
+            is_restored ? restore_button_ : maximize_button_;
+        SetViewVisibility(invisible_button, false);
 
-      views::Button* visible_button =
-          is_restored ? maximize_button_ : restore_button_;
-      SetViewVisibility(visible_button, true);
-      SetBoundsForButton(button_id, visible_button, alignment);
+        views::Button* visible_button =
+            is_restored ? maximize_button_ : restore_button_;
+        SetViewVisibility(visible_button, true);
+        SetBoundsForButton(button_id, visible_button, alignment);
+      } else {
+        HideButton(button_id);
+      }
       break;
     }
     case views::FrameButton::kClose: {
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h
index ad3901b0..c7f1753 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h
@@ -47,6 +47,9 @@
   virtual bool IsRegularOrGuestSession() const = 0;
 
   // Controls window state.
+  virtual bool CanMaximize() const = 0;
+  virtual bool CanMinimize() const = 0;
+
   virtual bool IsMaximized() const = 0;
   virtual bool IsMinimized() const = 0;
   virtual bool IsFullscreen() const = 0;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
index f65e8fa..b5ae260a 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -64,6 +64,8 @@
     return show_caption_buttons_;
   }
   bool IsRegularOrGuestSession() const override { return true; }
+  bool CanMaximize() const override { return true; }
+  bool CanMinimize() const override { return true; }
   bool IsMaximized() const override { return maximized_; }
   bool IsMinimized() const override { return false; }
   bool IsFullscreen() const override { return false; }
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.cc b/chrome/browser/ui/views/intent_picker_bubble_view.cc
index 70d5905..6acaf91 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view.cc
+++ b/chrome/browser/ui/views/intent_picker_bubble_view.cc
@@ -8,6 +8,7 @@
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
+#include "base/check_op.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/feature_list.h"
 #include "base/i18n/rtl.h"
@@ -94,7 +95,8 @@
 
 // Callback for when an app is selected in the app list. First parameter is the
 // index, second parameter is true if the dialog should be immediately accepted.
-using AppSelectedCallback = base::RepeatingCallback<void(size_t, bool)>;
+using AppSelectedCallback =
+    base::RepeatingCallback<void(absl::optional<size_t>, bool)>;
 
 // Grid view:
 
@@ -277,19 +279,27 @@
     ClipHeightTo(kGridItemPreferredSize, kGridItemPreferredSize * 2.5f);
   }
 
-  void SetSelectedIndex(size_t index) override {
+  void SetSelectedIndex(absl::optional<size_t> index) override {
     SetSelectedIndexInternal(index, false);
   }
 
-  size_t GetSelectedIndex() const override { return selected_app_index_; }
+  absl::optional<size_t> GetSelectedIndex() const override {
+    return selected_app_index_;
+  }
 
  private:
-  void SetSelectedIndexInternal(size_t new_index, bool accepted) {
-    GetButtonAtIndex(selected_app_index_)->SetSelected(false);
-    GetButtonAtIndex(new_index)->SetSelected(true);
+  void SetSelectedIndexInternal(absl::optional<size_t> new_index,
+                                bool accepted) {
+    if (selected_app_index_.has_value()) {
+      GetButtonAtIndex(selected_app_index_.value())->SetSelected(false);
+    }
+    if (new_index.has_value()) {
+      GetButtonAtIndex(new_index.value())->SetSelected(true);
+    }
 
-    if (GetButtonAtIndex(selected_app_index_)->HasFocus()) {
-      GetButtonAtIndex(new_index)->RequestFocus();
+    if (selected_app_index_.has_value() && new_index.has_value() &&
+        GetButtonAtIndex(selected_app_index_.value())->HasFocus()) {
+      GetButtonAtIndex(new_index.value())->RequestFocus();
     }
 
     selected_app_index_ = new_index;
@@ -304,11 +314,11 @@
 
   AppSelectedCallback selected_callback_;
 
-  size_t selected_app_index_ = 0;
+  absl::optional<size_t> selected_app_index_ = 0;
 };
 
 BEGIN_METADATA(IntentPickerAppGridView, views::ScrollView)
-ADD_PROPERTY_METADATA(size_t, SelectedIndex)
+ADD_PROPERTY_METADATA(absl::optional<size_t>, SelectedIndex)
 END_METADATA
 
 // List view:
@@ -388,11 +398,15 @@
 
   ~IntentPickerAppListView() override = default;
 
-  void SetSelectedIndex(size_t index) override {
-    SetSelectedAppIndex(index, nullptr);
+  void SetSelectedIndex(absl::optional<size_t> index) override {
+    DCHECK(index.has_value());  // List-style intent picker does not support
+                                // having no selection.
+    SetSelectedAppIndex(index.value(), nullptr);
   }
 
-  size_t GetSelectedIndex() const override { return selected_app_index_; }
+  absl::optional<size_t> GetSelectedIndex() const override {
+    return selected_app_index_;
+  }
 
   void OnKeyEvent(ui::KeyEvent* event) override {
     if (!IsKeyboardCodeArrow(event->key_code()) ||
@@ -469,7 +483,7 @@
 };
 
 BEGIN_METADATA(IntentPickerAppListView, views::ScrollView)
-ADD_PROPERTY_METADATA(size_t, SelectedIndex)
+ADD_PROPERTY_METADATA(absl::optional<size_t>, SelectedIndex)
 END_METADATA
 
 }  // namespace
@@ -508,7 +522,8 @@
 
   DCHECK(intent_picker_bubble_->HasCandidates());
   widget->Show();
-  intent_picker_bubble_->SetSelectedIndex(0);
+
+  intent_picker_bubble_->SelectDefaultItem();
   return widget;
 }
 
@@ -527,9 +542,12 @@
   bool should_persist = remember_selection_checkbox_ &&
                         remember_selection_checkbox_->GetChecked();
   auto selected_index = GetSelectedIndex();
-  RunCallbackAndCloseBubble(
-      app_info_[selected_index].launch_name, app_info_[selected_index].type,
-      apps::IntentPickerCloseReason::OPEN_APP, should_persist);
+  // Dialog cannot be accepted when there is no selection.
+  DCHECK(selected_index.has_value());
+  RunCallbackAndCloseBubble(app_info_[selected_index.value()].launch_name,
+                            app_info_[selected_index.value()].type,
+                            apps::IntentPickerCloseReason::OPEN_APP,
+                            should_persist);
 }
 
 void IntentPickerBubbleView::OnDialogCancelled() {
@@ -553,12 +571,19 @@
   return true;
 }
 
-void IntentPickerBubbleView::SetSelectedIndex(size_t index) {
-  DCHECK_LT(index, app_info_.size());
-  apps_view_->SetSelectedIndex(index);
+void IntentPickerBubbleView::SelectDefaultItem() {
+  if (use_grid_view_ && app_info_.size() > 1) {
+    apps_view_->SetSelectedIndex(absl::nullopt);
+    // The default button is disabled in this case. Clear the focus so it
+    // returns to the window, as if there was no default button in the first
+    // place.
+    GetWidget()->GetFocusManager()->ClearFocus();
+  } else {
+    apps_view_->SetSelectedIndex(0);
+  }
 }
 
-size_t IntentPickerBubbleView::GetSelectedIndex() const {
+absl::optional<size_t> IntentPickerBubbleView::GetSelectedIndex() const {
   return apps_view_->GetSelectedIndex();
 }
 
@@ -631,10 +656,16 @@
                             false);
 }
 
-void IntentPickerBubbleView::OnAppSelected(size_t index, bool accepted) {
-  UpdateCheckboxState(index);
+void IntentPickerBubbleView::OnAppSelected(absl::optional<size_t> index,
+                                           bool accepted) {
+  SetButtonEnabled(ui::DIALOG_BUTTON_OK, index.has_value());
+
+  if (index.has_value()) {
+    UpdateCheckboxState(index.value());
+  }
 
   if (accepted) {
+    DCHECK(index.has_value());
     AcceptDialog();
   }
 }
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.h b/chrome/browser/ui/views/intent_picker_bubble_view.h
index 10f590f..1dfe688e 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view.h
+++ b/chrome/browser/ui/views/intent_picker_bubble_view.h
@@ -103,15 +103,20 @@
 
   BubbleType bubble_type() const { return bubble_type_; }
 
-  void SetSelectedIndex(size_t index);
-  size_t GetSelectedIndex() const;
+  // Selects the default app for the current configuration. Must be called after
+  // the Bubble is shown.
+  void SelectDefaultItem();
+
+  // Returns the index of the currently selected item. May return nullopt to
+  // indicate no selection.
+  absl::optional<size_t> GetSelectedIndex() const;
 
   // A ScrollView which contains a list of apps. This view manages the selection
   // state for the dialog.
   class IntentPickerAppsView : public views::ScrollView {
    public:
-    virtual void SetSelectedIndex(size_t index) = 0;
-    virtual size_t GetSelectedIndex() const = 0;
+    virtual void SetSelectedIndex(absl::optional<size_t> index) = 0;
+    virtual absl::optional<size_t> GetSelectedIndex() const = 0;
   };
 
   const std::vector<AppInfo>& app_info_for_testing() const { return app_info_; }
@@ -127,9 +132,11 @@
   // views::BubbleDialogDelegateView overrides:
   void OnWidgetDestroying(views::Widget* widget) override;
 
-  // Called when the app at |index| is selected in the app list. If |accepted|
-  // is true, the dialog should be immediately accepted with that app selected.
-  void OnAppSelected(size_t index, bool accepted);
+  // Called when the app at |index| is selected in the app list. If
+  // |accepted| is true, the dialog should be immediately accepted with that app
+  // selected. If |index| is nullopt, no app is selected, and the Accept button
+  // will be disabled
+  void OnAppSelected(absl::optional<size_t> index, bool accepted);
 
   void Initialize();
 
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc
index b88d77b..7ca6bfb 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc
@@ -456,6 +456,20 @@
     feature_list_.InitAndEnableFeature(apps::features::kLinkCapturingUiUpdate);
   }
 
+  void ShowUi(const std::string& name) override {
+    IntentPickerDialogTest::ShowUi(name);
+
+    // Click the first item in the list so we can verify the selection state.
+    auto* bubble = IntentPickerBubbleView::intent_picker_bubble();
+    auto event_generator =
+        ui::test::EventGenerator(views::GetRootWindow(bubble->GetWidget()));
+    auto* button =
+        bubble->GetViewByID(IntentPickerBubbleView::ViewId::kItemContainer)
+            ->children()[0];
+    event_generator.MoveMouseTo(button->GetBoundsInScreen().CenterPoint());
+    event_generator.ClickLeftButton();
+  }
+
  private:
   views::Button* GetAnchorButton() override {
     return BrowserView::GetBrowserViewForBrowser(browser())
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc b/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc
index 21402144..fb0da72 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc
@@ -75,17 +75,12 @@
                         bool show_stay_in_chrome,
                         BubbleType bubble_type,
                         const absl::optional<url::Origin>& initiating_origin) {
+    DCHECK(!app_info_.empty());
     BrowserView* browser_view =
         BrowserView::GetBrowserViewForBrowser(browser());
     anchor_view_ =
         browser_view->toolbar()->AddChildView(std::make_unique<views::View>());
 
-    // Pushing a couple of fake apps just to check they are created on the UI.
-    app_info_.emplace_back(apps::PickerEntryType::kArc, ui::ImageModel(),
-                           "package_1", "dank app 1");
-    app_info_.emplace_back(apps::PickerEntryType::kArc, ui::ImageModel(),
-                           "package_2", "dank_app_2");
-
     if (use_icons)
       FillAppListWithDummyIcons();
 
@@ -126,6 +121,11 @@
     app_info_.emplace_back(app_type, ui::ImageModel(), launch_name, title);
   }
 
+  void AddDefaultApps() {
+    AddApp(apps::PickerEntryType::kArc, "package_1", "App 1");
+    AddApp(apps::PickerEntryType::kArc, "package_2", "App 2");
+  }
+
   void FillAppListWithDummyIcons() {
     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
     ui::ImageModel dummy_icon_model =
@@ -186,6 +186,7 @@
 
 // Verifies that we didn't set up an image for any LabelButton.
 TEST_F(IntentPickerBubbleViewTest, NullIcons) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/true,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -199,6 +200,7 @@
 
 // Verifies that all the icons contain a non-null icon.
 TEST_F(IntentPickerBubbleViewTest, NonNullIcons) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/true, /*show_stay_in_chrome=*/true,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -215,6 +217,7 @@
 // shown to the user on the picker UI, so there could be a difference
 // represented by |chrome_package_repetitions|.
 TEST_F(IntentPickerBubbleViewTest, LabelsPtrVectorSize) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/true, /*show_stay_in_chrome=*/true,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -226,6 +229,7 @@
 // Verifies that the first item is activated by default when creating a new
 // bubble.
 TEST_F(IntentPickerBubbleViewTest, VerifyStartingInkDrop) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/true, /*show_stay_in_chrome=*/true,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -239,6 +243,7 @@
 // Press each button at a time and make sure it goes to ACTIVATED state,
 // followed by HIDDEN state after selecting other button.
 TEST_F(IntentPickerBubbleViewTest, InkDropStateTransition) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/true, /*show_stay_in_chrome=*/true,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -252,6 +257,7 @@
 
 // Arbitrary press a button twice, check that the InkDropState remains the same.
 TEST_F(IntentPickerBubbleViewTest, PressButtonTwice) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/true, /*show_stay_in_chrome=*/true,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -266,6 +272,7 @@
 
 // Check that a non nullptr WebContents() has been created and observed.
 TEST_F(IntentPickerBubbleViewTest, WebContentsTiedToBubble) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -279,6 +286,7 @@
 
 // Check that that the correct window title is shown.
 TEST_F(IntentPickerBubbleViewTest, WindowTitle) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -295,6 +303,7 @@
 
 // Check that that the correct button labels are used.
 TEST_F(IntentPickerBubbleViewTest, ButtonLabels) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -316,6 +325,7 @@
 }
 
 TEST_F(IntentPickerBubbleViewTest, InitiatingOriginView) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
@@ -402,6 +412,8 @@
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
 
+  ClickApp(0);
+
   views::Checkbox* checkbox = static_cast<views::Checkbox*>(
       bubble_->GetViewByID(IntentPickerBubbleView::ViewId::kRememberCheckbox));
   checkbox->SetChecked(true);
@@ -447,10 +459,12 @@
 #define MAYBE_KeyboardNavigation KeyboardNavigation
 #endif
 TEST_P(IntentPickerBubbleViewLayoutTest, MAYBE_KeyboardNavigation) {
+  AddDefaultApps();
   CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false,
                    BubbleType::kLinkCapturing,
                    /*initiating_origin=*/absl::nullopt);
 
+  ClickApp(0);
   GetButtonAtIndex(0)->RequestFocus();
 
   event_generator_->PressAndReleaseKey(ui::VKEY_DOWN);
@@ -485,3 +499,29 @@
                          IntentPickerBubbleViewLayoutTest,
                          testing::Values(BubbleInterfaceType::kListView,
                                          BubbleInterfaceType::kGridView));
+
+class IntentPickerBubbleViewGridLayoutTest : public IntentPickerBubbleViewTest {
+ private:
+  base::test::ScopedFeatureList feature_list_{
+      apps::features::kLinkCapturingUiUpdate};
+};
+
+TEST_F(IntentPickerBubbleViewGridLayoutTest, DefaultSelectionOneApp) {
+  AddApp(apps::PickerEntryType::kWeb, "web_app_id", "Web App");
+  CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false,
+                   BubbleType::kLinkCapturing,
+                   /*initiating_origin=*/absl::nullopt);
+
+  ASSERT_EQ(bubble_->GetSelectedIndex(), 0u);
+}
+
+TEST_F(IntentPickerBubbleViewGridLayoutTest, DefaultSelectionTwoApps) {
+  AddApp(apps::PickerEntryType::kWeb, "web_app_id_1", "Web App");
+  AddApp(apps::PickerEntryType::kWeb, "web_app_id_2", "Web App");
+
+  CreateBubbleView(/*use_icons=*/false, /*show_stay_in_chrome=*/false,
+                   BubbleType::kLinkCapturing,
+                   /*initiating_origin=*/absl::nullopt);
+
+  ASSERT_FALSE(bubble_->GetSelectedIndex().has_value());
+}
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
index 8dbd3a57..1825995 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
@@ -260,7 +260,13 @@
   EXPECT_FALSE(custom_tab_bar_);
 }
 
-IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest, IsNotCreatedInPopup) {
+// TODO(crbug.com/1338068): Re-enable this test
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_IsNotCreatedInPopup DISABLED_IsNotCreatedInPopup
+#else
+#define MAYBE_IsNotCreatedInPopup IsNotCreatedInPopup
+#endif
+IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest, MAYBE_IsNotCreatedInPopup) {
   Browser* popup = OpenPopup(browser_view_->GetActiveWebContents(),
                              GURL("http://example.com"));
   EXPECT_TRUE(popup);
@@ -277,8 +283,15 @@
   EXPECT_FALSE(popup_view->toolbar()->custom_tab_bar());
 }
 
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_BackToAppButtonIsNotVisibleInOutOfScopePopups \
+  DISABLED_BackToAppButtonIsNotVisibleInOutOfScopePopups
+#else
+#define MAYBE_BackToAppButtonIsNotVisibleInOutOfScopePopups \
+  BackToAppButtonIsNotVisibleInOutOfScopePopups
+#endif
 IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest,
-                       BackToAppButtonIsNotVisibleInOutOfScopePopups) {
+                       MAYBE_BackToAppButtonIsNotVisibleInOutOfScopePopups) {
   const GURL app_url = https_server()->GetURL("app.com", "/ssl/google.html");
   const GURL out_of_scope_url = GURL("https://example.com");
 
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
index fd640df..bcec8e5 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
@@ -9,7 +9,6 @@
 #include "base/scoped_observation.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "build/build_config.h"
-#include "chrome/browser/certificate_viewer.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
@@ -178,7 +177,6 @@
       const PageInfoBubbleViewBrowserTest& test) = delete;
 
   void SetUp() override {
-    MockCertificateViewerForTesting();
     ASSERT_TRUE(embedded_test_server()->Start());
     InProcessBrowserTest::SetUp();
   }
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc
index ad74ce1..0fde7a7 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -54,7 +54,6 @@
 #include "components/signin/core/browser/signin_error_controller.h"
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/base/signin_pref_names.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/primary_account_mutator.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/vector_icons/vector_icons.h"
@@ -634,9 +633,7 @@
   bool add_sign_out_button = has_unconsented_account && !has_primary_account;
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // Clearing the primary account is not allowed in the main profile.
-  add_sign_out_button &=
-      (!profile->IsMainProfile() &&
-       base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles));
+  add_sign_out_button &= !profile->IsMainProfile();
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
   // The sign-out button is always at the bottom.
   if (add_sign_out_button) {
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
index 1741eb0..978a47c 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
@@ -88,7 +88,6 @@
 #include "chrome/browser/signin/signin_ui_delegate_impl_lacros.h"
 #include "components/account_manager_core/chromeos/account_manager_facade_factory.h"
 #include "components/account_manager_core/chromeos/fake_account_manager_ui.h"
-#include "components/signin/public/base/signin_switches.h"
 #endif
 
 namespace {
@@ -215,10 +214,6 @@
 
  private:
   Browser* target_browser_ = nullptr;
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  base::test::ScopedFeatureList feature_list_{
-      switches::kLacrosNonSyncingProfiles};
-#endif
 };
 
 class ProfileMenuViewExtensionsTest : public ProfileMenuViewTestBase,
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
index ba24e88a..c9d8bdc 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
@@ -72,7 +72,6 @@
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
@@ -1838,9 +1837,6 @@
   // be triggered and completed before we enter the test body.
   base::HistogramTester histogram_tester_;
 
-  base::test::ScopedFeatureList feature_list_{
-      switches::kLacrosNonSyncingProfiles};
-
   // Lifts the timeout to make sure it is not hiding errors where we don't get
   // the signal that the sync service started.
   // TODO(https://crbug.com/1324886): Find a better way to safely work around
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
index c1ce1bd..2145f5c0 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
@@ -236,7 +236,7 @@
 }
 
 void SidePanelCoordinator::Toggle() {
-  if (GetContentView() != nullptr) {
+  if (IsSidePanelShowing()) {
     Close();
   } else {
     Show();
@@ -252,11 +252,22 @@
   no_delays_for_testing_ = true;
 }
 
+absl::optional<SidePanelEntry::Id> SidePanelCoordinator::GetCurrentEntryId()
+    const {
+  return current_entry_
+             ? absl::optional<SidePanelEntry::Id>(current_entry_->id())
+             : absl::nullopt;
+}
+
 SidePanelEntry::Id SidePanelCoordinator::GetComboboxDisplayedEntryIdForTesting()
     const {
   return combobox_model_->GetIdAt(header_combobox_->GetSelectedIndex());
 }
 
+bool SidePanelCoordinator::IsSidePanelShowing() {
+  return GetContentView() != nullptr;
+}
+
 views::View* SidePanelCoordinator::GetContentView() const {
   return browser_view_->right_aligned_side_panel()->GetViewByID(
       kSidePanelContentViewId);
@@ -325,15 +336,17 @@
     auto current_entry_view =
         content_wrapper->RemoveChildViewT(content_wrapper->children().front());
     current_entry_->CacheView(std::move(current_entry_view));
-    current_entry_->OnEntryHidden();
   }
   content_wrapper->AddChildView(content_view.has_value()
                                     ? std::move(content_view.value())
                                     : entry->GetContent());
   if (auto* contextual_registry = GetActiveContextualRegistry())
     contextual_registry->ResetActiveEntry();
+  auto* previous_entry = current_entry_.get();
   current_entry_ = entry->GetWeakPtr();
   entry->OnEntryShown();
+  if (previous_entry)
+    previous_entry->OnEntryHidden();
 }
 
 void SidePanelCoordinator::ClearCachedEntryViews() {
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator.h b/chrome/browser/ui/views/side_panel/side_panel_coordinator.h
index 37be3a2..7a919a9 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator.h
+++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator.h
@@ -52,8 +52,12 @@
     return current_entry_.get();
   }
 
+  absl::optional<SidePanelEntry::Id> GetCurrentEntryId() const;
+
   SidePanelEntry::Id GetComboboxDisplayedEntryIdForTesting() const;
 
+  bool IsSidePanelShowing();
+
  private:
   friend class SidePanelCoordinatorTest;
   FRIEND_TEST_ALL_PREFIXES(UserNoteUICoordinatorTest,
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator_unittest.cc b/chrome/browser/ui/views/side_panel/side_panel_coordinator_unittest.cc
index 3bb6bb0..c71e8a3 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator_unittest.cc
+++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator_unittest.cc
@@ -25,7 +25,12 @@
  public:
   void SetUp() override {
     base::test::ScopedFeatureList features;
-    features.InitWithFeatures({features::kUnifiedSidePanel}, {});
+    // Need to disable side search to prevent `UnifiedSideSearchController` from
+    // removing the entry due to side search requirement not met.
+    // TODO(crbug.com/1336417): Remove features::kSideSearch from disabled
+    // feature.
+    features.InitWithFeatures({features::kUnifiedSidePanel},
+                              {features::kSideSearch});
     TestWithBrowserView::SetUp();
 
     AddTab(browser_view()->browser(), GURL("http://foo1.com"));
diff --git a/chrome/browser/ui/views/side_search/side_search_browser_controller_interactive_uitest.cc b/chrome/browser/ui/views/side_search/side_search_browser_controller_interactive_uitest.cc
index 5cd2d92..fd3dad9 100644
--- a/chrome/browser/ui/views/side_search/side_search_browser_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/side_search/side_search_browser_controller_interactive_uitest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/side_panel/side_panel.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_web_ui_view.h"
 #include "chrome/browser/ui/views/side_search/side_search_icon_view.h"
 #include "chrome/browser/ui/views/toolbar/side_panel_toolbar_button.h"
@@ -221,7 +222,7 @@
             SideSearchBrowserController::VIEW_ID_SIDE_PANEL_CLOSE_BUTTON)));
   }
 
-  SidePanel* GetSidePanelFor(Browser* browser) {
+  virtual SidePanel* GetSidePanelFor(Browser* browser) {
     return BrowserViewFor(browser)->side_search_side_panel_for_testing();
   }
 
@@ -835,6 +836,162 @@
       SideSearchPageActionLabelVisibility::kNotVisible, 1);
 }
 
+// Fixture for testing side panel v2 only
+// TODO(yuhengh): Break this away to its own test file.
+class SideSearchV2Test : public SideSearchBrowserControllerTest {
+ public:
+  void SetUp() override {
+    scoped_feature_list_.InitWithFeatures({features::kUnifiedSidePanel}, {});
+    SideSearchBrowserControllerTest::SetUp();
+  }
+  void TearDown() override {
+    SideSearchBrowserControllerTest::TearDown();
+    scoped_feature_list_.Reset();
+  }
+  SidePanel* GetSidePanelFor(Browser* browser) override {
+    return BrowserViewFor(browser)->right_aligned_side_panel();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Only instantiate tests for DSE configuration.
+INSTANTIATE_TEST_SUITE_P(All, SideSearchV2Test, ::testing::Values(true));
+
+IN_PROC_BROWSER_TEST_P(SideSearchV2Test, SwitchSidePanelInSingleTab) {
+  auto* browser_view = BrowserViewFor(browser());
+  auto* coordinator = browser_view->side_panel_coordinator();
+  coordinator->SetNoDelaysForTesting();
+
+  // Tab 0 with side search available and open.
+  AppendTab(browser(), GetMatchingSearchUrl());
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_TRUE(GetSidePanelButtonFor(browser())->GetVisible());
+  NotifyButtonClick(browser());
+  EXPECT_FALSE(GetSidePanelButtonFor(browser())->GetVisible());
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Switch to reading list side panel.
+  coordinator->Show(SidePanelEntry::Id::kReadingList);
+  EXPECT_TRUE(GetSidePanelButtonFor(browser())->GetVisible());
+  EXPECT_EQ(SidePanelEntry::Id::kReadingList,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Switch back to side search side panel.
+  coordinator->Show(SidePanelEntry::Id::kSideSearch);
+  EXPECT_FALSE(GetSidePanelButtonFor(browser())->GetVisible());
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+}
+
+IN_PROC_BROWSER_TEST_P(SideSearchV2Test, SwitchTabsWithGlobalSidePanel) {
+  auto* browser_view = BrowserViewFor(browser());
+  auto* coordinator = browser_view->side_panel_coordinator();
+  coordinator->SetNoDelaysForTesting();
+
+  // Tab 0 without side search available and open with reading list.
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_FALSE(GetSidePanelButtonFor(browser())->GetVisible());
+  coordinator->Show(SidePanelEntry::Id::kReadingList);
+  EXPECT_EQ(SidePanelEntry::Id::kReadingList,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Tab 1 with side search available and open.
+  AppendTab(browser(), GetMatchingSearchUrl());
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_TRUE(GetSidePanelButtonFor(browser())->GetVisible());
+  NotifyButtonClick(browser());
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Tab 2 with side search available and open.
+  AppendTab(browser(), GetMatchingSearchUrl());
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_TRUE(GetSidePanelButtonFor(browser())->GetVisible());
+  NotifyButtonClick(browser());
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Tab 3 with side search available but not open.
+  AppendTab(browser(), GetMatchingSearchUrl());
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_TRUE(GetSidePanelButtonFor(browser())->GetVisible());
+  EXPECT_EQ(SidePanelEntry::Id::kReadingList,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Switch to tab 0, side panel is open with reading list.
+  ActivateTabAt(browser(), 0);
+  EXPECT_EQ(SidePanelEntry::Id::kReadingList,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Switch to tab 1, side panel is open with side search.
+  ActivateTabAt(browser(), 1);
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Switch to tab 2, side panel is open with side search.
+  ActivateTabAt(browser(), 2);
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Switch to tab 3, side panel is open with reading list.
+  ActivateTabAt(browser(), 3);
+  EXPECT_EQ(SidePanelEntry::Id::kReadingList,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+}
+
+IN_PROC_BROWSER_TEST_P(SideSearchV2Test, SwitchTabsWithoutGlobalSidePanel) {
+  auto* browser_view = BrowserViewFor(browser());
+  auto* coordinator = browser_view->side_panel_coordinator();
+
+  // Tab 0 without side search available.
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_FALSE(GetSidePanelButtonFor(browser())->GetVisible());
+  EXPECT_EQ(nullptr, coordinator->GetCurrentSidePanelEntryForTesting());
+
+  // Tab 1 with side search available and open.
+  AppendTab(browser(), GetMatchingSearchUrl());
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_TRUE(GetSidePanelButtonFor(browser())->GetVisible());
+  NotifyButtonClick(browser());
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Tab 2 with side search available and open.
+  AppendTab(browser(), GetMatchingSearchUrl());
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_TRUE(GetSidePanelButtonFor(browser())->GetVisible());
+  NotifyButtonClick(browser());
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Tab 3 with side search available but not open.
+  AppendTab(browser(), GetMatchingSearchUrl());
+  NavigateActiveTab(browser(), GetNonMatchingUrl());
+  EXPECT_TRUE(GetSidePanelButtonFor(browser())->GetVisible());
+  EXPECT_EQ(nullptr, coordinator->GetCurrentSidePanelEntryForTesting());
+
+  // Switch to tab 0, side panel is closed.
+  ActivateTabAt(browser(), 0);
+  EXPECT_EQ(nullptr, coordinator->GetCurrentSidePanelEntryForTesting());
+
+  // Switch to tab 1, side panel is open with side search.
+  ActivateTabAt(browser(), 1);
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Switch to tab 2, side panel is open with side search.
+  ActivateTabAt(browser(), 2);
+  EXPECT_EQ(SidePanelEntry::Id::kSideSearch,
+            coordinator->GetCurrentSidePanelEntryForTesting()->id());
+
+  // Switch to tab 3, side panel is closed.
+  ActivateTabAt(browser(), 3);
+  EXPECT_EQ(nullptr, coordinator->GetCurrentSidePanelEntryForTesting());
+}
+
 // Fixture for testing side panel clobbering behavior with global panels.
 class SideSearchDSEClobberingTest : public SideSearchBrowserControllerTest {
  public:
diff --git a/chrome/browser/ui/views/side_search/side_search_icon_view.cc b/chrome/browser/ui/views/side_search/side_search_icon_view.cc
index df38cb8f..8e675a9b 100644
--- a/chrome/browser/ui/views/side_search/side_search_icon_view.cc
+++ b/chrome/browser/ui/views/side_search/side_search_icon_view.cc
@@ -10,9 +10,11 @@
 #include "chrome/browser/ui/side_search/side_search_config.h"
 #include "chrome/browser/ui/side_search/side_search_metrics.h"
 #include "chrome/browser/ui/side_search/side_search_tab_contents_helper.h"
+#include "chrome/browser/ui/side_search/side_search_utils.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/side_search/side_search_browser_controller.h"
+#include "chrome/browser/ui/views/side_search/unified_side_search_controller.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/feature_engagement/public/event_constants.h"
 #include "components/feature_engagement/public/feature_constants.h"
@@ -23,6 +25,19 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/view_class_properties.h"
 
+namespace {
+
+bool IsSideSearchToggleOpen(BrowserView* browser_view) {
+  if (base::FeatureList::IsEnabled(features::kUnifiedSidePanel)) {
+    auto* coordinator = browser_view->side_panel_coordinator();
+    return coordinator->IsSidePanelShowing() &&
+           coordinator->GetCurrentEntryId() == SidePanelEntry::Id::kSideSearch;
+  }
+  return browser_view->side_search_controller()->GetSidePanelToggledOpen();
+}
+
+}  // namespace
+
 SideSearchIconView::SideSearchIconView(
     CommandUpdater* command_updater,
     IconLabelBubbleView::Delegate* icon_label_bubble_delegate,
@@ -83,7 +98,7 @@
   const bool was_visible = GetVisible();
   const bool should_show =
       tab_contents_helper->CanShowSidePanelForCommittedNavigation() &&
-      !tab_contents_helper->toggled_open();
+      !IsSideSearchToggleOpen(browser_view);
   SetVisible(should_show);
 
   if (should_show && !was_visible) {
@@ -106,8 +121,6 @@
 }
 
 void SideSearchIconView::OnExecuting(PageActionIconView::ExecuteSource source) {
-  auto* side_search_browser_controller =
-      BrowserView::GetBrowserViewForBrowser(browser_)->side_search_controller();
   RecordSideSearchPageActionLabelVisibilityOnToggle(
       label()->GetVisible() ? SideSearchPageActionLabelVisibility::kVisible
                             : SideSearchPageActionLabelVisibility::kNotVisible);
@@ -115,8 +128,15 @@
   // Reset the slide animation if in progress.
   HidePageActionLabel();
 
-  side_search_browser_controller->ToggleSidePanel();
-
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
+  if (base::FeatureList::IsEnabled(features::kUnifiedSidePanel)) {
+    content::WebContents* active_contents =
+        browser_view->GetActiveWebContents();
+    UnifiedSideSearchController::FromWebContents(active_contents)
+        ->OpenSidePanel();
+  } else {
+    browser_view->side_search_controller()->ToggleSidePanel();
+  }
   auto* tracker = feature_engagement::TrackerFactory::GetForBrowserContext(
       browser_->profile());
   if (tracker)
diff --git a/chrome/browser/ui/views/side_search/unified_side_search_controller.cc b/chrome/browser/ui/views/side_search/unified_side_search_controller.cc
new file mode 100644
index 0000000..8d4e7cf
--- /dev/null
+++ b/chrome/browser/ui/views/side_search/unified_side_search_controller.cc
@@ -0,0 +1,188 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/side_search/unified_side_search_controller.h"
+
+#include "base/bind.h"
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/color/chrome_color_id.h"
+#include "chrome/browser/ui/side_search/side_search_utils.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/side_panel/side_panel.h"
+#include "content/public/browser/navigation_handle.h"
+#include "ui/views/controls/webview/webview.h"
+#include "ui/views/layout/flex_layout_types.h"
+#include "ui/views/layout/flex_layout_view.h"
+
+UnifiedSideSearchController::UnifiedSideSearchController(
+    content::WebContents* web_contents)
+    : content::WebContentsUserData<UnifiedSideSearchController>(*web_contents) {
+  auto* helper = SideSearchTabContentsHelper::FromWebContents(web_contents);
+  if (helper)
+    helper->SetDelegate(weak_factory_.GetWeakPtr());
+
+  Observe(web_contents);
+
+  // Update the state of the side panel to catch cases where we switch to a tab
+  // where the panel should be hidden (or vise versa).
+  UpdateSidePanel();
+}
+
+UnifiedSideSearchController::~UnifiedSideSearchController() {
+  Observe(nullptr);
+}
+
+bool UnifiedSideSearchController::HandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  auto* browser_view = GetBrowserView();
+  return browser_view ? unhandled_keyboard_event_handler_.HandleKeyboardEvent(
+                            event, browser_view->GetFocusManager())
+                      : false;
+}
+
+content::WebContents* UnifiedSideSearchController::OpenURLFromTab(
+    content::WebContents* source,
+    const content::OpenURLParams& params) {
+  auto* browser_view = GetBrowserView();
+  return browser_view ? browser_view->browser()->OpenURL(params) : nullptr;
+}
+
+void UnifiedSideSearchController::SidePanelAvailabilityChanged(
+    bool should_close) {
+  if (should_close) {
+    CloseSidePanel();
+  } else {
+    UpdateSidePanel();
+  }
+}
+
+void UnifiedSideSearchController::DidFinishNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (!navigation_handle->IsInPrimaryMainFrame() ||
+      navigation_handle->IsSameDocument() ||
+      !navigation_handle->HasCommitted()) {
+    return;
+  }
+
+  UpdateSidePanel();
+}
+
+void UnifiedSideSearchController::OnEntryShown(SidePanelEntry* entry) {
+  UpdateSidePanel();
+}
+
+void UnifiedSideSearchController::OnEntryHidden(SidePanelEntry* entry) {
+  UpdateSidePanel();
+}
+
+std::unique_ptr<views::View> UnifiedSideSearchController::GetSideSearchView() {
+  auto* browser_view = GetBrowserView();
+  DCHECK(browser_view);
+  auto side_search_view =
+      std::make_unique<views::WebView>(browser_view->GetProfile());
+  side_search_view->SetProperty(
+      views::kFlexBehaviorKey,
+      views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
+                               views::MaximumFlexSizeRule::kUnbounded));
+  side_search_view->SetBackground(
+      views::CreateThemedSolidBackground(kColorToolbar));
+  auto* tab_contents_helper =
+      SideSearchTabContentsHelper::FromWebContents(web_contents());
+  DCHECK(tab_contents_helper);
+  side_search_view->SetWebContents(tab_contents_helper->GetSidePanelContents());
+  return std::move(side_search_view);
+}
+
+void UnifiedSideSearchController::OpenSidePanel() {
+  auto* browser_view = GetBrowserView();
+  if (browser_view) {
+    browser_view->side_panel_coordinator()->Show(
+        SidePanelEntry::Id::kSideSearch);
+  }
+  UpdateSidePanel();
+}
+
+void UnifiedSideSearchController::CloseSidePanel(
+    absl::optional<SideSearchCloseActionType> action) {
+  auto* browser_view = GetBrowserView();
+  if (browser_view) {
+    browser_view->side_panel_coordinator()->Close();
+  }
+  UpdateSidePanel();
+
+  // Clear the side contents for the currently active tab.
+  ClearSideContentsCache();
+}
+
+BrowserView* UnifiedSideSearchController::GetBrowserView() const {
+  auto* browser = chrome::FindBrowserWithWebContents(web_contents());
+  return browser ? BrowserView::GetBrowserViewForBrowser(browser) : nullptr;
+}
+
+void UnifiedSideSearchController::ClearSideContentsCache() {
+  auto* browser_view = GetBrowserView();
+  if (!browser_view)
+    return;
+  DCHECK(!browser_view->side_panel_coordinator()->IsSidePanelShowing());
+  auto* registry = SidePanelRegistry::Get(web_contents());
+  if (!registry)
+    return;
+  auto* current_entry =
+      registry->GetEntryForId(SidePanelEntry::Id::kSideSearch);
+  if (current_entry)
+    current_entry->ClearCachedView();
+
+  auto* helper = SideSearchTabContentsHelper::FromWebContents(web_contents());
+  if (helper)
+    helper->ClearSidePanelContents();
+}
+
+void UnifiedSideSearchController::UpdateSidePanel() {
+  auto* tab_contents_helper =
+      SideSearchTabContentsHelper::FromWebContents(web_contents());
+
+  // Early return if the tab helper for the active tab is not defined
+  // (crbug.com/1307908).
+  if (!tab_contents_helper)
+    return;
+
+  UpdateSidePanelRegistry(
+      tab_contents_helper->CanShowSidePanelForCommittedNavigation());
+
+  auto* browser_view = GetBrowserView();
+  // GetBrowserView() can return nullptr when the WebContents
+  // is detached and about to move into another browser.
+  if (browser_view) {
+    browser_view->UpdatePageActionIcon(PageActionIconType::kSideSearch);
+    browser_view->InvalidateLayout();
+  }
+}
+
+void UnifiedSideSearchController::UpdateSidePanelRegistry(bool is_available) {
+  auto* registry = SidePanelRegistry::Get(web_contents());
+  if (!registry)
+    return;
+  auto* current_entry =
+      registry->GetEntryForId(SidePanelEntry::Id::kSideSearch);
+  if (!current_entry && is_available) {
+    // TODO(yuhengh): Replace with default search engine name and icon.
+    auto entry = std::make_unique<SidePanelEntry>(
+        SidePanelEntry::Id::kSideSearch, u"Side Search",
+        ui::ImageModel::FromVectorIcon(kReadLaterIcon, ui::kColorIcon),
+        base::BindRepeating(&UnifiedSideSearchController::GetSideSearchView,
+                            base::Unretained(this)));
+    entry->AddObserver(this);
+    registry->Register(std::move(entry));
+  }
+
+  if (current_entry && !is_available) {
+    current_entry->RemoveObserver(this);
+    registry->Deregister(SidePanelEntry::Id::kSideSearch);
+  }
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(UnifiedSideSearchController);
diff --git a/chrome/browser/ui/views/side_search/unified_side_search_controller.h b/chrome/browser/ui/views/side_search/unified_side_search_controller.h
new file mode 100644
index 0000000..5a13eb5
--- /dev/null
+++ b/chrome/browser/ui/views/side_search/unified_side_search_controller.h
@@ -0,0 +1,83 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_UNIFIED_SIDE_SEARCH_CONTROLLER_H_
+#define CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_UNIFIED_SIDE_SEARCH_CONTROLLER_H_
+
+#include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
+#include "base/supports_user_data.h"
+#include "base/timer/elapsed_timer.h"
+#include "chrome/browser/ui/side_search/side_search_metrics.h"
+#include "chrome/browser/ui/side_search/side_search_tab_contents_helper.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
+#include "chrome/browser/ui/views/side_panel/side_panel_registry_observer.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
+#include "ui/views/view.h"
+
+class BrowserView;
+
+// Responsible for managing the WebContents hosted in the browser's side panel
+// for Side Search. Created immediately following the creation of the tab's
+// WebContents.
+class UnifiedSideSearchController
+    : public SideSearchTabContentsHelper::Delegate,
+      public content::WebContentsObserver,
+      public SidePanelEntryObserver,
+      public content::WebContentsUserData<UnifiedSideSearchController> {
+ public:
+  explicit UnifiedSideSearchController(content::WebContents* web_contents);
+  UnifiedSideSearchController(const UnifiedSideSearchController&) = delete;
+  UnifiedSideSearchController& operator=(const UnifiedSideSearchController&) =
+      delete;
+  ~UnifiedSideSearchController() override;
+
+  // SideSearchTabContentsHelper::Delegate:
+  bool HandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+  content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params) override;
+  void SidePanelAvailabilityChanged(bool should_close) override;
+  void OpenSidePanel() override;
+  void CloseSidePanel(
+      absl::optional<SideSearchCloseActionType> action = absl::nullopt);
+
+  // content::WebContentsObserver:
+  void DidFinishNavigation(
+      content::NavigationHandle* navigation_handle) override;
+
+  // SidePanelEntryObserver:
+  void OnEntryShown(SidePanelEntry* entry) override;
+  void OnEntryHidden(SidePanelEntry* entry) override;
+
+  // Create a WebView to host the side search WebContents.
+  std::unique_ptr<views::View> GetSideSearchView();
+
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+
+ private:
+  BrowserView* GetBrowserView() const;
+
+  // Clears the side contents for the currently active tab in this browser
+  // window and the view in the side search registry.
+  void ClearSideContentsCache();
+
+  // Updates side panel's availability from SideSearchTabContentsHelper.
+  void UpdateSidePanel();
+
+  void UpdateSidePanelRegistry(bool is_available);
+
+  // A handler to handle unhandled keyboard messages coming back from the
+  // renderer process.
+  views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
+
+  base::WeakPtrFactory<UnifiedSideSearchController> weak_factory_{this};
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_UNIFIED_SIDE_SEARCH_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/side_search/unified_side_search_helper.cc b/chrome/browser/ui/views/side_search/unified_side_search_helper.cc
new file mode 100644
index 0000000..76d1d8f
--- /dev/null
+++ b/chrome/browser/ui/views/side_search/unified_side_search_helper.cc
@@ -0,0 +1,11 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/side_search/unified_side_search_helper.h"
+
+#include "chrome/browser/ui/views/side_search/unified_side_search_controller.h"
+
+void CreateUnifiedSideSearchController(content::WebContents* web_contents) {
+  UnifiedSideSearchController::CreateForWebContents(web_contents);
+}
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 159eb51..3e88c25 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -90,11 +90,11 @@
 #include "ash/shell.h"
 #include "ash/wm/window_state.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/ui/views/frame/browser_view_layout.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller_test_api.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/screen_position_client.h"
@@ -3656,8 +3656,7 @@
  public:
   DetachToBrowserTabDragControllerTestWithTabbedSystemApp()
       : test_system_web_app_installation_(
-            web_app::TestSystemWebAppInstallation::
-                SetUpTabbedMultiWindowApp()) {}
+            ash::TestSystemWebAppInstallation::SetUpTabbedMultiWindowApp()) {}
 
   web_app::AppId InstallMockApp() {
     test_system_web_app_installation_->WaitForAppInstall();
@@ -3673,7 +3672,7 @@
   }
 
  private:
-  std::unique_ptr<web_app::TestSystemWebAppInstallation>
+  std::unique_ptr<ash::TestSystemWebAppInstallation>
       test_system_web_app_installation_;
 };
 
diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc
index 96a0fa8..1033888a 100644
--- a/chrome/browser/ui/views/toolbar/app_menu.cc
+++ b/chrome/browser/ui/views/toolbar/app_menu.cc
@@ -342,7 +342,8 @@
   METADATA_HEADER(FullscreenButton);
   explicit FullscreenButton(PressedCallback callback,
                             ButtonMenuItemModel* menu_model,
-                            int fullscreen_index)
+                            int fullscreen_index,
+                            bool is_in_fullscreen)
       : ImageButton(std::move(callback)) {
     // Since |fullscreen_button_| will reside in a menu, make it ALWAYS
     // focusable regardless of the platform.
@@ -352,9 +353,11 @@
     SetImageVerticalAlignment(ImageButton::ALIGN_MIDDLE);
     SetBackground(std::make_unique<InMenuButtonBackground>(
         InMenuButtonBackground::LEADING_BORDER));
-    SetTooltipText(l10n_util::GetStringUTF16(IDS_ACCNAME_FULLSCREEN));
+    const int accname_string_id =
+        is_in_fullscreen ? IDS_ACCNAME_EXIT_FULLSCREEN : IDS_ACCNAME_FULLSCREEN;
+    SetTooltipText(l10n_util::GetStringUTF16(accname_string_id));
     SetAccessibleName(GetAccessibleNameForAppMenuItem(
-        menu_model, fullscreen_index, IDS_ACCNAME_FULLSCREEN,
+        menu_model, fullscreen_index, accname_string_id,
 #if BUILDFLAG(IS_CHROMEOS_ASH)
         // ChromeOS uses a dedicated "fullscreen" media key for fullscreen
         // mode on most ChromeOS devices which cannot be specified in the
@@ -519,7 +522,8 @@
               menu->CancelAndEvaluate(menu_model, index);
             },
             menu, menu_model, fullscreen_index),
-        menu_model, fullscreen_index);
+        menu_model, fullscreen_index,
+        menu->browser_->window() && menu->browser_->window()->IsFullscreen());
 
     // all buttons on menu should must be a custom button in order for
     // the keyboard navigation to work.
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
index 9e0ba19..769865e 100644
--- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
+++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -215,7 +215,7 @@
               dialog_model));
       break;
     case Step::kNotStarted:
-    case Step::kLocationBarBubble:
+    case Step::kConditionalMediation:
     case Step::kClosed:
       sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
           std::make_unique<PlaceholderSheetModel>(dialog_model));
diff --git a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
index c945f77..3384a134 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
+++ b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "build/chromeos_buildflags.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/devtools/protocol/browser_handler.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/themes/custom_theme_supplier.h"
@@ -23,7 +24,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_manager.h"
@@ -93,7 +93,7 @@
  public:
   AppBrowserControllerBrowserTest()
       : test_system_web_app_installation_(
-            TestSystemWebAppInstallation::SetUpTabbedMultiWindowApp()) {
+            ash::TestSystemWebAppInstallation::SetUpTabbedMultiWindowApp()) {
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
     EnableSystemWebAppsInLacrosForTesting();
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -173,7 +173,7 @@
   GURL tabbed_app_url_;
 
  private:
-  std::unique_ptr<TestSystemWebAppInstallation>
+  std::unique_ptr<ash::TestSystemWebAppInstallation>
       test_system_web_app_installation_;
 };
 
@@ -361,7 +361,7 @@
  public:
   AppBrowserControllerChromeUntrustedBrowserTest()
       : test_system_web_app_installation_(
-            TestSystemWebAppInstallation::SetUpChromeUntrustedApp()) {
+            ash::TestSystemWebAppInstallation::SetUpChromeUntrustedApp()) {
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
     EnableSystemWebAppsInLacrosForTesting();
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -379,7 +379,7 @@
   }
 
  private:
-  std::unique_ptr<TestSystemWebAppInstallation>
+  std::unique_ptr<ash::TestSystemWebAppInstallation>
       test_system_web_app_installation_;
 };
 
diff --git a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
index f714ee14..d092e97 100644
--- a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
+++ b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
 #include "chrome/browser/ash/system_web_apps/test_support/system_web_app_browsertest_base.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
 #include "chrome/browser/ui/app_list/app_service/app_service_app_item.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -30,7 +31,6 @@
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/web_app_tab_helper.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/common/webui_url_constants.h"
@@ -82,7 +82,7 @@
     EnableSystemWebAppsInLacrosForTesting();
 #endif
     maybe_installation_ =
-        TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
+        ash::TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
   }
   ~SystemWebAppLinkCaptureBrowserTest() override = default;
 
@@ -485,8 +485,8 @@
  public:
   SystemWebAppManagerWindowSizeControlsTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
-    maybe_installation_ =
-        TestSystemWebAppInstallation::SetUpNonResizeableAndNonMaximizableApp();
+    maybe_installation_ = ash::TestSystemWebAppInstallation::
+        SetUpNonResizeableAndNonMaximizableApp();
   }
   ~SystemWebAppManagerWindowSizeControlsTest() override = default;
 };
@@ -527,7 +527,7 @@
     account_id1_ = login_mixin_.users()[0].account_id;
     account_id2_ = login_mixin_.users()[1].account_id;
     installation_ =
-        TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
+        ash::TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
   }
 
   ~SystemWebAppManagerMultiDesktopLaunchBrowserTest() override = default;
@@ -586,7 +586,7 @@
   }
 
  protected:
-  std::unique_ptr<TestSystemWebAppInstallation> installation_;
+  std::unique_ptr<ash::TestSystemWebAppInstallation> installation_;
   ash::LoginManagerMixin login_mixin_{&mixin_host_};
   AccountId account_id1_;
   AccountId account_id2_;
@@ -605,7 +605,7 @@
   WaitForSystemWebAppInstall(profile1);
 
   installation_ =
-      TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
+      ash::TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
   ash::UserAddingScreen::Get()->Start();
   AddUser(account_id2_);
   base::RunLoop().RunUntilIdle();
@@ -659,7 +659,7 @@
   WaitForSystemWebAppInstall(profile1);
 
   installation_ =
-      TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
+      ash::TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
   ash::UserAddingScreen::Get()->Start();
   AddUser(account_id2_);
   base::RunLoop().RunUntilIdle();
@@ -961,9 +961,8 @@
  public:
   SystemWebAppManagerCloseFromScriptsTest()
       : SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
-    maybe_installation_ =
-        TestSystemWebAppInstallation::SetupAppWithAllowScriptsToCloseWindows(
-            true);
+    maybe_installation_ = ash::TestSystemWebAppInstallation::
+        SetupAppWithAllowScriptsToCloseWindows(true);
   }
   ~SystemWebAppManagerCloseFromScriptsTest() override = default;
 };
@@ -993,9 +992,8 @@
  public:
   SystemWebAppManagerShouldNotCloseFromScriptsTest()
       : ash::SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
-    maybe_installation_ =
-        TestSystemWebAppInstallation::SetupAppWithAllowScriptsToCloseWindows(
-            false);
+    maybe_installation_ = ash::TestSystemWebAppInstallation::
+        SetupAppWithAllowScriptsToCloseWindows(false);
   }
   ~SystemWebAppManagerShouldNotCloseFromScriptsTest() override = default;
 };
@@ -1033,7 +1031,7 @@
   SystemWebAppNewWindowMenuItemTest()
       : ash::SystemWebAppManagerBrowserTest(/*install_mock=*/false) {
     maybe_installation_ =
-        TestSystemWebAppInstallation::SetUpAppWithNewWindowMenuItem();
+        ash::TestSystemWebAppInstallation::SetUpAppWithNewWindowMenuItem();
   }
   ~SystemWebAppNewWindowMenuItemTest() override = default;
 
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index eb6fe76..c891c24 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/browser_app_launcher.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/banners/app_banner_manager_desktop.h"
 #include "chrome/browser/browser_features.h"
 #include "chrome/browser/browser_process.h"
@@ -53,7 +54,6 @@
 #include "chrome/browser/ui/web_applications/web_app_menu_model.h"
 #include "chrome/browser/ui/web_applications/web_app_ui_utils.h"
 #include "chrome/browser/web_applications/external_install_options.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/test/web_app_test_observers.h"
 #include "chrome/browser/web_applications/test/web_app_test_utils.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
@@ -354,12 +354,12 @@
     switch (GetBackgroundColorChangeTestMode()) {
       case BackgroundColorChangeTestMode::kSWA:
         system_web_app_installation_ =
-            TestSystemWebAppInstallation::SetUpAppWithColors(
+            ash::TestSystemWebAppInstallation::SetUpAppWithColors(
                 /*theme_color=*/SK_ColorWHITE,
                 /*dark_mode_theme_color=*/SK_ColorBLACK,
                 /*background_color=*/SK_ColorWHITE,
                 /*dark_mode_background_color=*/SK_ColorBLACK);
-        static_cast<UnittestingSystemAppDelegate*>(
+        static_cast<ash::UnittestingSystemAppDelegate*>(
             system_web_app_installation_->GetDelegate())
             ->SetPreferManifestBackgroundColor(PreferManifestBackgroundColor());
         break;
@@ -399,7 +399,8 @@
   }
 
  private:
-  std::unique_ptr<TestSystemWebAppInstallation> system_web_app_installation_;
+  std::unique_ptr<ash::TestSystemWebAppInstallation>
+      system_web_app_installation_;
 };
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/ui/webui/certificate_viewer_webui.cc b/chrome/browser/ui/webui/certificate_viewer_webui.cc
index 518ce71..3c6f7a1 100644
--- a/chrome/browser/ui/webui/certificate_viewer_webui.cc
+++ b/chrome/browser/ui/webui/certificate_viewer_webui.cc
@@ -145,6 +145,14 @@
       std::move(cert_buffers), std::move(nicknames), web_contents, parent);
 }
 
+#if !(BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC))
+void ShowCertificateViewerForClientAuth(content::WebContents* web_contents,
+                                        gfx::NativeWindow parent,
+                                        net::X509Certificate* cert) {
+  ShowCertificateViewer(web_contents, parent, cert);
+}
+#endif
+
 ////////////////////////////////////////////////////////////////////////////////
 // CertificateViewerDialog
 
@@ -374,7 +382,8 @@
     return;
 
   gfx::NativeWindow window =
-      platform_util::GetTopLevel(dialog_->GetNativeWebContentsModalDialog());
+      platform_util::GetTopLevel(platform_util::GetViewForWindow(
+          dialog_->GetNativeWebContentsModalDialog()));
 
   std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> export_certs;
   for (const auto& cert : base::make_span(*certs_).subspan(cert_index)) {
diff --git a/chrome/browser/ui/webui/certificate_viewer_webui.h b/chrome/browser/ui/webui/certificate_viewer_webui.h
index 512c42b..6073870e 100644
--- a/chrome/browser/ui/webui/certificate_viewer_webui.h
+++ b/chrome/browser/ui/webui/certificate_viewer_webui.h
@@ -27,12 +27,10 @@
 
 class ConstrainedWebDialogDelegate;
 
-// TODO(https://crbug.com/953425): Update comment when this is used by other
-// platforms.
-// Dialog for displaying detailed certificate information. This is used in linux
-// and chromeos builds to display detailed information in a floating dialog when
-// the user clicks on "Certificate Information" from the lock icon of a web site
-// or "View" from the Certificate Manager.
+// Dialog for displaying detailed certificate information. This is used on
+// desktop builds to display detailed information in a floating dialog when the
+// user clicks on "Certificate Information" from the lock icon of a web site or
+// "View" from the Certificate Manager.
 class CertificateViewerDialog : public ui::WebDialogDelegate {
  public:
 #if BUILDFLAG(USE_NSS_CERTS)
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index bad1855f..dd5d8910 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -341,7 +341,7 @@
 #include "chrome/browser/ui/webui/connectors_internals/connectors_internals_ui.h"
 #endif
 
-#if BUILDFLAG(USE_NSS_CERTS) && defined(USE_AURA)
+#if BUILDFLAG(ENABLE_WEBUI_CERTIFICATE_VIEWER)
 #include "chrome/browser/ui/webui/certificate_viewer_ui.h"
 #endif
 
@@ -1169,10 +1169,10 @@
   if (url.host_piece() == chrome::kChromeUITabModalConfirmDialogHost)
     return &NewWebUI<ConstrainedWebDialogUI>;
 #endif
-#if BUILDFLAG(USE_NSS_CERTS) && defined(USE_AURA)
+#if BUILDFLAG(ENABLE_WEBUI_CERTIFICATE_VIEWER)
   if (url.host_piece() == chrome::kChromeUICertificateViewerHost)
     return &NewWebUI<CertificateViewerUI>;
-#endif  // USE_NSS_CERTS && USE_AURA
+#endif  // ENABLE_WEBUI_CERTIFICATE_VIEWER
 
   if (url.host_piece() == chrome::kChromeUIPolicyHost)
     return &NewWebUI<PolicyUI>;
diff --git a/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc b/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
index 6399714..b045632 100644
--- a/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
@@ -7,11 +7,11 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/values.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
-#include "chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_ui.h"
diff --git a/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.h b/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.h
index db22103..d7d6253 100644
--- a/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.h
+++ b/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.h
@@ -8,9 +8,9 @@
 #include <string>
 
 #include "base/memory/weak_ptr.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "content/public/browser/web_ui_message_handler.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/chrome/browser/ui/webui/chromeos/edu_account_login_handler_unittest.cc b/chrome/browser/ui/webui/chromeos/edu_account_login_handler_unittest.cc
index f39dfffb..9406454e 100644
--- a/chrome/browser/ui/webui/chromeos/edu_account_login_handler_unittest.cc
+++ b/chrome/browser/ui/webui/chromeos/edu_account_login_handler_unittest.cc
@@ -12,9 +12,9 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "chrome/browser/ash/net/network_portal_detector_test_impl.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/image_fetcher/core/mock_image_fetcher.h"
 #include "components/image_fetcher/core/request_metadata.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
index c0af736e..28b90fcd5 100644
--- a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
@@ -105,8 +105,6 @@
 void AppLaunchSplashScreenHandler::RegisterMessages() {
   AddCallback("configureNetwork",
               &AppLaunchSplashScreenHandler::HandleConfigureNetwork);
-  AddCallback("continueAppLaunch",
-              &AppLaunchSplashScreenHandler::HandleContinueAppLaunch);
 }
 
 void AppLaunchSplashScreenHandler::Hide() {
@@ -277,7 +275,7 @@
     LOG(WARNING) << "No delegate set to handle network configuration.";
 }
 
-void AppLaunchSplashScreenHandler::HandleContinueAppLaunch() {
+void AppLaunchSplashScreenHandler::ContinueAppLaunch() {
   if (!delegate_)
     return;
 
diff --git a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
index 86f68752..b9488b2 100644
--- a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
@@ -80,6 +80,9 @@
 
   // Returns true if the default network has Internet access.
   virtual bool IsNetworkReady() = 0;
+
+  // Continues app launch after error screen is shown.
+  virtual void ContinueAppLaunch() = 0;
 };
 
 // A class that handles the WebUI hooks for the app launch splash screen.
@@ -117,6 +120,7 @@
   void ShowNetworkConfigureUI() override;
   void ShowErrorMessage(KioskAppLaunchError::Error error) override;
   bool IsNetworkReady() override;
+  void ContinueAppLaunch() override;
 
   // NetworkStateInformer::NetworkStateInformerObserver implementation:
   void OnNetworkReady() override;
@@ -127,7 +131,6 @@
   void SetLaunchText(const std::string& text);
   int GetProgressMessageFromState(AppLaunchState state);
   void HandleConfigureNetwork();
-  void HandleContinueAppLaunch();
   void DoToggleNetworkConfig(bool visible);
 
   Delegate* delegate_ = nullptr;
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
index 82877a85f..b836786 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -237,6 +237,10 @@
   CallJS("cr.ui.Oobe.toggleSystemInfo");
 }
 
+void CoreOobeHandler::LaunchHelpApp(int help_topic_id) {
+  HandleLaunchHelpApp(help_topic_id);
+}
+
 void CoreOobeHandler::OnOobeConfigurationChanged() {
   base::Value configuration(base::Value::Type::DICTIONARY);
   configuration::FilterConfiguration(
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
index 017477e..b937155 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
@@ -39,6 +39,7 @@
   virtual void UpdateClientAreaSize(const gfx::Size& size) = 0;
   virtual void ToggleSystemInfo() = 0;
   virtual void ForwardCancel() = 0;
+  virtual void LaunchHelpApp(int help_topic_id) = 0;
 };
 
 // The core handler for Javascript messages related to the "oobe" view.
@@ -91,6 +92,7 @@
   void ToggleSystemInfo() override;
   // Forwards the cancel accelerator value to the shown screen.
   void ForwardCancel() override;
+  void LaunchHelpApp(int help_topic_id) override;
 
   // ash::TabletModeObserver:
   void OnTabletModeStarted() override;
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
index 6d8d69063..437be2715 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
@@ -17,16 +17,9 @@
 
 namespace chromeos {
 
-constexpr StaticOobeScreenId ErrorScreenView::kScreenId;
+ErrorScreenHandler::ErrorScreenHandler() : BaseScreenHandler(kScreenId) {}
 
-ErrorScreenHandler::ErrorScreenHandler() : BaseScreenHandler(kScreenId) {
-  set_user_acted_method_path_deprecated("login.ErrorMessageScreen.userActed");
-}
-
-ErrorScreenHandler::~ErrorScreenHandler() {
-  if (screen_)
-    screen_->OnViewDestroyed(this);
-}
+ErrorScreenHandler::~ErrorScreenHandler() = default;
 
 void ErrorScreenHandler::Show() {
   if (!IsJavascriptAllowed()) {
@@ -67,36 +60,31 @@
 
 void ErrorScreenHandler::SetErrorStateCode(
     NetworkError::ErrorState error_state) {
-  CallJS("login.ErrorMessageScreen.setErrorState",
-         static_cast<int>(error_state));
+  CallExternalAPI("setErrorState", static_cast<int>(error_state));
 }
 
 void ErrorScreenHandler::SetErrorStateNetwork(const std::string& network_name) {
-  CallJS("login.ErrorMessageScreen.setErrorStateNetwork", network_name);
+  CallExternalAPI("setErrorStateNetwork", network_name);
 }
 
 void ErrorScreenHandler::SetGuestSigninAllowed(bool value) {
-  CallJS("login.ErrorMessageScreen.allowGuestSignin", value);
+  CallExternalAPI("allowGuestSignin", value);
 }
 
 void ErrorScreenHandler::SetOfflineSigninAllowed(bool value) {
-  CallJS("login.ErrorMessageScreen.allowOfflineLogin", value);
+  CallExternalAPI("allowOfflineLogin", value);
 }
 
 void ErrorScreenHandler::SetShowConnectingIndicator(bool value) {
-  CallJS("login.ErrorMessageScreen.showConnectingIndicator", value);
+  CallExternalAPI("showConnectingIndicator", value);
 }
 
 void ErrorScreenHandler::SetIsPersistentError(bool is_persistent) {
-  CallJS("login.ErrorMessageScreen.setIsPersistentError", is_persistent);
+  CallExternalAPI("setIsPersistentError", is_persistent);
 }
 
 void ErrorScreenHandler::SetUIState(NetworkError::UIState ui_state) {
-  CallJS("login.ErrorMessageScreen.setUIState", static_cast<int>(ui_state));
-}
-
-void ErrorScreenHandler::OnReloadGaiaClicked() {
-  CallJS("login.GaiaSigninScreen.doReload");
+  CallExternalAPI("setUIState", static_cast<int>(ui_state));
 }
 
 void ErrorScreenHandler::DeclareLocalizedValues(
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h
index b5bb05bb..83d5743 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ERROR_SCREEN_HANDLER_H_
 #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ERROR_SCREEN_HANDLER_H_
 
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/login/screens/network_error.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 
@@ -16,12 +17,12 @@
 
 // Interface for dependency injection between ErrorScreen and its actual
 // representation. Owned by ErrorScreen.
-class ErrorScreenView {
+class ErrorScreenView : public base::SupportsWeakPtr<ErrorScreenView> {
  public:
-  constexpr static StaticOobeScreenId kScreenId{"error-message",
-                                                "ErrorMessageScreen"};
+  inline constexpr static StaticOobeScreenId kScreenId{"error-message",
+                                                       "ErrorMessageScreen"};
 
-  virtual ~ErrorScreenView() {}
+  virtual ~ErrorScreenView() = default;
 
   // Shows the contents of the screen.
   virtual void Show() = 0;
@@ -58,9 +59,6 @@
 
   // Sets current UI state of the screen.
   virtual void SetUIState(NetworkError::UIState ui_state) = 0;
-
-  // Reloads gaia.
-  virtual void OnReloadGaiaClicked() = 0;
 };
 
 // A class that handles the WebUI hooks in error screen.
@@ -89,7 +87,6 @@
   void SetShowConnectingIndicator(bool value) override;
   void SetIsPersistentError(bool is_persistent) override;
   void SetUIState(NetworkError::UIState ui_state) override;
-  void OnReloadGaiaClicked() override;
 
   // BaseScreenHandler:
   void DeclareLocalizedValues(
diff --git a/chrome/browser/ui/webui/chromeos/login/fake_app_launch_splash_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/fake_app_launch_splash_screen_handler.h
index 8a54b15..ca13f55 100644
--- a/chrome/browser/ui/webui/chromeos/login/fake_app_launch_splash_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/fake_app_launch_splash_screen_handler.h
@@ -20,6 +20,7 @@
   void ShowNetworkConfigureUI() override {}
   void ShowErrorMessage(KioskAppLaunchError::Error error) override;
   bool IsNetworkReady() override;
+  void ContinueAppLaunch() override {}
 
   KioskAppLaunchError::Error GetErrorMessageType() const;
   void SetNetworkReady(bool ready);
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index 36a88315..b201623 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -408,6 +408,8 @@
     const bool* collect_stats_consent) {
   base::Value params(base::Value::Type::DICTIONARY);
 
+  // TODO(https://crbug.com/1338102): Looks like `forceReload` isn't used
+  //                                  anywhere further. Remove?
   params.SetBoolKey("forceReload", context.force_reload);
   params.SetStringKey("gaiaId", context.gaia_id);
   params.SetBoolKey("readOnlyEmail", true);
@@ -717,6 +719,13 @@
   // used during the current sign-in attempt.
   extension_provided_client_cert_usage_observer_ =
       std::make_unique<LoginClientCertUsageObserver>();
+
+  // Clear old storage partitions after a new sign-in page is loaded. All
+  // reference to the old storage partitions should be cleared.
+  login::SigninPartitionManager* signin_partition_manager =
+      login::SigninPartitionManager::Factory::GetForBrowserContext(
+          Profile::FromWebUI(web_ui()));
+  signin_partition_manager->DisposeOldStoragePartitions();
 }
 
 void GaiaScreenHandler::HandleWebviewLoadAborted(int error_code) {
@@ -1335,6 +1344,10 @@
   CallExternalAPI("showAllowlistCheckFailedError", std::move(params));
 }
 
+void GaiaScreenHandler::ReloadGaiaAuthenticator() {
+  CallExternalAPI("doReload");
+}
+
 void GaiaScreenHandler::LoadAuthExtension(bool force) {
   VLOG(1) << "LoadAuthExtension, force: " << force;
   if (auth_extension_being_loaded_) {
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
index 137eed92..4139525f 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -85,6 +85,8 @@
   virtual void SetGaiaPath(GaiaPath gaia_path) = 0;
   // Show error UI at the end of GAIA flow when user is not allowlisted.
   virtual void ShowAllowlistCheckFailedError() = 0;
+  // Reloads authenticator.
+  virtual void ReloadGaiaAuthenticator() = 0;
 
   // Show sign-in screen for the given credentials. `services` is a list of
   // services returned by userInfo call as JSON array. Should be an empty array
@@ -135,6 +137,7 @@
   void Hide() override;
   void SetGaiaPath(GaiaPath gaia_path) override;
   void ShowAllowlistCheckFailedError() override;
+  void ReloadGaiaAuthenticator() override;
 
   void ShowSigninScreenForTest(const std::string& username,
                                const std::string& password,
diff --git a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc
index e429b99..28f0e8fa 100644
--- a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc
@@ -24,6 +24,7 @@
 constexpr char kOptInVisibility[] = "optInVisibility";
 constexpr char kOptInDefaultState[] = "optInDefaultState";
 constexpr char kLegalFooterVisibility[] = "legalFooterVisibility";
+constexpr char kCloudGamingDevice[] = "cloudGamingDevice";
 
 void RecordShowShelfNavigationButtonsValueChange(bool enabled) {
   base::UmaHistogramBoolean(
@@ -47,6 +48,15 @@
     ::login::LocalizedValuesBuilder* builder) {
   builder->Add("marketingOptInScreenTitle",
                IDS_LOGIN_MARKETING_OPT_IN_SCREEN_TITLE);
+  builder->Add(
+      "marketingOptInScreenGameDeviceTitle",
+      IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_1);
+  builder->Add(
+      "marketingOptInScreenGameDeviceTitle2",
+      IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_TITLE_2);
+  builder->Add(
+      "marketingOptInScreenGameDeviceSubtitle",
+      IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SUBTITLE);
   builder->AddF("marketingOptInScreenSubtitle",
                 IDS_LOGIN_MARKETING_OPT_IN_SCREEN_SUBTITLE,
                 ui::GetChromeOSDeviceName());
@@ -56,6 +66,10 @@
   builder->Add(
       "marketingOptInGetChromebookUpdates",
       IDS_LOGIN_MARKETING_OPT_IN_SCREEN_GET_CHROMEBOOK_UPDATES_SIGN_ME_UP);
+  builder->AddF(
+      "marketingOptInGameDeviceUpdates",
+      IDS_LOGIN_MARKETING_OPT_IN_SCREEN_WITH_CLOUDGAMINGDEVICE_SIGN_ME_UP,
+      ui::GetChromeOSDeviceName());
   builder->Add("marketingOptInScreenAllSet", IDS_LOGIN_GET_STARTED);
   builder->Add("marketingOptInScreenUnsubscribeShort",
                IDS_LOGIN_MARKETING_OPT_IN_SCREEN_UNSUBSCRIBE_SHORT);
@@ -80,11 +94,13 @@
 
 void MarketingOptInScreenHandler::Show(bool opt_in_visible,
                                        bool opt_in_default_state,
-                                       bool legal_footer_visible) {
+                                       bool legal_footer_visible,
+                                       bool cloud_gaming_enabled) {
   base::Value::Dict data;
   data.Set(kOptInVisibility, opt_in_visible);
   data.Set(kOptInDefaultState, opt_in_default_state);
   data.Set(kLegalFooterVisibility, legal_footer_visible);
+  data.Set(kCloudGamingDevice, cloud_gaming_enabled);
 
   ShowInWebUI(std::move(data));
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
index 52f38fa..12d477c3 100644
--- a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
@@ -29,7 +29,8 @@
   // Shows the contents of the screen.
   virtual void Show(bool opt_in_visible,
                     bool opt_in_default_state,
-                    bool legal_footer_visible) = 0;
+                    bool legal_footer_visible,
+                    bool cloud_gaming_enabled) = 0;
 
   // Hides the contents of the screen.
   virtual void Hide() = 0;
@@ -64,7 +65,8 @@
   void Bind(ash::MarketingOptInScreen* screen) override;
   void Show(bool opt_in_visible,
             bool opt_in_default_state,
-            bool legal_footer_visible) override;
+            bool legal_footer_visible,
+            bool cloud_gaming_enabled) override;
   void Hide() override;
   void UpdateA11ySettingsButtonVisibility(bool shown) override;
   void UpdateA11yShelfNavigationButtonToggle(bool enabled) override;
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index b816d48..5a8ee3f 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -458,7 +458,8 @@
 
   AddScreenHandler(std::make_unique<ErrorScreenHandler>());
 
-  error_screen_ = std::make_unique<ErrorScreen>(GetView<ErrorScreenHandler>());
+  error_screen_ =
+      std::make_unique<ErrorScreen>(GetView<ErrorScreenHandler>()->AsWeakPtr());
   ErrorScreen* error_screen = error_screen_.get();
 
   AddScreenHandler(std::make_unique<EnrollmentScreenHandler>(
diff --git a/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.cc b/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.cc
index 3cf2769..e169b47 100644
--- a/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.cc
@@ -51,7 +51,7 @@
   message_center::RichNotificationData optional_fields;
 
   // Delegate does nothing.
-  scoped_refptr<message_center::NotificationDelegate> delegate =
+  auto delegate =
       base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
           base::BindRepeating([](absl::optional<int> button_index) {}));
 
@@ -65,7 +65,7 @@
           message_center::NOTIFICATION_TYPE_SIMPLE, notification_id, title,
           message, display_source, origin_url, notifier_id, optional_fields,
           delegate, kTerminalSshIcon,
-          message_center::SystemNotificationWarningLevel::WARNING);
+          message_center::SystemNotificationWarningLevel::NORMAL);
 
   message_center::MessageCenter::Get()->AddNotification(
       std::move(notification));
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
index 3e8dda3..4b88a6e7 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
@@ -13,10 +13,10 @@
 #include "base/test/mock_callback.h"
 #include "chrome/browser/ash/login/users/mock_user_manager.h"
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/dbus/update_engine/fake_update_engine_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ui/webui/help/version_updater_mac.h b/chrome/browser/ui/webui/help/version_updater_mac.h
index 83ec14e..1168a05 100644
--- a/chrome/browser/ui/webui/help/version_updater_mac.h
+++ b/chrome/browser/ui/webui/help/version_updater_mac.h
@@ -16,9 +16,9 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/updater/update_service.h"  // nogncheck
+#include "chrome/updater/update_service.h"
+#include "chrome/updater/updater_scope.h"
 
-class BrowserUpdaterClient;
 class BrowserUpdaterHelperClientMac;
 #endif  // BUILDFLAG(ENABLE_CHROMIUM_UPDATER)
 
@@ -58,10 +58,12 @@
   void UpdateStatusFromChromiumUpdater(
       VersionUpdater::StatusCallback status_callback,
       VersionUpdater::PromoteCallback promote_callback,
+      updater::UpdaterScope scope,
       updater::UpdateService::UpdateState update_state);
 
   void UpdatePromotionStatusFromChromiumUpdater(
       VersionUpdater::PromoteCallback promote_callback,
+      updater::UpdaterScope scope,
       bool enable_promote_button,
       const std::string& version);
 #endif  // BUILDFLAG(ENABLE_CHROMIUM_UPDATER)
@@ -79,9 +81,6 @@
   base::scoped_nsobject<KeystoneObserver> keystone_observer_;
 
 #if BUILDFLAG(ENABLE_CHROMIUM_UPDATER)
-  // Instance of the BrowserUpdaterClient used to update the browser with the
-  // new updater.
-  scoped_refptr<BrowserUpdaterClient> update_client_;
   scoped_refptr<BrowserUpdaterHelperClientMac> update_helper_client_;
   base::WeakPtrFactory<VersionUpdaterMac> weak_factory_{this};
 #endif  // BUILDFLAG(ENABLE_CHROMIUM_UPDATER)
diff --git a/chrome/browser/ui/webui/help/version_updater_mac.mm b/chrome/browser/ui/webui/help/version_updater_mac.mm
index 0078b54..23de12c 100644
--- a/chrome/browser/ui/webui/help/version_updater_mac.mm
+++ b/chrome/browser/ui/webui/help/version_updater_mac.mm
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 #include "base/mac/foundation_util.h"
@@ -107,14 +108,19 @@
 void VersionUpdaterMac::CheckForUpdate(StatusCallback status_callback,
                                        PromoteCallback promote_callback) {
 #if BUILDFLAG(ENABLE_CHROMIUM_UPDATER)
-  if (!update_client_)
-    update_client_ = BrowserUpdaterClient::Create();
-
-  update_client_->CheckForUpdate(base::BindRepeating(
-      &VersionUpdaterMac::UpdateStatusFromChromiumUpdater,
-      weak_factory_.GetWeakPtr(), std::move(status_callback),
-      std::move(promote_callback)));
-  return;
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::MayBlock()}, base::BindOnce(&GetUpdaterScope),
+      base::BindOnce(
+          [](base::RepeatingCallback<void(updater::UpdaterScope,
+                                          updater::UpdateService::UpdateState)>
+                 status_callback,
+             updater::UpdaterScope scope) {
+            BrowserUpdaterClient::Create(scope)->CheckForUpdate(
+                base::BindRepeating(status_callback, scope));
+          },
+          base::BindRepeating(
+              &VersionUpdaterMac::UpdateStatusFromChromiumUpdater,
+              weak_factory_.GetWeakPtr(), status_callback, promote_callback)));
 #else
   status_callback_ = std::move(status_callback);
   promote_callback_ = std::move(promote_callback);
@@ -302,11 +308,11 @@
     }
   }
 
-  if (!status_callback_.is_null())
+  if (status_callback_)
     status_callback_.Run(status, 0, false, false, std::string(), 0, message);
 
   PromotionState promotion_state;
-  if (!promote_callback_.is_null()) {
+  if (promote_callback_) {
     KeystoneGlue* keystone_glue = [KeystoneGlue defaultKeystoneGlue];
     if (keystone_glue && [keystone_glue isAutoupdateEnabledForAllUsers]) {
       promotion_state = PROMOTED;
@@ -352,6 +358,7 @@
 void VersionUpdaterMac::UpdateStatusFromChromiumUpdater(
     VersionUpdater::StatusCallback status_callback,
     VersionUpdater::PromoteCallback promote_callback,
+    updater::UpdaterScope scope,
     updater::UpdateService::UpdateState update_state) {
   VersionUpdater::Status status = VersionUpdater::Status::CHECKING;
   int progress = 0;
@@ -405,39 +412,35 @@
   // update_clent with system scope and attempt to get version. If the version
   // is empty, then the updater can be assumed to not be installed. If the
   // version returns a value, then the updater is installed.
-  if (!promote_callback.is_null() && ShouldPromoteUpdater()) {
-    update_client_->ResetConnection(updater::UpdaterScope::kSystem);
-    update_client_->GetUpdaterVersion(base::BindOnce(
-        &VersionUpdaterMac::UpdatePromotionStatusFromChromiumUpdater,
-        weak_factory_.GetWeakPtr(), std::move(promote_callback),
-        enable_promote_button));
+  if (promote_callback) {
+    base::ThreadPool::PostTaskAndReplyWithResult(
+        FROM_HERE, {base::MayBlock()}, base::BindOnce(&ShouldPromoteUpdater),
+        base::BindOnce(
+            [](base::OnceCallback<void(const std::string&)> promotion,
+               bool should_promote) {
+              if (should_promote) {
+                BrowserUpdaterClient::Create(updater::UpdaterScope::kSystem)
+                    ->GetUpdaterVersion(std::move(promotion));
+              }
+            },
+            base::BindOnce(
+                &VersionUpdaterMac::UpdatePromotionStatusFromChromiumUpdater,
+                weak_factory_.GetWeakPtr(), promote_callback, scope,
+                enable_promote_button)));
   }
 }
 
 void VersionUpdaterMac::UpdatePromotionStatusFromChromiumUpdater(
     VersionUpdater::PromoteCallback promote_callback,
+    updater::UpdaterScope scope,
     bool enable_promote_button,
     const std::string& version) {
-  if (promote_callback.is_null())
-    return;
-
-  VersionUpdater::PromotionState promotion_state =
-      VersionUpdater::PROMOTE_HIDDEN;
-  // If the version is not empty and the current path is owned by root (which
-  // is reflected in ShouldUseSystemLevelUpdater()), then the updater had
-  // already been promoted.
-  if (!version.empty() && ShouldUseSystemLevelUpdater()) {
-    promotion_state = VersionUpdater::PROMOTED;
-    update_client_->ResetConnection(updater::UpdaterScope::kSystem);
-  } else {
-    promotion_state = enable_promote_button ? VersionUpdater::PROMOTE_ENABLED
-                                            : VersionUpdater::PROMOTE_DISABLED;
-    if (!enable_promote_button) {
-      update_client_->ResetConnection(updater::UpdaterScope::kUser);
-    }
-  }
-
-  promote_callback.Run(promotion_state);
+  promote_callback.Run(
+      !version.empty() && scope == updater::UpdaterScope::kSystem
+          ? VersionUpdater::PROMOTED  // Successfully communicated with the
+                                      // system updater.
+          : (enable_promote_button ? VersionUpdater::PROMOTE_ENABLED
+                                   : VersionUpdater::PROMOTE_DISABLED));
 }
 
 #endif  // BUILDFLAG(ENABLE_CHROMIUM_UPDATER)
diff --git a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
index 3e76360..1927610 100644
--- a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
@@ -63,12 +63,12 @@
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/proxy/proxy_config_handler.h"
 #include "chromeos/ash/components/network/proxy/ui_proxy_config_service.h"
 #include "chromeos/dbus/dbus_thread_manager.h"  // nogncheck
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_metadata_store.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/system/fake_statistics_provider.h"
diff --git a/chrome/browser/ui/webui/profile_internals/profile_internals_handler.cc b/chrome/browser/ui/webui/profile_internals/profile_internals_handler.cc
index fd3915a..06198630 100644
--- a/chrome/browser/ui/webui/profile_internals/profile_internals_handler.cc
+++ b/chrome/browser/ui/webui/profile_internals/profile_internals_handler.cc
@@ -15,8 +15,10 @@
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/signin/profile_colors_util.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "content/public/browser/web_ui.h"
+#include "skia/ext/skia_utils_base.h"
 
 namespace {
 
@@ -53,6 +55,14 @@
   profile_entry.SetBoolKey("userAcceptedAccountManagement",
                            entry->UserAcceptedAccountManagement());
 
+  SkColor highlight_color =
+      entry->GetProfileThemeColors().profile_highlight_color;
+  profile_entry.SetStringKey("backgroundColor",
+                             skia::SkColorToHexString(highlight_color));
+  profile_entry.SetStringKey(
+      "foregroundColor",
+      skia::SkColorToHexString(GetProfileForegroundTextColor(highlight_color)));
+
   base::Value keep_alives(base::Value::Type::LIST);
   std::map<ProfileKeepAliveOrigin, int> keep_alives_map =
       g_browser_process->profile_manager()->GetKeepAlivesByPath(
diff --git a/chrome/browser/ui/webui/realbox/OWNERS b/chrome/browser/ui/webui/realbox/OWNERS
index 222931b0..fcdf4f33 100644
--- a/chrome/browser/ui/webui/realbox/OWNERS
+++ b/chrome/browser/ui/webui/realbox/OWNERS
@@ -1,5 +1,5 @@
 mahmadi@chromium.org
-tommycli@chromium.org
+mfacey@chromium.org
 file://components/omnibox/OWNERS
 
 per-file *.mojom=set noparent
diff --git a/chrome/browser/ui/webui/settings/ash/calculator/size_calculator.cc b/chrome/browser/ui/webui/settings/ash/calculator/size_calculator.cc
index ad7f2c8..e12b686 100644
--- a/chrome/browser/ui/webui/settings/ash/calculator/size_calculator.cc
+++ b/chrome/browser/ui/webui/settings/ash/calculator/size_calculator.cc
@@ -21,7 +21,7 @@
 #include "chrome/browser/browsing_data/browsing_data_file_system_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/ash/components/dbus/spaced/spaced_client.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "components/browsing_data/content/cache_storage_helper.h"
 #include "components/browsing_data/content/conditional_cache_counting_helper.h"
 #include "components/browsing_data/content/cookie_helper.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc
index 232e12a..60bd074 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc
@@ -68,27 +68,35 @@
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kLargeCursor}},
+       {.setting = mojom::Setting::kLargeCursor},
+       {IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT1,
+        IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT2,
+        IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT3,
+        IDS_OS_SETTINGS_TAG_A11Y_LARGE_CURSOR_ALT4, SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y,
        mojom::kAccessibilitySectionPath,
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kHigh,
        mojom::SearchResultType::kSection,
        {.section = mojom::Section::kAccessibility},
-       {IDS_OS_SETTINGS_TAG_A11Y_ALT1, SearchConcept::kAltTagEnd}},
+       {IDS_OS_SETTINGS_TAG_A11Y_ALT1, IDS_OS_SETTINGS_TAG_A11Y_ALT2,
+        SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_DOCKED_MAGNIFIER,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kDockedMagnifier}},
+       {.setting = mojom::Setting::kDockedMagnifier},
+       {IDS_OS_SETTINGS_TAG_A11Y_DOCKED_MAGNIFIER_ALT1,
+        SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11y_CHROMEVOX,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
        {.setting = mojom::Setting::kChromeVox},
-       {IDS_OS_SETTINGS_TAG_A11y_CHROMEVOX_ALT1, SearchConcept::kAltTagEnd}},
+       {IDS_OS_SETTINGS_TAG_A11y_CHROMEVOX_ALT1,
+        IDS_OS_SETTINGS_TAG_A11y_CHROMEVOX_ALT2, SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_MONO_AUDIO,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
@@ -103,7 +111,9 @@
        mojom::SearchResultType::kSubpage,
        {.subpage = mojom::Subpage::kTextToSpeech},
        {IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT1,
-        SearchConcept::kAltTagEnd}},
+        IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT2,
+        IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT3,
+        IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT4}},
       {IDS_OS_SETTINGS_TAG_A11Y_CAPTIONS,
        mojom::kCaptionsSubpagePath,
        mojom::SearchResultIcon::kA11y,
@@ -115,7 +125,11 @@
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kHighlightCursorWhileMoving}},
+       {.setting = mojom::Setting::kHighlightCursorWhileMoving},
+       {IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT1,
+        IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT2,
+        IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_CURSOR_ALT3,
+        SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_MANAGE,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
@@ -134,14 +148,19 @@
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kHighlightTextCaret}},
+       {.setting = mojom::Setting::kHighlightTextCaret},
+       {IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_TEXT_CARET_ALT1,
+        SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_DICTATION,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
        {.setting = mojom::Setting::kDictation},
-       {IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT1, SearchConcept::kAltTagEnd}},
+       {IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT1,
+        IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT2,
+        IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT3,
+        IDS_OS_SETTINGS_TAG_A11Y_DICTATION_ALT4, SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_HIGH_CONTRAST,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
@@ -155,19 +174,25 @@
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kHighlightKeyboardFocus}},
+       {.setting = mojom::Setting::kHighlightKeyboardFocus},
+       {IDS_OS_SETTINGS_TAG_A11Y_HIGHLIGHT_KEYBOARD_FOCUS_ALT1,
+        SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_STARTUP_SOUND,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kStartupSound}},
+       {.setting = mojom::Setting::kStartupSound},
+       {IDS_OS_SETTINGS_TAG_A11Y_STARTUP_SOUND_ALT1,
+        SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_AUTOMATICALLY_CLICK,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kAutoClickWhenCursorStops}},
+       {.setting = mojom::Setting::kAutoClickWhenCursorStops},
+       {IDS_OS_SETTINGS_TAG_A11Y_AUTOMATICALLY_CLICK_ALT1,
+        SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_SELECT_TO_SPEAK,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
@@ -185,7 +210,8 @@
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kTextToSpeechRate}},
+       {.setting = mojom::Setting::kTextToSpeechRate},
+       {IDS_OS_SETTINGS_TAG_A11Y_SPEECH_RATE_ALT1, SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_SPEECH_VOLUME,
        mojom::kTextToSpeechSubpagePath,
        mojom::SearchResultIcon::kA11y,
@@ -197,7 +223,10 @@
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kFullscreenMagnifier}},
+       {.setting = mojom::Setting::kFullscreenMagnifier},
+       {IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT1,
+        IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_ALT2,
+        SearchConcept::kAltTagEnd}},
       {IDS_OS_SETTINGS_TAG_A11Y_ENABLE_SWITCH_ACCESS,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
@@ -209,7 +238,9 @@
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kEnableCursorColor}},
+       {.setting = mojom::Setting::kEnableCursorColor},
+       {IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT1,
+        IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR_ALT2, SearchConcept::kAltTagEnd}},
   });
   return *tags;
 }
@@ -306,7 +337,8 @@
        mojom::SearchResultIcon::kA11y,
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kLiveCaption}},
+       {.setting = mojom::Setting::kLiveCaption},
+       {IDS_OS_SETTINGS_TAG_A11Y_LIVE_CAPTION_ALT1, SearchConcept::kAltTagEnd}},
   });
   return *tags;
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc b/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc
index 887709e..8a4e338 100644
--- a/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc
@@ -318,6 +318,7 @@
       {"enableFastPairSubtitle", IDS_BLUETOOTH_ENABLE_FAST_PAIR_SUBTITLE},
       {"savedDevicesLabel", IDS_BLUETOOTH_SAVED_DEVICES_LABEL},
       {"savedDevicesSubtitle", IDS_BLUETOOTH_SAVED_DEVICES_SUBTITLE},
+      {"savedDevicesPageName", IDS_SETTINGS_BLUETOOTH_SAVED_DEVICES},
       {"bluetoothPrimaryUserControlled",
        IDS_SETTINGS_BLUETOOTH_PRIMARY_USER_CONTROLLED},
       {"bluetoothDeviceWithConnectionStatus",
@@ -413,6 +414,7 @@
       mojom::Setting::kBluetoothConnectToDevice,
       mojom::Setting::kBluetoothDisconnectFromDevice,
   };
+
   RegisterNestedSettingBulk(mojom::Subpage::kBluetoothDevices,
                             kBluetoothDevicesSettings, generator);
   generator->RegisterTopLevelAltSetting(mojom::Setting::kBluetoothOnOff);
@@ -426,6 +428,13 @@
                                 ? mojom::Subpage::kBluetoothDeviceDetail
                                 : mojom::Subpage::kBluetoothDevices,
                             kBluetoothDevicesSettingsLegacy, generator);
+
+  generator->RegisterNestedSubpage(IDS_SETTINGS_BLUETOOTH_SAVED_DEVICES,
+                                   mojom::Subpage::kBluetoothSavedDevices,
+                                   mojom::Subpage::kBluetoothDevices,
+                                   mojom::SearchResultIcon::kBluetooth,
+                                   mojom::SearchResultDefaultRank::kMedium,
+                                   mojom::kBluetoothSavedDevicesSubpagePath);
 }
 
 void BluetoothSection::AdapterPresentChanged(device::BluetoothAdapter* adapter,
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
index 6c64f40..990508f 100644
--- a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
+++ b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
@@ -47,6 +47,7 @@
   // Bluetooth section.
   kBluetoothDevices = 100,
   kBluetoothDeviceDetail = 101,
+  kBluetoothSavedDevices = 102,
 
   // MultiDevice section.
   kMultiDeviceFeatures = 200,
@@ -170,6 +171,7 @@
 const string kBluetoothSectionPath = "bluetooth";
 const string kBluetoothDevicesSubpagePath = "bluetoothDevices";
 const string kBluetoothDeviceDetailSubpagePath = "bluetoothDeviceDetail";
+const string kBluetoothSavedDevicesSubpagePath = "bluetoothSavedDevices";
 
 // MultiDevice section.
 const string kMultiDeviceSectionPath = "multidevice";
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_section.h b/chrome/browser/ui/webui/settings/chromeos/internet_section.h
index 3805f88..62d17c2 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_section.h
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_section.h
@@ -10,7 +10,7 @@
 
 #include "base/values.h"
 #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -26,9 +26,8 @@
 
 class SearchTagRegistry;
 
-class InternetSection
-    : public OsSettingsSection,
-      public network_config::mojom::CrosNetworkConfigObserver {
+class InternetSection : public OsSettingsSection,
+                        public network_config::CrosNetworkConfigObserver {
  public:
   InternetSection(Profile* profile, SearchTagRegistry* search_tag_registry);
   ~InternetSection() override;
@@ -48,18 +47,11 @@
       OsSettingsIdentifier id,
       const std::string& url_to_modify) const override;
 
-  // network_config::mojom::CrosNetworkConfigObserver:
+  // network_config::CrosNetworkConfigObserver:
   void OnActiveNetworksChanged(
       std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks)
       override;
   void OnDeviceStateListChanged() override;
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
-      override {}
-  void OnNetworkStateListChanged() override {}
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
   void FetchDeviceList();
   void OnGlobalPolicy(network_config::mojom::GlobalPolicyPtr global_policy);
diff --git a/chrome/browser/ui/webui/settings/chromeos/languages_section.cc b/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
index 537591d2..dd7509ec 100644
--- a/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
@@ -103,11 +103,6 @@
   return *tags;
 }
 
-bool IsLanguageSettingsV2Update2Enabled() {
-  return base::FeatureList::IsEnabled(
-      ::chromeos::features::kLanguageSettingsUpdate2);
-}
-
 const std::vector<SearchConcept>& GetSmartInputsSearchConcepts() {
   static const base::NoDestructor<std::vector<SearchConcept>> tags({
       {IDS_OS_SETTINGS_TAG_LANGUAGES_SUGGESTIONS,
@@ -447,8 +442,7 @@
   AddLanguagesPageStringsV2(html_source);
   AddInputPageStringsV2(html_source);
 
-  html_source->AddBoolean("enableLanguageSettingsV2Update2",
-                          IsLanguageSettingsV2Update2Enabled());
+  html_source->AddBoolean("enableLanguageSettingsV2Update2", true);
   html_source->AddBoolean("onDeviceGrammarCheckEnabled",
                           base::FeatureList::IsEnabled(
                               ::chromeos::features::kOnDeviceGrammarCheck));
diff --git a/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc b/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc
index 014a441..1ea95c4 100644
--- a/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc
@@ -259,8 +259,6 @@
       l10n_util::GetStringFUTF16(
           IDS_OS_SETTINGS_AMBIENT_MODE_ALBUMS_SUBPAGE_GOOGLE_PHOTOS_NO_ALBUM,
           base::UTF8ToUTF16(GetGooglePhotosURL().spec())));
-  html_source->AddBoolean("isPersonalizationHubEnabled",
-                          ash::features::IsPersonalizationHubEnabled());
 }
 
 void PersonalizationSection::AddHandlers(content::WebUI* web_ui) {
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index fb7235c..6c2ec13 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -69,7 +69,6 @@
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT) || BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
-#include "components/signin/public/base/signin_switches.h"
 #endif
 
 using content::WebContents;
@@ -441,9 +440,7 @@
   populate_accounts_list =
       AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_);
 #elif BUILDFLAG(IS_CHROMEOS_LACROS)
-  populate_accounts_list =
-      base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles) &&
-      !profile_->IsMainProfile();
+  populate_accounts_list = !profile_->IsMainProfile();
 #endif
 
   if (populate_accounts_list) {
@@ -772,15 +769,9 @@
           sync_service->StopAndClear();
 // ChromeOS ash doesn't support signing out.
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-          bool should_revoke_sync_consent =
-              !sync_service->GetUserSettings()->IsFirstSetupComplete();
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-          should_revoke_sync_consent &=
-              base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles);
-#endif
           // Revoke sync consent on desktop Chrome if they click cancel during
           // initial setup or close sync setup without confirming sync.
-          if (should_revoke_sync_consent) {
+          if (!sync_service->GetUserSettings()->IsFirstSetupComplete()) {
             IdentityManagerFactory::GetForProfile(profile_)
                 ->GetPrimaryAccountMutator()
                 ->RevokeSyncConsent(
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index a19fa5f2..9571d50 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -38,7 +38,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/base/consent_level.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/accounts_mutator.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/identity_test_utils.h"
@@ -1354,8 +1353,6 @@
 }
 
 TEST(PeopleHandlerMainProfile, GetStoredAccountsList) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
   content::BrowserTaskEnvironment task_environment;
 
   TestingProfile::Builder builder;
@@ -1390,9 +1387,6 @@
 }
 
 TEST(PeopleHandlerSecondaryProfile, GetStoredAccountsList) {
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
-
   ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal());
   content::BrowserTaskEnvironment task_environment;
 
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index 1a67c27..3e342d7 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -72,7 +72,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/common/features.h"
 #include "components/signin/public/base/signin_pref_names.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "content/public/browser/url_data_source.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -238,9 +237,6 @@
   AddSettingsPageUIHandler(std::make_unique<SystemHandler>());
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   html_source->AddBoolean("isSecondaryUser", !profile->IsMainProfile());
-  html_source->AddBoolean(
-      "nonSyncingProfilesEnabled",
-      base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles));
 #endif
 
 #endif
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler.cc b/chrome/browser/ui/webui/signin/inline_login_handler.cc
index c8a9d17..47fbb80 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler.cc
@@ -34,6 +34,7 @@
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/url_util.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
 
 const char kSignInPromoQueryKeyShowAccountManagement[] =
     "showAccountManagement";
@@ -97,8 +98,8 @@
         value == "0") {
       partition->ClearData(
           content::StoragePartition::REMOVE_DATA_MASK_ALL,
-          content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
-          base::Time(), base::Time::Max(),
+          content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+          blink::StorageKey(), base::Time(), base::Time::Max(),
           base::BindOnce(&InlineLoginHandler::ContinueHandleInitializeMessage,
                          weak_ptr_factory_.GetWeakPtr()));
     } else {
diff --git a/chrome/browser/ui/webui/signin/profile_picker_ui.cc b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
index 02572cd..b3936884 100644
--- a/chrome/browser/ui/webui/signin/profile_picker_ui.cc
+++ b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
@@ -15,11 +15,9 @@
 #include "chrome/browser/profiles/profile_shortcut_manager.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
-#include "chrome/browser/signin/signin_features.h"
 #include "chrome/browser/signin/signin_util.h"
 #include "chrome/browser/ui/managed_ui.h"
 #include "chrome/browser/ui/profile_picker.h"
-#include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/webui/signin/profile_creation_customize_themes_handler.h"
 #include "chrome/browser/ui/webui/signin/profile_picker_handler.h"
 #include "chrome/browser/ui/webui/webui_util.h"
@@ -35,7 +33,6 @@
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/base/signin_buildflags.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -198,15 +195,9 @@
 #endif
   html_source->AddLocalizedString("mainViewTitle", main_view_title_id);
 
-  int sign_in_button_label_id =
-      IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_SIGNIN_BUTTON_LABEL;
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  if (!base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-    sign_in_button_label_id =
-        IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_SIGNIN_BUTTON_LABEL_LACROS;
-  }
-#endif
-  html_source->AddLocalizedString("signInButtonLabel", sign_in_button_label_id);
+  html_source->AddLocalizedString(
+      "signInButtonLabel",
+      IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_SIGNIN_BUTTON_LABEL);
 
   ProfilePicker::AvailabilityOnStartup availability_on_startup =
       static_cast<ProfilePicker::AvailabilityOnStartup>(
@@ -223,13 +214,6 @@
 #else
                           true);
 #endif
-  html_source->AddBoolean(
-      "localProfileCreationFlowSupported",
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-      base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles));
-#else
-      true);
-#endif
 
   html_source->AddString("minimumPickerSize",
                          base::StringPrintf("%ipx", kMinimumPickerSizePx));
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
index b1c8d045..26c21da 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
@@ -26,7 +26,6 @@
 #include "components/consent_auditor/consent_auditor.h"
 #include "components/signin/public/base/avatar_icon_util.h"
 #include "components/signin/public/base/consent_level.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -102,9 +101,6 @@
 }
 
 void SyncConfirmationHandler::HandleUndo(const base::Value::List& args) {
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  DCHECK(base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles));
-#endif
   did_user_explicitly_interact_ = true;
   CloseModalSigninWindow(LoginUIService::ABORT_SYNC);
 }
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
index f8ceb71..7837bdb 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/scoped_observation.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/metrics/user_action_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/consent_auditor/consent_auditor_factory.h"
@@ -33,7 +32,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/consent_auditor/fake_consent_auditor.h"
 #include "components/signin/public/base/avatar_icon_util.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_web_ui.h"
 
@@ -213,11 +211,6 @@
   base::HistogramTester histogram_tester_;
   std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
       identity_test_env_adaptor_;
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  base::test::ScopedFeatureList feature_list_{
-      switches::kLacrosNonSyncingProfiles};
-#endif
 };
 
 const char SyncConfirmationHandlerTest::kConsentText1[] = "consentText1";
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
index 40962de9..42a503c 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
@@ -25,7 +25,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/signin_resources.h"
 #include "components/signin/public/base/avatar_icon_util.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_ui.h"
@@ -39,16 +38,6 @@
 #include "ui/native_theme/native_theme.h"
 #include "ui/resources/grit/webui_generated_resources.h"
 
-namespace {
-
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-bool SyncForced() {
-  return !base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles);
-}
-#endif
-
-}  // namespace
-
 SyncConfirmationUI::SyncConfirmationUI(content::WebUI* web_ui)
     : SigninWebDialogUI(web_ui), profile_(Profile::FromWebUI(web_ui)) {
   bool is_modal =
@@ -102,13 +91,7 @@
   int info_title_id = IDS_SYNC_CONFIRMATION_SYNC_INFO_TITLE;
   int confirm_label_id = IDS_SYNC_CONFIRMATION_CONFIRM_BUTTON_LABEL;
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-  if (SyncForced()) {
-    title_id = IDS_SYNC_CONFIRMATION_TITLE_LACROS;
-    info_title_id = IDS_SYNC_CONFIRMATION_SYNC_INFO_TITLE_LACROS;
-    confirm_label_id = IDS_DONE;
-  } else {
-    title_id = IDS_SYNC_CONFIRMATION_TITLE_LACROS_NON_FORCED;
-  }
+  title_id = IDS_SYNC_CONFIRMATION_TITLE_LACROS_NON_FORCED;
 #endif
   AddStringResource(source, "syncConfirmationTitle", title_id);
   AddStringResource(source, "syncConfirmationSyncInfoTitle", info_title_id);
@@ -130,12 +113,6 @@
 
   source->AddBoolean("isModalDialog", is_modal_dialog);
 
-  bool sync_forced = false;
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  if (SyncForced())
-    sync_forced = true;
-#endif
-  source->AddBoolean("syncForced", sync_forced);
   source->AddString("accountPictureUrl",
                     profiles::GetPlaceholderAvatarIconUrl());
 
diff --git a/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc b/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc
index 1f34323..0af8cc83 100644
--- a/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc
+++ b/chrome/browser/ui/webui/signin/turn_sync_on_helper_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/location.h"
 #include "base/memory/raw_ptr.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
@@ -48,7 +47,6 @@
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/base/signin_metrics.h"
 #include "components/signin/public/base/signin_pref_names.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "components/signin/public/identity_manager/identity_test_utils.h"
@@ -641,9 +639,6 @@
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   testing::NiceMock<account_manager::MockAccountManagerFacade>
       mock_account_manager_facade_;
-
-  base::test::ScopedFeatureList scoped_feature_list_{
-      switches::kLacrosNonSyncingProfiles};
 #endif
 
   // State of the delegate calls.
diff --git a/chrome/browser/updater/browser_updater_client.h b/chrome/browser/updater/browser_updater_client.h
index 3b4d7d7..43c3adf 100644
--- a/chrome/browser/updater/browser_updater_client.h
+++ b/chrome/browser/updater/browser_updater_client.h
@@ -12,7 +12,6 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/sequence_checker.h"
 #include "base/task/sequenced_task_runner.h"
-#include "build/build_config.h"
 #include "chrome/updater/update_service.h"
 #include "chrome/updater/updater_scope.h"
 
@@ -22,33 +21,30 @@
 class BrowserUpdaterClient
     : public base::RefCountedThreadSafe<BrowserUpdaterClient> {
  public:
-  static scoped_refptr<BrowserUpdaterClient> Create();
-
-  BrowserUpdaterClient();
+  static scoped_refptr<BrowserUpdaterClient> Create(
+      updater::UpdaterScope scope);
 
   // Registers the browser to the Chromium updater via IPC registration API.
   // When registration is completed, it will call RegistrationCompleted().
+  // A ref to this object is held until the registration completes.
   void Register();
 
-  // Begins the process of an on-demand update from the Chromium updater via IPC
-  // update API. It will periodically get updates via HandleStatusUpdate(). When
-  // update is completed, it will call UpdateCompleted().
+  // Triggers an on-demand update from the Chromium updater, reporting status
+  // updates to the callback. A ref to this object is held until the update
+  // completes.
   void CheckForUpdate(
       base::RepeatingCallback<void(updater::UpdateService::UpdateState)>
           version_updater_callback);
 
   // Gets the current updater version. Can also be used to check for the
-  // existence of the updater.
+  // existence of the updater. A ref to the BrowserUpdaterClient is held until
+  // the callback is invoked.
   virtual void GetUpdaterVersion(
       base::OnceCallback<void(const std::string&)> callback) = 0;
 
-#if BUILDFLAG(IS_MAC)
-  // Resets the XPC Connection with the given scope.
-  virtual void ResetConnection(updater::UpdaterScope scope) = 0;
-#endif  // BUILDFLAG(IS_MAC)
-
  protected:
   friend class base::RefCountedThreadSafe<BrowserUpdaterClient>;
+  BrowserUpdaterClient();
   virtual ~BrowserUpdaterClient();
 
   scoped_refptr<base::SequencedTaskRunner> task_runner() {
diff --git a/chrome/browser/updater/browser_updater_client_mac.h b/chrome/browser/updater/browser_updater_client_mac.h
index 2f3e291..0a9b785 100644
--- a/chrome/browser/updater/browser_updater_client_mac.h
+++ b/chrome/browser/updater/browser_updater_client_mac.h
@@ -21,15 +21,15 @@
 
 class BrowserUpdaterClientMac : public BrowserUpdaterClient {
  public:
-  BrowserUpdaterClientMac();
+  explicit BrowserUpdaterClientMac(updater::UpdaterScope scope);
+  void GetUpdaterVersion(
+      base::OnceCallback<void(const std::string&)> callback) override;
+
+ private:
+  friend class UpdateClientMacTest;
   explicit BrowserUpdaterClientMac(
       base::scoped_nsobject<CRUUpdateClientOnDemandImpl> client);
 
-  void GetUpdaterVersion(
-      base::OnceCallback<void(const std::string&)> callback) override;
-  void ResetConnection(updater::UpdaterScope scope) override;
-
- private:
   ~BrowserUpdaterClientMac() override;
 
   SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/updater/browser_updater_client_mac.mm b/chrome/browser/updater/browser_updater_client_mac.mm
index 4e2e612..012a59d6 100644
--- a/chrome/browser/updater/browser_updater_client_mac.mm
+++ b/chrome/browser/updater/browser_updater_client_mac.mm
@@ -38,12 +38,6 @@
 
 @implementation CRUUpdateClientOnDemandImpl
 
-- (instancetype)init {
-  return [self initWithScope:ShouldUseSystemLevelUpdater()
-                                 ? updater::UpdaterScope::kSystem
-                                 : updater::UpdaterScope::kUser];
-}
-
 - (instancetype)initWithScope:(updater::UpdaterScope)scope {
   // If the system-level updater exists, and the browser is registered to the
   // system-level updater, then connect using NSXPCConnectionPrivileged.
@@ -179,10 +173,10 @@
 
 @end
 
-BrowserUpdaterClientMac::BrowserUpdaterClientMac()
+BrowserUpdaterClientMac::BrowserUpdaterClientMac(updater::UpdaterScope scope)
     : BrowserUpdaterClientMac(
           base::scoped_nsobject<CRUUpdateClientOnDemandImpl>(
-              [[CRUUpdateClientOnDemandImpl alloc] init])) {}
+              [[CRUUpdateClientOnDemandImpl alloc] initWithScope:scope])) {}
 
 BrowserUpdaterClientMac::BrowserUpdaterClientMac(
     base::scoped_nsobject<CRUUpdateClientOnDemandImpl> client)
@@ -193,7 +187,11 @@
 void BrowserUpdaterClientMac::GetUpdaterVersion(
     base::OnceCallback<void(const std::string&)> callback) {
   __block base::OnceCallback<void(const std::string&)> block_callback =
-      std::move(callback);
+      base::BindOnce(
+          [](base::OnceCallback<void(const std::string&)> callback,
+             scoped_refptr<BrowserUpdaterClientMac> keep_alive,
+             const std::string& version) { std::move(callback).Run(version); },
+          std::move(callback), base::WrapRefCounted(this));
 
   auto reply = ^(NSString* version) {
     std::string result = base::SysNSStringToUTF8(version);
@@ -204,10 +202,6 @@
   [client_ getVersionWithReply:reply];
 }
 
-void BrowserUpdaterClientMac::ResetConnection(updater::UpdaterScope scope) {
-  client_.reset([[CRUUpdateClientOnDemandImpl alloc] initWithScope:scope]);
-}
-
 void BrowserUpdaterClientMac::BeginRegister(
     const std::string& brand_code,
     const std::string& tag,
@@ -264,6 +258,7 @@
 }
 
 // static
-scoped_refptr<BrowserUpdaterClient> BrowserUpdaterClient::Create() {
-  return base::MakeRefCounted<BrowserUpdaterClientMac>();
+scoped_refptr<BrowserUpdaterClient> BrowserUpdaterClient::Create(
+    updater::UpdaterScope scope) {
+  return base::MakeRefCounted<BrowserUpdaterClientMac>(scope);
 }
diff --git a/chrome/browser/updater/browser_updater_client_util.h b/chrome/browser/updater/browser_updater_client_util.h
index a134e76e..c9c3ab8 100644
--- a/chrome/browser/updater/browser_updater_client_util.h
+++ b/chrome/browser/updater/browser_updater_client_util.h
@@ -7,6 +7,8 @@
 
 #include <string>
 
+#include "chrome/updater/updater_scope.h"
+
 namespace base {
 class FilePath;
 }
@@ -28,9 +30,9 @@
 
 // System level updater should only be used if the browser is owned by root.
 // During promotion, the browser will be changed to be owned by root and wheel.
-// A browser should go through promotion before it can utilize the system-level
+// A browser must go through promotion before it can utilize the system-level
 // updater.
-bool ShouldUseSystemLevelUpdater();
+updater::UpdaterScope GetUpdaterScope();
 
 // Updater should be promoted if it meets the following criteria:
 //    1) When browser is owned by root and updater is not yet installed.
diff --git a/chrome/browser/updater/browser_updater_client_util_mac.mm b/chrome/browser/updater/browser_updater_client_util_mac.mm
index a0c50a7..89451d4 100644
--- a/chrome/browser/updater/browser_updater_client_util_mac.mm
+++ b/chrome/browser/updater/browser_updater_client_util_mac.mm
@@ -20,17 +20,12 @@
 #include "base/strings/strcat.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/common/chrome_version.h"
+#include "chrome/updater/updater_scope.h"
 
 namespace {
 
-// If for_current_user is set to true, geteuid() will be called to get the
-// current effective user. If for_current_user is set to false, the given euid
-// will be 0, meaning the function will be checking with the root user in mind.
-bool PathOwnedByUser(const base::FilePath& path, bool for_current_user) {
-  uid_t user_uid = 0;
-  if (for_current_user)
-    user_uid = geteuid();
-
+bool BundleOwnedByUser(uid_t user_uid) {
+  const base::FilePath path = base::mac::OuterBundlePath();
   base::stat_wrapper_t stat_info = {};
   if (base::File::Lstat(path.value().c_str(), &stat_info) != 0) {
     VPLOG(2) << "Failed to get information on path " << path.value();
@@ -42,12 +37,15 @@
     return false;
   }
 
-  if (stat_info.st_uid != user_uid) {
-    VLOG(2) << "Path " << path.value() << " is owned by the wrong user.";
-    return false;
-  }
+  return stat_info.st_uid == user_uid;
+}
 
-  return true;
+bool BundleOwnedByRoot() {
+  return BundleOwnedByUser(0);
+}
+
+bool BundleOwnedByCurrentUser() {
+  return BundleOwnedByUser(geteuid());
 }
 
 bool IsEffectiveUserAdmin() {
@@ -118,17 +116,18 @@
 }
 
 bool CanInstallUpdater() {
-  return PathOwnedByUser(base::mac::OuterBundlePath(), true) && geteuid() != 0;
+  return BundleOwnedByCurrentUser() && geteuid() != 0;
 }
 
-bool ShouldUseSystemLevelUpdater() {
-  return PathOwnedByUser(base::mac::OuterBundlePath(), false);
+updater::UpdaterScope GetUpdaterScope() {
+  return BundleOwnedByRoot() ? updater::UpdaterScope::kSystem
+                             : updater::UpdaterScope::kUser;
 }
 
 bool ShouldPromoteUpdater() {
   // 1) Should promote if browser is owned by root and not installed. The not
   // installed part of this case is handled in version_updater_mac.mm
-  if (PathOwnedByUser(base::mac::OuterBundlePath(), false))
+  if (BundleOwnedByRoot())
     return true;
 
   // 2) If the effective user is root and the browser is not owned by root (i.e.
@@ -138,6 +137,5 @@
 
   // 3) If effective user is not the owner of the browser and is an
   // administrator.
-  return !PathOwnedByUser(base::mac::OuterBundlePath(), true) &&
-         IsEffectiveUserAdmin();
+  return !BundleOwnedByCurrentUser() && IsEffectiveUserAdmin();
 }
diff --git a/chrome/browser/user_agent/user_agent_browsertest.cc b/chrome/browser/user_agent/user_agent_browsertest.cc
index c1df8bb5..9b784fc 100644
--- a/chrome/browser/user_agent/user_agent_browsertest.cc
+++ b/chrome/browser/user_agent/user_agent_browsertest.cc
@@ -93,9 +93,7 @@
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), empty_url()));
   EXPECT_EQ(observed_user_agent(),
             embedder_support::GetFullUserAgent(
-                embedder_support::ForceMajorVersionToMinorPosition::kDefault,
-                embedder_support::UserAgentReductionEnterprisePolicyState::
-                    kForceDisabled));
+                embedder_support::ForceMajorVersionToMinorPosition::kDefault));
 }
 
 IN_PROC_BROWSER_TEST_P(UserAgentBrowserTest, ReductionPolicyEnabled) {
diff --git a/chrome/browser/user_notes/user_note_service_delegate_impl.cc b/chrome/browser/user_notes/user_note_service_delegate_impl.cc
index 325a527..8388db6f2 100644
--- a/chrome/browser/user_notes/user_note_service_delegate_impl.cc
+++ b/chrome/browser/user_notes/user_note_service_delegate_impl.cc
@@ -34,4 +34,11 @@
   return nullptr;
 }
 
+bool UserNoteServiceDelegateImpl::IsFrameInActiveTab(
+    const content::RenderFrameHost* rfh) {
+  // TODO(gujen): finish implementation.
+  NOTIMPLEMENTED();
+  return false;
+}
+
 }  // namespace user_notes
diff --git a/chrome/browser/user_notes/user_note_service_delegate_impl.h b/chrome/browser/user_notes/user_note_service_delegate_impl.h
index ed4d967..8a99690 100644
--- a/chrome/browser/user_notes/user_note_service_delegate_impl.h
+++ b/chrome/browser/user_notes/user_note_service_delegate_impl.h
@@ -36,6 +36,8 @@
   UserNotesUI* GetUICoordinatorForFrame(
       const content::RenderFrameHost* rfh) override;
 
+  bool IsFrameInActiveTab(const content::RenderFrameHost* rfh) override;
+
  private:
   raw_ptr<Profile> profile_;
 };
diff --git a/chrome/browser/user_notes/user_note_service_factory.cc b/chrome/browser/user_notes/user_note_service_factory.cc
index 6c51755..4c576fc8 100644
--- a/chrome/browser/user_notes/user_note_service_factory.cc
+++ b/chrome/browser/user_notes/user_note_service_factory.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/user_notes/user_note_service_delegate_impl.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/user_notes/browser/user_note_service.h"
+#include "components/user_notes/storage/user_note_storage_impl.h"
 #include "components/user_notes/user_notes_features.h"
 #include "content/public/browser/browser_context.h"
 
@@ -48,8 +49,10 @@
 KeyedService* UserNoteServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   DCHECK(IsUserNotesEnabled());
-  return new UserNoteService(std::make_unique<UserNoteServiceDelegateImpl>(
-      Profile::FromBrowserContext(context)));
+  return new UserNoteService(
+      std::make_unique<UserNoteServiceDelegateImpl>(
+          Profile::FromBrowserContext(context)),
+      std::make_unique<UserNoteStorageImpl>(context->GetPath()));
 }
 
 content::BrowserContext* UserNoteServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/user_notes/user_notes_tab_helper_unittest.cc b/chrome/browser/user_notes/user_notes_tab_helper_unittest.cc
index a214a8f..86b600bb 100644
--- a/chrome/browser/user_notes/user_notes_tab_helper_unittest.cc
+++ b/chrome/browser/user_notes/user_notes_tab_helper_unittest.cc
@@ -43,8 +43,10 @@
 
 class MockUserNoteService : public UserNoteService {
  public:
-  // A service delegate is not needed for these tests, so pass nullptr.
-  MockUserNoteService() : UserNoteService(/*delegate=*/nullptr) {}
+  // A service delegate and user note storage are not needed for these tests, so
+  // pass nullptr.
+  MockUserNoteService()
+      : UserNoteService(/*delegate=*/nullptr, /*storage=*/nullptr) {}
 
   MOCK_METHOD(void,
               OnFrameNavigated,
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index 24c6bf54..7b44bf0 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -35,6 +35,8 @@
     "extension_status_utils.h",
     "external_install_options.cc",
     "external_install_options.h",
+    "externally_installed_prefs_migration_metrics.cc",
+    "externally_installed_prefs_migration_metrics.h",
     "externally_installed_web_app_prefs.cc",
     "externally_installed_web_app_prefs.h",
     "externally_managed_app_install_task.cc",
@@ -384,8 +386,8 @@
   testonly = true
 
   sources = [
-    "system_web_apps/test/test_system_web_app_installation.cc",
-    "system_web_apps/test/test_system_web_app_installation.h",
+    # TODO(crbug.com/1321984): Move these files to
+    # chrome/browser/ash/system_web_apps/test_support/ directory.
     "system_web_apps/test/test_system_web_app_manager.cc",
     "system_web_apps/test/test_system_web_app_manager.h",
     "system_web_apps/test/test_system_web_app_url_data_source.cc",
@@ -668,6 +670,7 @@
     "//base",
     "//chrome/app:command_ids",
     "//chrome/browser/apps/app_service:test_support",
+    "//chrome/browser/ash/system_web_apps/test_support",
     "//chrome/browser/ash/system_web_apps/test_support:test_support_ui",
     "//chrome/browser/profiles:profile",
     "//chrome/test:test_support",
diff --git a/chrome/browser/web_applications/externally_installed_prefs_migration_metrics.cc b/chrome/browser/web_applications/externally_installed_prefs_migration_metrics.cc
new file mode 100644
index 0000000..7c8dcb7
--- /dev/null
+++ b/chrome/browser/web_applications/externally_installed_prefs_migration_metrics.cc
@@ -0,0 +1,27 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/externally_installed_prefs_migration_metrics.h"
+
+#include "base/metrics/histogram_functions.h"
+
+namespace web_app {
+void LogPlaceholderMigrationState(
+    const PlaceholderMigrationState& migration_state) {
+  base::UmaHistogramEnumeration(kPlaceholderMigrationHistogram,
+                                migration_state);
+}
+
+void LogInstallURLMigrationState(
+    const InstallURLMigrationState& migration_state) {
+  base::UmaHistogramEnumeration(kInstallURLMigrationHistogram, migration_state);
+}
+
+void LogUserUninstalledPreinstalledAppMigration(
+    const UserUninstalledPreinstalledAppMigrationState& migration_state) {
+  base::UmaHistogramEnumeration(kPreinstalledAppMigrationHistogram,
+                                migration_state);
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/externally_installed_prefs_migration_metrics.h b/chrome/browser/web_applications/externally_installed_prefs_migration_metrics.h
new file mode 100644
index 0000000..fa40d93e
--- /dev/null
+++ b/chrome/browser/web_applications/externally_installed_prefs_migration_metrics.h
@@ -0,0 +1,79 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEB_APPLICATIONS_EXTERNALLY_INSTALLED_PREFS_MIGRATION_METRICS_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_EXTERNALLY_INSTALLED_PREFS_MIGRATION_METRICS_H_
+
+namespace web_app {
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class PlaceholderMigrationState {
+  // Migration to web_app DB successful for placeholder info.
+  kPlaceholderInfoMigrated = 0,
+
+  // Migration to web_app DB skipped because data is in sync, or has been
+  // already migrated.
+  kPlaceholderInfoAlreadyInSync = 1,
+
+  kMaxValue = kPlaceholderInfoAlreadyInSync
+};
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class InstallURLMigrationState {
+  // Migration to web_app DB successful for install_url.
+  kInstallURLMigrated = 0,
+
+  // Migration to web_app DB skipped because data is in sync, or has been
+  // already migrated.
+  kInstallURLAlreadyInSync = 1,
+
+  kMaxValue = kInstallURLAlreadyInSync
+};
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class UserUninstalledPreinstalledAppMigrationState {
+  // Migration to UserUninstalledPreinstalledWebAppPrefs successful due to user
+  // uninstalls.
+  kPreinstalledAppDataMigratedByUser = 0,
+
+  // Migration to UserUninstalledPreinstalledWebAppPrefs successful due to true
+  // value in kWasExternalAppUninstalledByUser.
+  kPreinstalledAppDataMigratedByOldPref = 1,
+
+  // Migration to UserUninstalledPreinstalledWebAppPrefs skipped because data is
+  // in sync, or has been already migrated.
+  kPreinstalledAppDataAlreadyInSync = 2,
+
+  kMaxValue = kPreinstalledAppDataAlreadyInSync
+};
+
+const char kPrefDataAbsentDBDataAbsent[] =
+    "WebApp.ExternalPrefs.PrefDataAbsentDBDataAbsent";
+const char kPrefDataAbsentDBDataPresent[] =
+    "WebApp.ExternalPrefs.PrefDataAbsentDBDataPresent";
+const char kPrefDataPresentDBDataAbsent[] =
+    "WebApp.ExternalPrefs.PrefDataPresentDBDataAbsent";
+const char kPrefDataPresentDBDataPresent[] =
+    "WebApp.ExternalPrefs.PrefDataPresentDBDataPresent";
+const char kPlaceholderMigrationHistogram[] =
+    "WebApp.ExternalPrefs.PlaceholderMigrationState";
+const char kInstallURLMigrationHistogram[] =
+    "WebApp.ExternalPrefs.TypeOfMigrationSyncStatus";
+const char kPreinstalledAppMigrationHistogram[] =
+    "WebApp.ExternalPrefs.UserUninstalledPreinstalledAppMigrationState";
+
+// Setting functions
+void LogPlaceholderMigrationState(
+    const PlaceholderMigrationState& migration_state);
+void LogInstallURLMigrationState(
+    const InstallURLMigrationState& migration_state);
+void LogUserUninstalledPreinstalledAppMigration(
+    const UserUninstalledPreinstalledAppMigrationState& migration_state);
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_EXTERNALLY_INSTALLED_PREFS_MIGRATION_METRICS_H_
diff --git a/chrome/browser/web_applications/externally_installed_web_app_prefs.cc b/chrome/browser/web_applications/externally_installed_web_app_prefs.cc
index f326045..e7d59fb 100644
--- a/chrome/browser/web_applications/externally_installed_web_app_prefs.cc
+++ b/chrome/browser/web_applications/externally_installed_web_app_prefs.cc
@@ -9,6 +9,8 @@
 #include <vector>
 
 #include "base/containers/contains.h"
+#include "base/metrics/histogram_functions.h"
+#include "chrome/browser/web_applications/externally_installed_prefs_migration_metrics.h"
 #include "chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_prefs_utils.h"
@@ -279,26 +281,53 @@
   ExternallyInstalledWebAppPrefs::ParsedPrefs pref_to_app_data =
       ParseExternalPrefsToWebAppData(pref_service);
 
-  // First migrate data to UserUninstalledPreinstalledWebAppPrefs.
-  MigrateExternalPrefDataToPreinstalledPrefs(
-      pref_service, &sync_bridge->registrar(), pref_to_app_data);
+  const WebAppRegistrar& registrar = sync_bridge->registrar();
 
+  LogDataMetrics(pref_to_app_data.size() != 0,
+                 registrar.AppsExistWithExternalConfigData());
+
+  // First migrate data to UserUninstalledPreinstalledWebAppPrefs.
+  MigrateExternalPrefDataToPreinstalledPrefs(pref_service, &registrar,
+                                             pref_to_app_data);
   ScopedRegistryUpdate update(sync_bridge);
   for (auto it : pref_to_app_data) {
-    WebApp* web_app = update->UpdateApp(it.first);
+    const WebApp* web_app = registrar.GetAppById(it.first);
     if (web_app) {
       // Sync data across externally installed prefs and web_app DB.
       for (auto parsed_info : it.second) {
-        if (!web_app->GetSources().test(parsed_info.first)) {
+        WebAppManagement::Type& source = parsed_info.first;
+        if (!web_app->GetSources().test(source))
           continue;
+
+        auto config_map = web_app->management_to_external_config_map();
+        // Placeholder migration and metrics logging.
+        if (base::Contains(config_map, source) &&
+            config_map[source].is_placeholder ==
+                parsed_info.second.is_placeholder) {
+          LogPlaceholderMigrationState(
+              PlaceholderMigrationState::kPlaceholderInfoAlreadyInSync);
+        } else {
+          WebApp* updated_app = update->UpdateApp(it.first);
+          updated_app->AddPlaceholderInfoToManagementExternalConfigMap(
+              source, parsed_info.second.is_placeholder);
+          LogPlaceholderMigrationState(
+              PlaceholderMigrationState::kPlaceholderInfoMigrated);
         }
-        web_app->AddPlaceholderInfoToManagementExternalConfigMap(
-            parsed_info.first, parsed_info.second.is_placeholder);
+
+        // Install URL migration and metrics logging.
         for (auto url : parsed_info.second.install_urls) {
-          // Do not migrate invalid URLs.
           DCHECK(url.is_valid());
-          web_app->AddInstallURLToManagementExternalConfigMap(parsed_info.first,
-                                                              url);
+          if (base::Contains(config_map, source) &&
+              base::Contains(config_map[source].install_urls, url)) {
+            LogInstallURLMigrationState(
+                InstallURLMigrationState::kInstallURLAlreadyInSync);
+          } else {
+            WebApp* updated_app = update->UpdateApp(it.first);
+            updated_app->AddInstallURLToManagementExternalConfigMap(
+                parsed_info.first, url);
+            LogInstallURLMigrationState(
+                InstallURLMigrationState::kInstallURLMigrated);
+          }
         }
       }
     }
@@ -322,7 +351,17 @@
     // it was preinstalled and then uninstalled by user.
     if (!registrar->IsInstalledByDefaultManagement(app_id) &&
         it != source_to_config_map.end()) {
-      preinstalled_prefs.Add(app_id, it->second.install_urls);
+      if (preinstalled_prefs.AppIdContainsAllUrls(app_id, source_to_config_map,
+                                                  /*only_default=*/true)) {
+        LogUserUninstalledPreinstalledAppMigration(
+            UserUninstalledPreinstalledAppMigrationState::
+                kPreinstalledAppDataAlreadyInSync);
+      } else {
+        preinstalled_prefs.Add(app_id, std::move(it->second.install_urls));
+        LogUserUninstalledPreinstalledAppMigration(
+            UserUninstalledPreinstalledAppMigrationState::
+                kPreinstalledAppDataMigratedByUser);
+      }
     }
     // 2. If the value corresponding to the app_id in
     // web_app::kWasExternalAppUninstalledByUser is true, then it was previously
@@ -331,7 +370,19 @@
     // app could have been installed as an app with a different source now.
     if (GetBoolWebAppPref(pref_service, app_id,
                           kWasExternalAppUninstalledByUser)) {
-      preinstalled_prefs.Add(app_id, MergeAllUrls(source_to_config_map));
+      if (preinstalled_prefs.AppIdContainsAllUrls(app_id, source_to_config_map,
+                                                  /*only_default=*/false)) {
+        LogUserUninstalledPreinstalledAppMigration(
+            UserUninstalledPreinstalledAppMigrationState::
+                kPreinstalledAppDataAlreadyInSync);
+      } else {
+        base::flat_set<GURL> urls_to_migrate =
+            MergeAllUrls(source_to_config_map);
+        preinstalled_prefs.Add(app_id, std::move(urls_to_migrate));
+        LogUserUninstalledPreinstalledAppMigration(
+            UserUninstalledPreinstalledAppMigrationState::
+                kPreinstalledAppDataMigratedByOldPref);
+      }
     }
   }
 }
@@ -347,8 +398,30 @@
       urls.push_back(url);
     }
   }
-
   return urls;
 }
 
+// static
+void ExternallyInstalledWebAppPrefs::LogDataMetrics(
+    bool data_exists_in_pref,
+    bool data_exists_in_registrar) {
+  // Data in registry refers to the data stored in
+  // management_to_external_config_map per web_app. See
+  // WebApps::management_to_external_config_map() for more info.
+  if (!data_exists_in_pref && !data_exists_in_registrar) {
+    // Case 1: No external apps installed (prefs empty, empty data per web_app
+    // in the registry).
+    base::UmaHistogramBoolean(kPrefDataAbsentDBDataAbsent, /*sample=*/true);
+  } else if (!data_exists_in_pref && data_exists_in_registrar) {
+    // Case 2: prefs are empty, but data exists in registry.
+    base::UmaHistogramBoolean(kPrefDataAbsentDBDataPresent, /*sample=*/true);
+  } else if (data_exists_in_pref && !data_exists_in_registrar) {
+    // Case 3: prefs contain data, but data does not exist in the registry.
+    base::UmaHistogramBoolean(kPrefDataPresentDBDataAbsent, /*sample=*/true);
+  } else {
+    // Case 4: Data exists in both prefs and in the registry.
+    base::UmaHistogramBoolean(kPrefDataPresentDBDataPresent, /*sample=*/true);
+  }
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/externally_installed_web_app_prefs.h b/chrome/browser/web_applications/externally_installed_web_app_prefs.h
index b6ba07e..4a4e575 100644
--- a/chrome/browser/web_applications/externally_installed_web_app_prefs.h
+++ b/chrome/browser/web_applications/externally_installed_web_app_prefs.h
@@ -101,10 +101,15 @@
       PrefService* pref_service,
       const WebAppRegistrar* registrar,
       const ParsedPrefs& parsed_data);
+
   static base::flat_set<GURL> MergeAllUrls(
       const base::flat_map<WebAppManagement::Type,
                            WebApp::ExternalManagementConfig>&
           source_config_map);
+
+  static void LogDataMetrics(bool data_exists_in_pref,
+                             bool data_exists_in_registrar);
+
   const raw_ptr<PrefService> pref_service_;
 };
 
diff --git a/chrome/browser/web_applications/externally_installed_web_app_prefs_browsertest.cc b/chrome/browser/web_applications/externally_installed_web_app_prefs_browsertest.cc
index d6ad745..ad2804d 100644
--- a/chrome/browser/web_applications/externally_installed_web_app_prefs_browsertest.cc
+++ b/chrome/browser/web_applications/externally_installed_web_app_prefs_browsertest.cc
@@ -9,11 +9,14 @@
 #include "base/containers/contains.h"
 #include "base/containers/flat_set.h"
 #include "base/json/json_reader.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
+#include "chrome/browser/web_applications/externally_installed_prefs_migration_metrics.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
+#include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_prefs_utils.h"
@@ -423,6 +426,8 @@
   ExternallyInstalledWebAppPrefs external_prefs(profile()->GetPrefs());
   UserUninstalledPreinstalledWebAppPrefs preinstalled_prefs(
       profile()->GetPrefs());
+  base::HistogramTester tester;
+
   AppId app_id1 = "test_app1";
   external_prefs.Insert(GURL("https://app1.com/install"), app_id1,
                         ExternalInstallSource::kExternalPolicy);
@@ -431,12 +436,20 @@
   external_prefs.Insert(GURL("https://app2.com/install"), app_id1,
                         ExternalInstallSource::kArc);
   external_prefs.SetIsPlaceholder(GURL("https://app2.com/install"), true);
+  tester.ExpectBucketCount(kPreinstalledAppMigrationHistogram,
+                           UserUninstalledPreinstalledAppMigrationState::
+                               kPreinstalledAppDataMigratedByOldPref,
+                           0);
 
   UpdateBoolWebAppPref(profile()->GetPrefs(), app_id1,
                        kWasExternalAppUninstalledByUser, true);
 
   ExternallyInstalledWebAppPrefs::MigrateExternalPrefData(
       profile()->GetPrefs(), &provider().sync_bridge());
+  tester.ExpectBucketCount(kPreinstalledAppMigrationHistogram,
+                           UserUninstalledPreinstalledAppMigrationState::
+                               kPreinstalledAppDataMigratedByOldPref,
+                           1);
 
   // On migration, everything (app_ids and both URLs should be migrated).
   EXPECT_TRUE(preinstalled_prefs.DoesAppIdExist(app_id1));
@@ -477,6 +490,154 @@
   EXPECT_EQ(1, preinstalled_prefs.Size());
 }
 
+IN_PROC_BROWSER_TEST_F(ExternallyInstalledWebAppPrefsBrowserTest,
+                       MigrationMetricsLoggedProperly) {
+  PrefService* pref_service = profile()->GetPrefs();
+  ExternallyInstalledWebAppPrefs external_prefs(pref_service);
+  base::HistogramTester tester;
+  const GURL url("https://app.com/install");
+
+  // Initially, all buckets are empty.
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataAbsentDBDataAbsent), 0);
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataAbsentDBDataPresent), 0);
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataPresentDBDataAbsent), 0);
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataPresentDBDataPresent), 0);
+
+  external_prefs.Insert(url, GenerateAppId(/*manifest_id=*/absl::nullopt, url),
+                        ExternalInstallSource::kExternalDefault);
+  external_prefs.SetIsPlaceholder(url, true);
+
+  // Mock the startup by triggering a migration. Right now, only pref
+  // data should be present.
+  ExternallyInstalledWebAppPrefs::MigrateExternalPrefData(
+      pref_service, &provider().sync_bridge());
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataAbsentDBDataAbsent), 0);
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataAbsentDBDataPresent), 0);
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataPresentDBDataAbsent), 1);
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataPresentDBDataPresent), 0);
+  tester.ExpectBucketCount(kPlaceholderMigrationHistogram,
+                           PlaceholderMigrationState::kPlaceholderInfoMigrated,
+                           0);
+  tester.ExpectBucketCount(kInstallURLMigrationHistogram,
+                           InstallURLMigrationState::kInstallURLMigrated, 0);
+  tester.ExpectBucketCount(kPreinstalledAppMigrationHistogram,
+                           UserUninstalledPreinstalledAppMigrationState::
+                               kPreinstalledAppDataMigratedByUser,
+                           1);
+
+  // Install a web_app and then retrigger migration. This should cause both
+  // pref and DB data to be present.
+  {
+    auto web_app_install_info = std::make_unique<WebAppInstallInfo>();
+    web_app_install_info->start_url = url;
+    web_app_install_info->title = u"App Title";
+    web_app_install_info->display_mode = web_app::DisplayMode::kBrowser;
+    web_app_install_info->user_display_mode =
+        web_app::UserDisplayMode::kStandalone;
+    AppId app_id =
+        test::InstallWebApp(profile(), std::move(web_app_install_info),
+                            /*overwrite_existing_manifest_fields=*/true,
+                            webapps::WebappInstallSource::EXTERNAL_DEFAULT);
+  }
+
+  // Retrigger the migration once web_app has been installed.
+  ExternallyInstalledWebAppPrefs::MigrateExternalPrefData(
+      pref_service, &provider().sync_bridge());
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataAbsentDBDataAbsent), 0);
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataAbsentDBDataPresent), 0);
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataPresentDBDataAbsent), 1);
+  EXPECT_EQ(tester.GetTotalSum(kPrefDataPresentDBDataPresent), 1);
+  tester.ExpectBucketCount(kPlaceholderMigrationHistogram,
+                           PlaceholderMigrationState::kPlaceholderInfoMigrated,
+                           1);
+  tester.ExpectBucketCount(kInstallURLMigrationHistogram,
+                           InstallURLMigrationState::kInstallURLMigrated, 1);
+  tester.ExpectBucketCount(kPreinstalledAppMigrationHistogram,
+                           UserUninstalledPreinstalledAppMigrationState::
+                               kPreinstalledAppDataMigratedByUser,
+                           1);
+}
+
+IN_PROC_BROWSER_TEST_F(ExternallyInstalledWebAppPrefsBrowserTest,
+                       MetricsInSyncWebAppDB) {
+  PrefService* pref_service = profile()->GetPrefs();
+  ExternallyInstalledWebAppPrefs external_prefs(pref_service);
+  base::HistogramTester tester;
+  const GURL url("https://app.com/install");
+
+  external_prefs.Insert(url, GenerateAppId(/*manifest_id=*/absl::nullopt, url),
+                        ExternalInstallSource::kExternalPolicy);
+  external_prefs.SetIsPlaceholder(url, true);
+
+  // Install a web_app and then trigger migration. This would cause the
+  // sync histograms to be filled as data already exists.
+  AppId app_id;
+  {
+    auto web_app_install_info = std::make_unique<WebAppInstallInfo>();
+    web_app_install_info->start_url = url;
+    web_app_install_info->title = u"App Title";
+    web_app_install_info->display_mode = web_app::DisplayMode::kBrowser;
+    web_app_install_info->user_display_mode =
+        web_app::UserDisplayMode::kStandalone;
+    web_app_install_info->install_url = url;
+    app_id = test::InstallWebApp(profile(), std::move(web_app_install_info),
+                                 /*overwrite_existing_manifest_fields=*/true,
+                                 webapps::WebappInstallSource::EXTERNAL_POLICY);
+  }
+  tester.ExpectBucketCount(
+      kPlaceholderMigrationHistogram,
+      PlaceholderMigrationState::kPlaceholderInfoAlreadyInSync, 0);
+  tester.ExpectBucketCount(kInstallURLMigrationHistogram,
+                           InstallURLMigrationState::kInstallURLAlreadyInSync,
+                           0);
+  {
+    ScopedRegistryUpdate update(&provider().sync_bridge());
+    WebApp* installed_app = update->UpdateApp(app_id);
+    if (installed_app) {
+      installed_app->AddPlaceholderInfoToManagementExternalConfigMap(
+          WebAppManagement::kPolicy, /*is_placeholder=*/true);
+    }
+  }
+  // Retrigger the migration once web_app has been installed.
+  ExternallyInstalledWebAppPrefs::MigrateExternalPrefData(
+      pref_service, &provider().sync_bridge());
+  tester.ExpectBucketCount(
+      kPlaceholderMigrationHistogram,
+      PlaceholderMigrationState::kPlaceholderInfoAlreadyInSync, 1);
+  tester.ExpectBucketCount(kInstallURLMigrationHistogram,
+                           InstallURLMigrationState::kInstallURLAlreadyInSync,
+                           1);
+}
+
+IN_PROC_BROWSER_TEST_F(ExternallyInstalledWebAppPrefsBrowserTest,
+                       MetricsInSyncUserUninstalledPrefs) {
+  PrefService* pref_service = profile()->GetPrefs();
+  ExternallyInstalledWebAppPrefs external_prefs(pref_service);
+  UserUninstalledPreinstalledWebAppPrefs preinstalled_prefs(pref_service);
+  base::HistogramTester tester;
+
+  external_prefs.Insert(GURL("https://a.com/"), "app_id",
+                        ExternalInstallSource::kExternalDefault);
+  external_prefs.Insert(GURL("https://b.com/"), "app_id",
+                        ExternalInstallSource::kInternalDefault);
+  tester.ExpectBucketCount(kPreinstalledAppMigrationHistogram,
+                           UserUninstalledPreinstalledAppMigrationState::
+                               kPreinstalledAppDataAlreadyInSync,
+                           0);
+
+  // Now the data in the preinstalled_prefs and external_prefs are the safe,
+  // triggering migration should log a kPreinstalledAppDataAlreadyInSync.
+  preinstalled_prefs.Add("app_id",
+                         {GURL("https://a.com/"), GURL("https://b.com/")});
+
+  ExternallyInstalledWebAppPrefs::MigrateExternalPrefData(
+      pref_service, &provider().sync_bridge());
+  tester.ExpectBucketCount(kPreinstalledAppMigrationHistogram,
+                           UserUninstalledPreinstalledAppMigrationState::
+                               kPreinstalledAppDataAlreadyInSync,
+                           1);
+}
+
 INSTANTIATE_TEST_SUITE_P(
     All,
     ExternallyInstalledWebAppPrefsBrowserTest_ExternalPrefMigration,
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
index 223d0998..e15f1de 100644
--- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -33,6 +33,7 @@
 #include "build/build_config.h"
 #include "build/buildflag.h"
 #include "build/chromeos_buildflags.h"
+#include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_dialogs.h"
@@ -45,7 +46,6 @@
 #include "chrome/browser/web_applications/manifest_update_task.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
 #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
-#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/test/web_app_icon_test_utils.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/test/web_app_sync_test_utils.h"
@@ -1956,8 +1956,8 @@
     : public ManifestUpdateManagerBrowserTest {
  public:
   ManifestUpdateManagerSystemAppBrowserTest()
-      : system_app_(
-            TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp()) {
+      : system_app_(ash::TestSystemWebAppInstallation::
+                        SetUpStandaloneSingleWindowApp()) {
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
     EnableSystemWebAppsInLacrosForTesting();
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -1966,7 +1966,7 @@
   void SetUpOnMainThread() override { system_app_->WaitForAppInstall(); }
 
  protected:
-  std::unique_ptr<TestSystemWebAppInstallation> system_app_;
+  std::unique_ptr<ash::TestSystemWebAppInstallation> system_app_;
 };
 
 IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerSystemAppBrowserTest,
diff --git a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.cc b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.cc
index 99e7116f..9f5498a8 100644
--- a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.cc
+++ b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.cc
@@ -8,12 +8,19 @@
 #include <utility>
 
 #include "base/containers/contains.h"
+#include "base/metrics/user_metrics.h"
 #include "base/strings/string_piece.h"
 #include "base/values.h"
+#include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_constants.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace web_app {
 
+const char UserUninstalledPreinstalledWebAppPrefs::
+    kUserUninstalledPreinstalledAppAction[] =
+        "WebApp.Preinstalled.UninstallByUser";
+
 UserUninstalledPreinstalledWebAppPrefs::UserUninstalledPreinstalledWebAppPrefs(
     PrefService* pref_service)
     : pref_service_(pref_service) {}
@@ -36,6 +43,11 @@
   for (auto install_url : install_urls)
     url_list.Append(install_url.spec());
 
+  if (!DoesAppIdExist(app_id)) {
+    base::RecordAction(
+        base::UserMetricsAction(kUserUninstalledPreinstalledAppAction));
+  }
+
   DictionaryPrefUpdate update(pref_service_,
                               prefs::kUserUninstalledPreinstalledWebAppPref);
   update->SetKey(app_id, base::Value(std::move(url_list)));
@@ -158,4 +170,43 @@
   return true;
 }
 
+bool UserUninstalledPreinstalledWebAppPrefs::AppIdContainsAllUrls(
+    const AppId& app_id,
+    const base::flat_map<WebAppManagement::Type,
+                         WebApp::ExternalManagementConfig>& url_map,
+    const bool only_default) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (url_map.empty())
+    return false;
+
+  const base::Value* ids_to_urls = pref_service_->GetDictionary(
+      prefs::kUserUninstalledPreinstalledWebAppPref);
+  if (!ids_to_urls)
+    return false;
+
+  const base::Value::Dict* pref_info = ids_to_urls->GetIfDict();
+  if (!pref_info)
+    return false;
+
+  const base::Value::List* current_list = pref_info->FindList(app_id);
+  if (!current_list)
+    return false;
+
+  base::flat_set<std::string> existing_urls;
+  for (const base::Value& url : *current_list) {
+    existing_urls.emplace(url.GetString());
+  }
+
+  for (auto it : url_map) {
+    if (only_default && !(it.first == WebAppManagement::kDefault))
+      continue;
+
+    for (const GURL& url_to_insert : it.second.install_urls) {
+      if (!base::Contains(existing_urls, url_to_insert.spec()))
+        return false;
+    }
+  }
+  return true;
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h
index 5b92d0f..0accde2f7 100644
--- a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h
+++ b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs.h
@@ -7,6 +7,8 @@
 
 #include "base/containers/flat_set.h"
 #include "base/memory/raw_ptr.h"
+#include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/common/pref_names.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -44,6 +46,7 @@
 // PreinstalledAppsUninstalledByUserConfigs json for debugging purposes.
 class UserUninstalledPreinstalledWebAppPrefs {
  public:
+  static const char kUserUninstalledPreinstalledAppAction[];
   explicit UserUninstalledPreinstalledWebAppPrefs(PrefService* pref_service);
   UserUninstalledPreinstalledWebAppPrefs(
       const UserUninstalledPreinstalledWebAppPrefs&) = delete;
@@ -58,6 +61,11 @@
                                          base::flat_set<GURL>& urls);
   int Size();
   bool RemoveByInstallUrl(const AppId& app_id, const GURL& install_url);
+  bool AppIdContainsAllUrls(
+      const AppId& app_id,
+      const base::flat_map<WebAppManagement::Type,
+                           WebApp::ExternalManagementConfig>& url_map,
+      const bool only_default);
 
  private:
   const raw_ptr<PrefService> pref_service_;
diff --git a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs_browsertest.cc b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs_browsertest.cc
index 3002e43..657d1bce 100644
--- a/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs_browsertest.cc
+++ b/chrome/browser/web_applications/user_uninstalled_preinstalled_web_app_prefs_browsertest.cc
@@ -7,11 +7,14 @@
 #include <memory>
 
 #include "base/containers/flat_set.h"
+#include "base/test/metrics/user_action_tester.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
+#include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
@@ -25,18 +28,31 @@
 
 IN_PROC_BROWSER_TEST_F(UserUninstalledPreinstalledWebAppPrefsBrowserTest,
                        BasicOperations) {
+  base::UserActionTester tester;
   GURL url1("https://foo.com");
   GURL url2("https://bar1.com");
   GURL url3("https://bar2.com");
   AppId app_id1 = "foo";
   AppId app_id2 = "bar";
-
   UserUninstalledPreinstalledWebAppPrefs preinstalled_prefs(
       profile()->GetPrefs());
+
+  EXPECT_EQ(tester.GetActionCount(UserUninstalledPreinstalledWebAppPrefs::
+                                      kUserUninstalledPreinstalledAppAction),
+            0);
   preinstalled_prefs.Add(app_id1, {url1});
+  EXPECT_EQ(tester.GetActionCount(UserUninstalledPreinstalledWebAppPrefs::
+                                      kUserUninstalledPreinstalledAppAction),
+            1);
   preinstalled_prefs.Add(app_id2, {url2});
+  EXPECT_EQ(tester.GetActionCount(UserUninstalledPreinstalledWebAppPrefs::
+                                      kUserUninstalledPreinstalledAppAction),
+            2);
   // To test that url3 gets appended.
   preinstalled_prefs.Add(app_id2, {url3});
+  EXPECT_EQ(tester.GetActionCount(UserUninstalledPreinstalledWebAppPrefs::
+                                      kUserUninstalledPreinstalledAppAction),
+            2);
 
   // Basic checks to verify app id exists in preinstalled prefs or not.
   EXPECT_TRUE(preinstalled_prefs.DoesAppIdExist(app_id1));
@@ -123,4 +139,31 @@
   EXPECT_FALSE(preinstalled_prefs.DoesAppIdExist(app_id2));
 }
 
+IN_PROC_BROWSER_TEST_F(UserUninstalledPreinstalledWebAppPrefsBrowserTest,
+                       VerifyAppIdContainsAllUrls) {
+  UserUninstalledPreinstalledWebAppPrefs preinstalled_prefs(
+      profile()->GetPrefs());
+  base::flat_map<WebAppManagement::Type, WebApp::ExternalManagementConfig>
+      test_map;
+  WebApp::ExternalManagementConfig config1;
+  WebApp::ExternalManagementConfig config2;
+  config1.install_urls = {GURL("https://a.com")};
+  config2.install_urls = {GURL("https://c.com")};
+  // Default source test.
+  test_map[WebAppManagement::kDefault] = std::move(config1);
+  preinstalled_prefs.Add("app_id",
+                         {GURL("https://a.com"), GURL("https://b.com")});
+  EXPECT_TRUE(preinstalled_prefs.AppIdContainsAllUrls("app_id", test_map,
+                                                      /*only_default=*/true));
+  // Non-default source test.
+  test_map[WebAppManagement::kPolicy] = std::move(config2);
+  EXPECT_FALSE(preinstalled_prefs.AppIdContainsAllUrls("app_id", test_map,
+                                                       /*only_default=*/false));
+  // Empty test.
+  test_map.erase(WebAppManagement::kDefault);
+  test_map.erase(WebAppManagement::kPolicy);
+  EXPECT_FALSE(preinstalled_prefs.AppIdContainsAllUrls("app_id", test_map,
+                                                       /*only_default=*/false));
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_constants.h b/chrome/browser/web_applications/web_app_constants.h
index 0c25bdb..1b260b6d 100644
--- a/chrome/browser/web_applications/web_app_constants.h
+++ b/chrome/browser/web_applications/web_app_constants.h
@@ -242,6 +242,7 @@
 };
 
 using LaunchHandler = blink::Manifest::LaunchHandler;
+using TabStrip = blink::Manifest::TabStrip;
 
 // A result how `WebAppIconDownloader` processed the list of icon urls.
 //
diff --git a/chrome/browser/web_applications/web_app_install_info.h b/chrome/browser/web_applications/web_app_install_info.h
index 6e96223..568f313 100644
--- a/chrome/browser/web_applications/web_app_install_info.h
+++ b/chrome/browser/web_applications/web_app_install_info.h
@@ -333,6 +333,10 @@
   // populated (especially for user installed or sync installed apps)
   // in which case the URL will not be written to the web_app DB.
   GURL install_url;
+
+  // Customisations to the tab strip. This field is only used when the
+  // display mode is set to 'tabbed'.
+  absl::optional<blink::Manifest::TabStrip> tab_strip;
 };
 
 bool operator==(const IconSizes& icon_sizes1, const IconSizes& icon_sizes2);
diff --git a/chrome/browser/web_applications/web_app_install_utils.cc b/chrome/browser/web_applications/web_app_install_utils.cc
index 7ec5f8c..b89a334 100644
--- a/chrome/browser/web_applications/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/web_app_install_utils.cc
@@ -591,6 +591,8 @@
     copy.matches_opaque_src = decl.matches_opaque_src;
     web_app_info->permissions_policy.push_back(std::move(copy));
   }
+
+  web_app_info->tab_strip = manifest.tab_strip;
 }
 
 std::vector<GURL> GetValidIconUrlsToDownload(
diff --git a/chrome/browser/web_applications/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/web_app_install_utils_unittest.cc
index b8ecf07..25b9b3ec 100644
--- a/chrome/browser/web_applications/web_app_install_utils_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_utils_unittest.cc
@@ -1022,6 +1022,64 @@
   EXPECT_FALSE(web_app_info.translations["language 3"].description);
 }
 
+TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifest_TabStrip) {
+  blink::mojom::Manifest manifest;
+  WebAppInstallInfo web_app_info;
+
+  {
+    TabStrip tab_strip;
+    tab_strip.home_tab = TabStrip::Visibility::kAbsent;
+    tab_strip.new_tab_button = TabStrip::Visibility::kAuto;
+    manifest.tab_strip = std::move(tab_strip);
+
+    const GURL kAppManifestUrl("http://www.chromium.org/manifest.json");
+    UpdateWebAppInfoFromManifest(manifest, kAppManifestUrl, &web_app_info);
+
+    EXPECT_TRUE(web_app_info.tab_strip.has_value());
+    EXPECT_EQ(absl::get<TabStrip::Visibility>(
+                  web_app_info.tab_strip.value().home_tab),
+              TabStrip::Visibility::kAbsent);
+    EXPECT_EQ(absl::get<TabStrip::Visibility>(
+                  web_app_info.tab_strip.value().new_tab_button),
+              TabStrip::Visibility::kAuto);
+  }
+
+  {
+    blink::Manifest::ImageResource icon;
+    const GURL kAppIcon("fav1.png");
+    icon.purpose = {Purpose::ANY};
+    icon.src = kAppIcon;
+
+    TabStrip tab_strip;
+    blink::Manifest::HomeTabParams home_tab_params;
+    home_tab_params.icons.push_back(icon);
+    tab_strip.home_tab = home_tab_params;
+
+    blink::Manifest::NewTabButtonParams new_tab_button_params;
+    new_tab_button_params.url = GURL("https://www.example.com/");
+    tab_strip.new_tab_button = new_tab_button_params;
+    manifest.tab_strip = std::move(tab_strip);
+
+    const GURL kAppManifestUrl("http://www.chromium.org/manifest.json");
+    UpdateWebAppInfoFromManifest(manifest, kAppManifestUrl, &web_app_info);
+
+    EXPECT_TRUE(web_app_info.tab_strip.has_value());
+    EXPECT_EQ(absl::get<blink::Manifest::HomeTabParams>(
+                  web_app_info.tab_strip.value().home_tab)
+                  .icons.size(),
+              1u);
+    EXPECT_EQ(absl::get<blink::Manifest::HomeTabParams>(
+                  web_app_info.tab_strip.value().home_tab)
+                  .icons[0]
+                  .src,
+              kAppIcon);
+    EXPECT_EQ(absl::get<blink::Manifest::NewTabButtonParams>(
+                  web_app_info.tab_strip.value().new_tab_button)
+                  .url,
+              GURL("https://www.example.com/"));
+  }
+}
+
 class FileHandlersFromManifestTest : public ::testing::TestWithParam<bool> {
  public:
   FileHandlersFromManifestTest() {
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc
index a2d5822..7e7bb6c 100644
--- a/chrome/browser/web_applications/web_app_registrar.cc
+++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -513,6 +513,14 @@
   return app_ids;
 }
 
+bool WebAppRegistrar::AppsExistWithExternalConfigData() const {
+  for (const WebApp& web_app : GetApps()) {
+    if (web_app.management_to_external_config_map().size() > 0)
+      return true;
+  }
+  return false;
+}
+
 void WebAppRegistrar::Start() {
   // Profile manager can be null in unit tests.
   if (g_browser_process->profile_manager())
diff --git a/chrome/browser/web_applications/web_app_registrar.h b/chrome/browser/web_applications/web_app_registrar.h
index 1336752..6bb73c5 100644
--- a/chrome/browser/web_applications/web_app_registrar.h
+++ b/chrome/browser/web_applications/web_app_registrar.h
@@ -69,6 +69,8 @@
   const WebApp* GetAppByStartUrl(const GURL& start_url) const;
   std::vector<AppId> GetAppsFromSyncAndPendingInstallation() const;
 
+  bool AppsExistWithExternalConfigData() const;
+
   void Start();
   void Shutdown();
 
diff --git a/chrome/browser/webapps/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenIPHController.java b/chrome/browser/webapps/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenIPHController.java
index a5009d7e..cdbd4ef 100644
--- a/chrome/browser/webapps/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenIPHController.java
+++ b/chrome/browser/webapps/android/java/src/org/chromium/chrome/browser/webapps/AddToHomescreenIPHController.java
@@ -8,22 +8,14 @@
 import android.content.Context;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
-import android.os.Handler;
-import android.view.View;
 
-import androidx.annotation.IdRes;
 import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
 
 import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.banners.AppMenuVerbiage;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler;
-import org.chromium.chrome.browser.user_education.IPHCommandBuilder;
-import org.chromium.chrome.browser.user_education.UserEducationHelper;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.feature_engagement.EventConstants;
 import org.chromium.components.feature_engagement.FeatureConstants;
@@ -48,45 +40,26 @@
  * creation, metrics logging etc.
  */
 public class AddToHomescreenIPHController {
-    private static final String VARIATION_KEY_USE_TEXT_BUBBLE = "use_text_bubble";
-    private static final String VARIATION_KEY_USE_MESSAGE = "use_message";
-
     private Activity mActivity;
-    private AppMenuHandler mAppMenuHandler;
     private final WindowAndroid mWindowAndroid;
     private final ModalDialogManager mModalDialogManager;
-    private final @IdRes int mHighlightMenuItemId;
-    private final Supplier<View> mMenuButtonView;
     private final MessageDispatcher mMessageDispatcher;
-    private final UserEducationHelper mUserEducationHelper;
     private final Tracker mTracker;
-    private final Handler mHandler = new Handler();
-
-    private GURL mLastClickedMostVisitedTileUrl;
 
     /**
      * Creates an {@link AddToHomescreenIPHController}.
      * @param activity The associated activity.
      * @param windowAndroid The associated {@link WindowAndroid}.
      * @param modalDialogManager The {@link ModalDialogManager} for showing the dialog.
-     * @param appMenuHandler The {@link AppMenuHandler}.
-     * @param highlightMenuItemId The resource id of 'Add to Home screen' in the app menu.
-     * @param menuButtonView The view representing the menu button.
      * @param messageDispatcher The {@link MessageDispatcher} for displaying messages.
      */
     public AddToHomescreenIPHController(Activity activity, WindowAndroid windowAndroid,
-            ModalDialogManager modalDialogManager, AppMenuHandler appMenuHandler,
-            @IdRes int highlightMenuItemId, Supplier<View> menuButtonView,
-            MessageDispatcher messageDispatcher) {
+            ModalDialogManager modalDialogManager, MessageDispatcher messageDispatcher) {
         mActivity = activity;
         mWindowAndroid = windowAndroid;
         mModalDialogManager = modalDialogManager;
-        mAppMenuHandler = appMenuHandler;
-        mHighlightMenuItemId = highlightMenuItemId;
-        mMenuButtonView = menuButtonView;
         mMessageDispatcher = messageDispatcher;
         mTracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile());
-        mUserEducationHelper = new UserEducationHelper(mActivity, mHandler);
     }
 
     /**
@@ -96,16 +69,7 @@
     public void showAddToHomescreenIPH(Tab tab) {
         if (mActivity == null) return;
         if (!canShowAddToHomescreenMenuItem(mActivity, tab)) return;
-
-        if (ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
-                    ChromeFeatureList.ADD_TO_HOMESCREEN_IPH, VARIATION_KEY_USE_TEXT_BUBBLE,
-                    false)) {
-            showTextBubbleIPH();
-        } else if (ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
-                           ChromeFeatureList.ADD_TO_HOMESCREEN_IPH, VARIATION_KEY_USE_MESSAGE,
-                           false)) {
-            showMessageIPH(tab);
-        }
+        showMessageIPH(tab);
     }
 
     /**
@@ -113,7 +77,6 @@
      */
     public void destroy() {
         mActivity = null;
-        mAppMenuHandler = null;
     }
 
     private static boolean canShowAddToHomescreenMenuItem(Context context, Tab tab) {
@@ -148,27 +111,7 @@
         return true;
     }
 
-    private void showTextBubbleIPH() {
-        mUserEducationHelper.requestShowIPH(
-                new IPHCommandBuilder(mActivity.getResources(),
-                        FeatureConstants.ADD_TO_HOMESCREEN_TEXT_BUBBLE_FEATURE,
-                        R.string.iph_bubble_add_to_home_screen,
-                        R.string.iph_bubble_add_to_home_screen_accessibility)
-                        .setAnchorView(mMenuButtonView.get())
-                        .setOnShowCallback(this::turnOnTextBubbleHighlightForMenuItem)
-                        .setOnDismissCallback(this::turnOffTextBubbleHighlightForMenuItem)
-                        .build());
-    }
-
     private void showMessageIPH(Tab tab) {
-        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.MESSAGES_FOR_ANDROID_INFRASTRUCTURE)) {
-            return;
-        }
-
-        if (!mTracker.shouldTriggerHelpUI(FeatureConstants.ADD_TO_HOMESCREEN_MESSAGE_FEATURE)) {
-            return;
-        }
-
         PropertyModel model =
                 new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
                         .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
@@ -214,14 +157,4 @@
         // TODO(shaktisahu): Record metrics for explicit dismiss vs timeout.
         mTracker.dismissed(FeatureConstants.ADD_TO_HOMESCREEN_MESSAGE_FEATURE);
     }
-
-    private void turnOnTextBubbleHighlightForMenuItem() {
-        if (mAppMenuHandler == null) return;
-        mAppMenuHandler.setMenuHighlight(mHighlightMenuItemId);
-    }
-
-    private void turnOffTextBubbleHighlightForMenuItem() {
-        if (mAppMenuHandler == null) return;
-        mAppMenuHandler.clearMenuHighlight();
-    }
 }
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
index 91fa826..25f3e6e 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -167,21 +167,20 @@
 
 void AuthenticatorRequestDialogModel::StartFlow(
     TransportAvailabilityInfo transport_availability,
-    bool use_location_bar_bubble,
+    bool use_conditional_mediation,
     bool prefer_native_api) {
   DCHECK(!started_);
   DCHECK_EQ(current_step(), Step::kNotStarted);
 
   started_ = true;
   transport_availability_ = std::move(transport_availability);
-  use_location_bar_bubble_ = use_location_bar_bubble;
+  use_conditional_mediation_ = use_conditional_mediation;
 
   PopulateMechanisms(prefer_native_api);
 
-  if (use_location_bar_bubble_) {
-    // This is a conditional request so show a lightweight, non-modal dialog
-    // instead.
-    StartLocationBarBubbleRequest();
+  if (use_conditional_mediation_) {
+    // This is a conditional mediation request.
+    StartConditionalMediationRequest();
   } else {
     StartGuidedFlowForMostLikelyTransportOrShowMechanismSelection();
   }
@@ -193,8 +192,8 @@
   for (auto& observer : observers_)
     observer.OnStartOver();
 
-  if (use_location_bar_bubble_) {
-    StartLocationBarBubbleRequest();
+  if (use_conditional_mediation_) {
+    StartConditionalMediationRequest();
     return;
   }
   current_mechanism_.reset();
@@ -365,7 +364,7 @@
 
 void AuthenticatorRequestDialogModel::Cancel() {
   if (is_request_complete()) {
-    if (use_location_bar_bubble_) {
+    if (use_conditional_mediation_) {
       // Conditional UI requests are never cancelled, they restart silently.
       StartOver();
       return;
@@ -450,7 +449,7 @@
 }
 
 void AuthenticatorRequestDialogModel::OnUserConsentDenied() {
-  if (use_location_bar_bubble_) {
+  if (use_conditional_mediation_) {
     // Do not show a page-modal retry error sheet if the user cancelled out of
     // their platform authenticator during a conditional UI request.
     // Instead, retry silently.
@@ -462,7 +461,7 @@
 
 bool AuthenticatorRequestDialogModel::OnWinUserCancelled() {
 #if BUILDFLAG(IS_WIN)
-  if (use_location_bar_bubble_) {
+  if (use_conditional_mediation_) {
     // Do not show a page-modal retry error sheet if the user cancelled out of
     // their platform authenticator during a conditional UI request.
     // Instead, retry silently.
@@ -729,7 +728,7 @@
 void AuthenticatorRequestDialogModel::GetCredentialListForConditionalUi(
     base::OnceCallback<void(
         const std::vector<device::DiscoverableCredentialMetadata>&)> callback) {
-  if (current_step() == Step::kLocationBarBubble) {
+  if (current_step() == Step::kConditionalMediation) {
     std::move(callback).Run(ephemeral_state_.creds_);
     return;
   }
@@ -902,7 +901,7 @@
   SetCurrentStep(Step::kCableActivate);
 }
 
-void AuthenticatorRequestDialogModel::StartLocationBarBubbleRequest() {
+void AuthenticatorRequestDialogModel::StartConditionalMediationRequest() {
   ephemeral_state_.creds_ = {};
   for (const auto& cred :
        transport_availability_.recognized_platform_authenticator_credentials) {
@@ -913,7 +912,7 @@
     std::move(conditional_ui_user_list_callback_).Run(ephemeral_state_.creds_);
   }
 
-  SetCurrentStep(Step::kLocationBarBubble);
+  SetCurrentStep(Step::kConditionalMediation);
 }
 
 void AuthenticatorRequestDialogModel::DispatchRequestAsync(
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h
index 195e96ffc..e62df6d 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.h
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -58,9 +58,9 @@
     // The UX flow has not started yet, the dialog should still be hidden.
     kNotStarted,
 
-    // A more subtle version of the dialog is being shown as an icon or bubble
-    // on the omnibox, prompting the user to tap their security key.
-    kLocationBarBubble,
+    // Conditionally mediated UI. No dialog is shown, instead credentials are
+    // offered to the user on the password autofill prompt.
+    kConditionalMediation,
 
     kMechanismSelection,
 
@@ -271,7 +271,7 @@
   bool should_dialog_be_closed() const {
     return current_step() == Step::kClosed ||
            current_step() == Step::kNotStarted ||
-           current_step() == Step::kLocationBarBubble;
+           current_step() == Step::kConditionalMediation;
   }
   const TransportAvailabilityInfo* transport_availability() const {
     return &transport_availability_;
@@ -640,7 +640,7 @@
   void ContactPhoneAfterOffTheRecordInterstitial(std::string name);
   void ContactPhoneAfterBleIsPowered(std::string name);
 
-  void StartLocationBarBubbleRequest();
+  void StartConditionalMediationRequest();
 
   void DispatchRequestAsync(AuthenticatorReference* authenticator);
   void DispatchRequestAsyncInternal(const std::string& authenticator_id);
@@ -719,7 +719,7 @@
 
   // True if this request should use the non-modal location bar bubble UI
   // instead of the page-modal, regular UI.
-  bool use_location_bar_bubble_ = false;
+  bool use_conditional_mediation_ = false;
 
   // offer_try_again_in_ui_ indicates whether a button to retry the request
   // should be included on the dialog sheet shown when encountering certain
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
index 83f06443..37995ba 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
@@ -738,7 +738,7 @@
                   /*use_location_bar_bubble=*/true,
                   /*prefer_native_api=*/false);
   task_environment_.FastForwardUntilNoTasksRemain();
-  EXPECT_EQ(model.current_step(), Step::kLocationBarBubble);
+  EXPECT_EQ(model.current_step(), Step::kConditionalMediation);
   EXPECT_TRUE(model.should_dialog_be_closed());
   EXPECT_EQ(preselect_num_called, 0);
   EXPECT_EQ(request_num_called, 0);
@@ -778,7 +778,7 @@
   model.StartFlow(std::move(transports_info),
                   /*is_location_bar_bubble_ui==*/true,
                   /*prefer_native_api=*/false);
-  EXPECT_EQ(model.current_step(), Step::kLocationBarBubble);
+  EXPECT_EQ(model.current_step(), Step::kConditionalMediation);
   EXPECT_TRUE(model.should_dialog_be_closed());
   EXPECT_EQ(request_num_called, 0);
 
@@ -803,7 +803,7 @@
   model.StartFlow(std::move(TransportAvailabilityInfo()),
                   /*is_location_bar_bubble_ui==*/true,
                   /*prefer_native_api=*/false);
-  EXPECT_EQ(model.current_step(), Step::kLocationBarBubble);
+  EXPECT_EQ(model.current_step(), Step::kConditionalMediation);
   testing::Mock::VerifyAndClearExpectations(&mock_observer);
 
   // Cancel an ongoing request. It should inform the observers to e.g. stop
@@ -819,7 +819,7 @@
   EXPECT_CALL(mock_observer, OnStepTransition()).Times(2);
   model.SetCurrentStepForTesting(Step::kKeyAlreadyRegistered);
   model.Cancel();
-  EXPECT_EQ(model.current_step(), Step::kLocationBarBubble);
+  EXPECT_EQ(model.current_step(), Step::kConditionalMediation);
   testing::Mock::VerifyAndClearExpectations(&mock_observer);
   model.RemoveObserver(&mock_observer);
 }
@@ -838,14 +838,14 @@
   model.StartFlow(std::move(TransportAvailabilityInfo()),
                   /*is_location_bar_bubble_ui==*/true,
                   /*prefer_native_api=*/false);
-  EXPECT_EQ(model.current_step(), Step::kLocationBarBubble);
+  EXPECT_EQ(model.current_step(), Step::kConditionalMediation);
   testing::Mock::VerifyAndClearExpectations(&mock_observer);
 
   // Simulate the Windows authenticator cancelling.
   EXPECT_CALL(mock_observer, OnStepTransition());
   EXPECT_CALL(mock_observer, OnStartOver());
   model.OnWinUserCancelled();
-  EXPECT_EQ(model.current_step(), Step::kLocationBarBubble);
+  EXPECT_EQ(model.current_step(), Step::kConditionalMediation);
   testing::Mock::VerifyAndClearExpectations(&mock_observer);
   model.RemoveObserver(&mock_observer);
 }
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
index a4c6d5c0..f3c1930 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
@@ -317,7 +317,7 @@
     delegate.OnTransportAvailabilityEnumerated(
         AuthenticatorRequestDialogModel::TransportAvailabilityInfo());
     EXPECT_EQ(observer.last_step() ==
-                  AuthenticatorRequestDialogModel::Step::kLocationBarBubble,
+                  AuthenticatorRequestDialogModel::Step::kConditionalMediation,
               conditional_ui);
   }
 }
diff --git a/chrome/browser/win/chrome_elf_init.cc b/chrome/browser/win/chrome_elf_init.cc
index 7912f16..b1e4e25 100644
--- a/chrome/browser/win/chrome_elf_init.cc
+++ b/chrome/browser/win/chrome_elf_init.cc
@@ -12,6 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/registry.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/chrome_elf/blocklist_constants.h"
 #include "chrome/chrome_elf/chrome_elf_constants.h"
 #include "chrome/chrome_elf/dll_hash/dll_hash.h"
 #include "chrome/chrome_elf/third_party_dlls/public_api.h"
diff --git a/chrome/browser/win/chrome_elf_init_unittest.cc b/chrome/browser/win/chrome_elf_init_unittest.cc
index 25490b3..7669384 100644
--- a/chrome/browser/win/chrome_elf_init_unittest.cc
+++ b/chrome/browser/win/chrome_elf_init_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_reg_util_win.h"
-#include "chrome/chrome_elf/chrome_elf_constants.h"
+#include "chrome/chrome_elf/blocklist_constants.h"
 #include "chrome/common/chrome_version.h"
 #include "chrome/install_static/install_util.h"
 #include "components/variations/variations_associated_data.h"
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 628a8f3..2aff2f3 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1655834389-f20efa6117f81ee2f688d344652a075890d6552b.profdata
+chrome-linux-main-1655963931-c53950cdc5f0508a8492d82a19851aafaac6cf34.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 0d70404..ffd41b2d 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1655769597-ae10f0ec5df82954086413e53f273131230c0485.profdata
+chrome-mac-arm-main-1655942370-df7c214c365345fc18f09b7c5d1d4ab82d674988.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 765190a..6b1cc593 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1655834389-8a8167b3e3797bddaeb706c6915cfcc104babd9d.profdata
+chrome-mac-main-1655963931-b95b773862f91fc6f82fefc825e8981a4781385c.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 1aaa7ef..b292b26 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1655844917-c51458a42e2b5fa0adfd893af29e66a60bc8a280.profdata
+chrome-win32-main-1655963931-d840b259996e03c76aa9f55097006e49466d872b.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 0d000c6..f7ee222 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1655844917-bba1c641be9afcf0b1904f78b08e448fa0413558.profdata
+chrome-win64-main-1655963931-b7530841a860b65374e86be09692a0d31dd19adf.profdata
diff --git a/chrome/chrome_elf/BUILD.gn b/chrome/chrome_elf/BUILD.gn
index 3fe0b9b7..da34cf9 100644
--- a/chrome/chrome_elf/BUILD.gn
+++ b/chrome/chrome_elf/BUILD.gn
@@ -97,6 +97,8 @@
 
 source_set("constants") {
   sources = [
+    "blocklist_constants.cc",
+    "blocklist_constants.h",
     "chrome_elf_constants.cc",
     "chrome_elf_constants.h",
   ]
diff --git a/chrome/chrome_elf/blocklist_constants.cc b/chrome/chrome_elf/blocklist_constants.cc
new file mode 100644
index 0000000..2406e3b
--- /dev/null
+++ b/chrome/chrome_elf/blocklist_constants.cc
@@ -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.
+
+#include "chrome/chrome_elf/blocklist_constants.h"
+
+namespace blocklist {
+
+const wchar_t kRegistryBeaconKeyName[] = L"\\BLBeacon";
+const wchar_t kBeaconVersion[] = L"version";
+const wchar_t kBeaconState[] = L"state";
+const wchar_t kBeaconAttemptCount[] = L"failed_count";
+
+const DWORD kBeaconMaxAttempts = 2;
+
+}  // namespace blocklist
diff --git a/chrome/chrome_elf/blocklist_constants.h b/chrome/chrome_elf/blocklist_constants.h
new file mode 100644
index 0000000..5f86439
--- /dev/null
+++ b/chrome/chrome_elf/blocklist_constants.h
@@ -0,0 +1,41 @@
+// 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 handful of blocklist constants related to the ChromeELF.
+
+#ifndef CHROME_CHROME_ELF_BLOCKLIST_CONSTANTS_H_
+#define CHROME_CHROME_ELF_BLOCKLIST_CONSTANTS_H_
+
+#include <windows.h>
+
+namespace blocklist {
+
+// The name of the blocklist beacon registry key.
+extern const wchar_t kRegistryBeaconKeyName[];
+
+// The properties for the blocklist beacon.
+extern const wchar_t kBeaconVersion[];
+extern const wchar_t kBeaconState[];
+extern const wchar_t kBeaconAttemptCount[];
+
+// The number of failures that can occur on startup with the beacon enabled
+// before we give up and turn off the blocklist.
+extern const DWORD kBeaconMaxAttempts;
+
+// The states for the blocklist setup code.
+enum BlocklistState {
+  BLOCKLIST_DISABLED = 0,
+  BLOCKLIST_ENABLED,
+  // The blocklist setup code is running. If this is the state at startup, it
+  // means the last setup crashed.
+  BLOCKLIST_SETUP_RUNNING,
+  // If the last setup crashed, we reassign the state to failed.
+  BLOCKLIST_SETUP_FAILED,
+  // Always keep this at the end.
+  BLOCKLIST_STATE_MAX,
+};
+
+}  // namespace blocklist
+
+#endif  // CHROME_CHROME_ELF_BLOCKLIST_CONSTANTS_H_
diff --git a/chrome/chrome_elf/chrome_elf_constants.cc b/chrome/chrome_elf/chrome_elf_constants.cc
index 0f720ac8..5762c98 100644
--- a/chrome/chrome_elf/chrome_elf_constants.cc
+++ b/chrome/chrome_elf/chrome_elf_constants.cc
@@ -4,17 +4,6 @@
 
 #include "chrome/chrome_elf/chrome_elf_constants.h"
 
-namespace blocklist {
-
-const wchar_t kRegistryBeaconKeyName[] = L"\\BLBeacon";
-const wchar_t kBeaconVersion[] = L"version";
-const wchar_t kBeaconState[] = L"state";
-const wchar_t kBeaconAttemptCount[] = L"failed_count";
-
-const DWORD kBeaconMaxAttempts = 2;
-
-}  // namespace blocklist
-
 namespace elf_sec {
 
 const wchar_t kRegBrowserExtensionPointKeyName[] =
diff --git a/chrome/chrome_elf/chrome_elf_constants.h b/chrome/chrome_elf/chrome_elf_constants.h
index c3e1311..d16ac7b3 100644
--- a/chrome/chrome_elf/chrome_elf_constants.h
+++ b/chrome/chrome_elf/chrome_elf_constants.h
@@ -7,37 +7,6 @@
 #ifndef CHROME_CHROME_ELF_CHROME_ELF_CONSTANTS_H_
 #define CHROME_CHROME_ELF_CHROME_ELF_CONSTANTS_H_
 
-#include <windows.h>
-
-namespace blocklist {
-
-// The name of the blocklist beacon registry key.
-extern const wchar_t kRegistryBeaconKeyName[];
-
-// The properties for the blocklist beacon.
-extern const wchar_t kBeaconVersion[];
-extern const wchar_t kBeaconState[];
-extern const wchar_t kBeaconAttemptCount[];
-
-// The number of failures that can occur on startup with the beacon enabled
-// before we give up and turn off the blocklist.
-extern const DWORD kBeaconMaxAttempts;
-
-// The states for the blocklist setup code.
-enum BlocklistState {
-  BLOCKLIST_DISABLED = 0,
-  BLOCKLIST_ENABLED,
-  // The blocklist setup code is running. If this is the state at startup, it
-  // means the last setup crashed.
-  BLOCKLIST_SETUP_RUNNING,
-  // If the last setup crashed, we reassign the state to failed.
-  BLOCKLIST_SETUP_FAILED,
-  // Always keep this at the end.
-  BLOCKLIST_STATE_MAX,
-};
-
-}  // namespace blocklist
-
 namespace elf_sec {
 
 // The name of the registry key which controls the enablement of
diff --git a/chrome/chrome_elf/third_party_dlls/DEPS b/chrome/chrome_elf/third_party_dlls/DEPS
index e8a67bd..be180529 100644
--- a/chrome/chrome_elf/third_party_dlls/DEPS
+++ b/chrome/chrome_elf/third_party_dlls/DEPS
@@ -4,7 +4,7 @@
   # Nothing from chrome except install_static and local includes.
   "-chrome",
   "+chrome/install_static",
-  "+chrome/chrome_elf/blacklist/blacklist.h",
+  "+chrome/chrome_elf/blocklist_constants.h",
   "+chrome/chrome_elf/chrome_elf_constants.h",
   "+chrome/chrome_elf/crash/crash_helper.h",
   "+chrome/chrome_elf/hook_util/hook_util.h",
diff --git a/chrome/chrome_elf/third_party_dlls/beacon.cc b/chrome/chrome_elf/third_party_dlls/beacon.cc
index 0970103..a540809 100644
--- a/chrome/chrome_elf/third_party_dlls/beacon.cc
+++ b/chrome/chrome_elf/third_party_dlls/beacon.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/chrome_elf/third_party_dlls/beacon.h"
 
-#include "chrome/chrome_elf/chrome_elf_constants.h"
+#include "chrome/chrome_elf/blocklist_constants.h"
 #include "chrome/chrome_elf/nt_registry/nt_registry.h"
 #include "chrome/install_static/install_util.h"
 
diff --git a/chrome/chrome_elf/third_party_dlls/beacon_unittest.cc b/chrome/chrome_elf/third_party_dlls/beacon_unittest.cc
index 4767087..a02995d 100644
--- a/chrome/chrome_elf/third_party_dlls/beacon_unittest.cc
+++ b/chrome/chrome_elf/third_party_dlls/beacon_unittest.cc
@@ -11,7 +11,7 @@
 
 #include "base/test/test_reg_util_win.h"
 #include "base/win/registry.h"
-#include "chrome/chrome_elf/chrome_elf_constants.h"
+#include "chrome/chrome_elf/blocklist_constants.h"
 #include "chrome/chrome_elf/nt_registry/nt_registry.h"
 #include "chrome/install_static/install_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index cf45f93..ed054dd 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -47,6 +47,7 @@
     "ENABLE_SUPERVISED_USERS=$enable_supervised_users",
     "ENABLE_SYSTEM_NOTIFICATIONS=$enable_system_notifications",
     "ENABLE_WAYLAND_SERVER=$enable_wayland_server",
+    "ENABLE_WEBUI_CERTIFICATE_VIEWER=$enable_webui_certificate_viewer",
     "ENABLE_WEBUI_TAB_STRIP=$enable_webui_tab_strip",
     "OPTIMIZE_WEBUI=$optimize_webui",
   ]
diff --git a/chrome/common/chromeos/extensions/api/diagnostics.idl b/chrome/common/chromeos/extensions/api/diagnostics.idl
index 2c80281..97135f9 100644
--- a/chrome/common/chromeos/extensions/api/diagnostics.idl
+++ b/chrome/common/chromeos/extensions/api/diagnostics.idl
@@ -5,7 +5,7 @@
 // Use the <code>chrome.os.diagnostics</code> API to run diagnostic routines.
 //
 // Many types defined here map with Mojo structs defined in
-// chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.
+// chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.
 [implemented_in = "chrome/browser/chromeos/extensions/telemetry/api/diagnostics_api.h"]
 namespace os.diagnostics {
   enum RoutineType {
diff --git a/chrome/common/extensions/api/file_manager_private.idl b/chrome/common/extensions/api/file_manager_private.idl
index 8047b47..dfdcf8a 100644
--- a/chrome/common/extensions/api/file_manager_private.idl
+++ b/chrome/common/extensions/api/file_manager_private.idl
@@ -359,8 +359,10 @@
 enum IOTaskType {
   copy,
   delete,
+  empty_trash,
   extract,
   move,
+  restore,
   trash,
   zip
 };
@@ -961,6 +963,9 @@
 
   // Password used for unpacking encrypted archives.
   DOMString? password;
+
+  // List of paths to restore trashed files to.
+  DOMString[]? restorePaths;
 };
 
 // IO Task Progress status, see file_manager::io_task::ProgressStatus.
diff --git a/chrome/common/extensions/api/file_manager_private_internal.idl b/chrome/common/extensions/api/file_manager_private_internal.idl
index 7ead75b..7fafca36 100644
--- a/chrome/common/extensions/api/file_manager_private_internal.idl
+++ b/chrome/common/extensions/api/file_manager_private_internal.idl
@@ -16,6 +16,7 @@
   dictionary IOTaskParams {
     DOMString? destinationFolderUrl;
     DOMString? password;
+    DOMString[]? restorePaths;
   };
 
   callback SimpleCallback = void();
diff --git a/chrome/common/features.gni b/chrome/common/features.gni
index f8f3fac0..1df3558 100644
--- a/chrome/common/features.gni
+++ b/chrome/common/features.gni
@@ -69,6 +69,9 @@
   # Indicates if Wayland display server support is enabled.
   enable_wayland_server = is_chromeos_ash
 
+  # Enables the webui certificate viewer dialog.
+  enable_webui_certificate_viewer = toolkit_views
+
   # optimize_webui was moved to ui/base/ui_features.gni
 }
 
@@ -91,6 +94,7 @@
   "enable_service_discovery=$enable_service_discovery",
   "enable_supervised_users=$enable_supervised_users",
   "enable_vr=$enable_vr",
+  "enable_webui_certificate_viewer=$enable_webui_certificate_viewer",
   "enable_webui_tab_strip=$enable_webui_tab_strip",
   "safe_browsing_mode=$safe_browsing_mode",
   "optimize_webui=$optimize_webui",
diff --git a/chrome/common/profiler/thread_profiler_browsertest.cc b/chrome/common/profiler/thread_profiler_browsertest.cc
index 4739bd1..7468fd2 100644
--- a/chrome/common/profiler/thread_profiler_browsertest.cc
+++ b/chrome/common/profiler/thread_profiler_browsertest.cc
@@ -158,12 +158,18 @@
 // These threads are not currently profiled on Android.
 #define MAYBE_BrowserProcessMainThread DISABLED_BrowserProcessMainThread
 #define MAYBE_BrowserProcessIOThread DISABLED_BrowserProcessIOThread
+#define MAYBE_GpuProcessMainThread DISABLED_GpuProcessMainThread
+#define MAYBE_GpuProcessIOThread DISABLED_GpuProcessIOThread
+#define MAYBE_GpuProcessCompositorThread DISABLED_GpuProcessCompositorThread
 // Android doesn't have a network service process.
 #define MAYBE_NetworkServiceProcessIOThread \
   DISABLED_NetworkServiceProcessIOThread
 #else
 #define MAYBE_BrowserProcessMainThread BrowserProcessMainThread
 #define MAYBE_BrowserProcessIOThread BrowserProcessIOThread
+#define MAYBE_GpuProcessMainThread GpuProcessMainThread
+#define MAYBE_GpuProcessIOThread GpuProcessIOThread
+#define MAYBE_GpuProcessCompositorThread GpuProcessCompositorThread
 #define MAYBE_NetworkServiceProcessIOThread NetworkServiceProcessIOThread
 #endif
 
@@ -183,17 +189,18 @@
                              metrics::BROWSER_PROCESS, metrics::IO_THREAD));
 }
 
-IN_PROC_BROWSER_TEST_F(ThreadProfilerBrowserTest, GpuProcessMainThread) {
+IN_PROC_BROWSER_TEST_F(ThreadProfilerBrowserTest, MAYBE_GpuProcessMainThread) {
   EXPECT_TRUE(WaitForProfile(metrics::SampledProfile::PROCESS_STARTUP,
                              metrics::GPU_PROCESS, metrics::MAIN_THREAD));
 }
 
-IN_PROC_BROWSER_TEST_F(ThreadProfilerBrowserTest, GpuProcessIOThread) {
+IN_PROC_BROWSER_TEST_F(ThreadProfilerBrowserTest, MAYBE_GpuProcessIOThread) {
   EXPECT_TRUE(WaitForProfile(metrics::SampledProfile::PROCESS_STARTUP,
                              metrics::GPU_PROCESS, metrics::IO_THREAD));
 }
 
-IN_PROC_BROWSER_TEST_F(ThreadProfilerBrowserTest, GpuProcessCompositorThread) {
+IN_PROC_BROWSER_TEST_F(ThreadProfilerBrowserTest,
+                       MAYBE_GpuProcessCompositorThread) {
   EXPECT_TRUE(WaitForProfile(metrics::SampledProfile::PROCESS_STARTUP,
                              metrics::GPU_PROCESS, metrics::COMPOSITOR_THREAD));
 }
diff --git a/chrome/common/profiler/thread_profiler_platform_configuration.cc b/chrome/common/profiler/thread_profiler_platform_configuration.cc
index d680a29..24c867d 100644
--- a/chrome/common/profiler/thread_profiler_platform_configuration.cc
+++ b/chrome/common/profiler/thread_profiler_platform_configuration.cc
@@ -214,7 +214,7 @@
       // http://uma/p/chrome/timeline_v2?sid=39bc30a43a01d045204d0add05ad120a
       return 0.75;
 
-    case metrics::CallStackProfileParams::Process::kGpu:
+    case metrics::CallStackProfileParams::Process::kUtility:
       return 1.0;
 
     default:
@@ -228,7 +228,7 @@
   // TODO(https://crbug.com/1326430): Enable for all the default processes.
   switch (process) {
     case metrics::CallStackProfileParams::Process::kRenderer:
-    case metrics::CallStackProfileParams::Process::kGpu:
+    case metrics::CallStackProfileParams::Process::kUtility:
       return true;
 
     default:
diff --git a/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc b/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc
index 868d56b..da2391e8 100644
--- a/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc
+++ b/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc
@@ -151,14 +151,14 @@
 MAYBE_PLATFORM_CONFIG_TEST_F(ThreadProfilerPlatformConfigurationTest,
                              GetChildProcessEnableFraction) {
 #if BUILDFLAG(IS_ANDROID)
+  EXPECT_EQ(0.0, config()->GetChildProcessEnableFraction(
+                     metrics::CallStackProfileParams::Process::kGpu));
   EXPECT_EQ(0.75, config()->GetChildProcessEnableFraction(
                       metrics::CallStackProfileParams::Process::kRenderer));
-  EXPECT_EQ(1.0, config()->GetChildProcessEnableFraction(
-                     metrics::CallStackProfileParams::Process::kGpu));
   EXPECT_EQ(0.0,
             config()->GetChildProcessEnableFraction(
                 metrics::CallStackProfileParams::Process::kNetworkService));
-  EXPECT_EQ(0.0, config()->GetChildProcessEnableFraction(
+  EXPECT_EQ(1.0, config()->GetChildProcessEnableFraction(
                      metrics::CallStackProfileParams::Process::kUtility));
   EXPECT_EQ(0.0, config()->GetChildProcessEnableFraction(
                      metrics::CallStackProfileParams::Process::kUnknown));
@@ -187,13 +187,13 @@
       metrics::CallStackProfileParams::Process::kBrowser,
       metrics::CallStackProfileParams::Thread::kIo));
 
-  EXPECT_TRUE(config()->IsEnabledForThread(
+  EXPECT_FALSE(config()->IsEnabledForThread(
       metrics::CallStackProfileParams::Process::kGpu,
       metrics::CallStackProfileParams::Thread::kMain));
-  EXPECT_TRUE(config()->IsEnabledForThread(
+  EXPECT_FALSE(config()->IsEnabledForThread(
       metrics::CallStackProfileParams::Process::kGpu,
       metrics::CallStackProfileParams::Thread::kIo));
-  EXPECT_TRUE(config()->IsEnabledForThread(
+  EXPECT_FALSE(config()->IsEnabledForThread(
       metrics::CallStackProfileParams::Process::kGpu,
       metrics::CallStackProfileParams::Thread::kCompositor));
 
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 06e7985..382d9c5 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -774,6 +774,7 @@
     blink::kChromeUIMemoryPressureModerateURL,
 #if BUILDFLAG(IS_WIN)
     blink::kChromeUIBrowserHeapCorruptionURL,
+    blink::kChromeUICfgViolationCrashURL,
     blink::kChromeUIHeapCorruptionCrashURL,
 #endif
 #if BUILDFLAG(IS_ANDROID)
diff --git a/chrome/elevation_service/BUILD.gn b/chrome/elevation_service/BUILD.gn
index d94e9b4..97f31190 100644
--- a/chrome/elevation_service/BUILD.gn
+++ b/chrome/elevation_service/BUILD.gn
@@ -59,6 +59,14 @@
   ]
 }
 
+source_set("public_headers") {
+  sources = [ "elevator.h" ]
+
+  deps = [ "//base" ]
+
+  public_deps = [ ":elevation_service_idl" ]
+}
+
 source_set("lib") {
   visibility = [ ":*" ]
 
@@ -68,7 +76,6 @@
     "elevated_recovery_impl.cc",
     "elevated_recovery_impl.h",
     "elevator.cc",
-    "elevator.h",
     "service_main.cc",
     "service_main.h",
   ]
@@ -78,12 +85,14 @@
   configs += [ ":winver" ]
 
   deps = [
-    ":elevation_service_idl",
     "//base",
     "//chrome/install_static:install_static_util",
     "//components/crx_file:crx_file",
     "//third_party/zlib/google:zip",
   ]
+
+  public_deps = [ ":public_headers" ]
+
   libs = [
     "crypt32.lib",
     "rpcrt4.lib",
diff --git a/chrome/elevation_service/elevator.h b/chrome/elevation_service/elevator.h
index 9c2a711..8ef5a2e 100644
--- a/chrome/elevation_service/elevator.h
+++ b/chrome/elevation_service/elevator.h
@@ -13,10 +13,22 @@
 #include <wrl/module.h>
 
 #include "base/gtest_prod_util.h"
+#include "base/win/windows_types.h"
 #include "chrome/elevation_service/elevation_service_idl.h"
 
 namespace elevation_service {
 
+constexpr IID kTestElevatorClsid = {
+    0x416C51AC,
+    0x4DEF,
+    0x43CA,
+    {0xE7, 0x35, 0xE7, 0x35, 0x21, 0x0A, 0xB2,
+     0x57}};  // Elevator Test CLSID. {416C51AC-4DEF-43CA-96E8-E735210AB257}
+
+namespace switches {
+constexpr char kElevatorClsIdForTestingSwitch[] = "elevator-clsid-for-testing";
+}  // namespace switches
+
 class Elevator
     : public Microsoft::WRL::RuntimeClass<
           Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
diff --git a/chrome/elevation_service/service_main.cc b/chrome/elevation_service/service_main.cc
index 599cabb8..ffc1296 100644
--- a/chrome/elevation_service/service_main.cc
+++ b/chrome/elevation_service/service_main.cc
@@ -95,6 +95,11 @@
                 "Arrays cookies_ and class_factories must be the same size.");
 
   IID class_ids[] = {install_static::GetElevatorClsid()};
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kElevatorClsIdForTestingSwitch)) {
+    class_ids[0] = {kTestElevatorClsid};
+  }
+
   DCHECK_EQ(std::size(cookies_), std::size(class_ids));
   static_assert(std::extent<decltype(cookies_)>() == std::size(class_ids),
                 "Arrays cookies_ and class_ids must be the same size.");
diff --git a/chrome/installer/setup/DEPS b/chrome/installer/setup/DEPS
index d9111420..706c796 100644
--- a/chrome/installer/setup/DEPS
+++ b/chrome/installer/setup/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h",
   "+chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.h",
+  "+chrome/chrome_elf/blocklist_constants.h",
   "+chrome/chrome_elf/chrome_elf_constants.h",
   "+chrome/install_static",
   "+components/base32",
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 56768b934..db6e49a 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -30,7 +30,7 @@
 #include "base/win/registry.h"
 #include "base/win/shortcut.h"
 #include "build/branding_buildflags.h"
-#include "chrome/chrome_elf/chrome_elf_constants.h"
+#include "chrome/chrome_elf/blocklist_constants.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_result_codes.h"
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 469ea67..3bf8e2e0 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -380,6 +380,8 @@
 
   if (!is_android) {
     sources += [
+      "accessibility/read_anything_app_controller.cc",
+      "accessibility/read_anything_app_controller.h",
       "media/chrome_speech_recognition_client.cc",
       "media/chrome_speech_recognition_client.h",
       "searchbox/searchbox.cc",
diff --git a/chrome/renderer/accessibility/OWNERS b/chrome/renderer/accessibility/OWNERS
new file mode 100644
index 0000000..976b955
--- /dev/null
+++ b/chrome/renderer/accessibility/OWNERS
@@ -0,0 +1 @@
+file://ui/accessibility/OWNERS
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc
new file mode 100644
index 0000000..6092174
--- /dev/null
+++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -0,0 +1,188 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/accessibility/read_anything_app_controller.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/notreached.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/renderer/chrome_object_extensions_utils.h"
+#include "content/public/renderer/render_frame.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/web/blink.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_script_source.h"
+#include "ui/accessibility/ax_node.h"
+#include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_tree.h"
+#include "ui/accessibility/ax_tree_update.h"
+#include "v8/include/v8-context.h"
+#include "v8/include/v8-microtask-queue.h"
+
+// static
+gin::WrapperInfo ReadAnythingAppController::kWrapperInfo = {
+    gin::kEmbedderNativeGin};
+
+// static
+ReadAnythingAppController* ReadAnythingAppController::Install(
+    content::RenderFrame* render_frame) {
+  v8::Isolate* isolate = blink::MainThreadIsolate();
+  v8::MicrotasksScope microtask_scope(isolate,
+                                      v8::MicrotasksScope::kDoNotRunMicrotasks);
+  v8::HandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context =
+      render_frame->GetWebFrame()->MainWorldScriptContext();
+  if (context.IsEmpty())
+    return nullptr;
+
+  v8::Context::Scope context_scope(context);
+
+  ReadAnythingAppController* controller =
+      new ReadAnythingAppController(render_frame);
+  gin::Handle<ReadAnythingAppController> handle =
+      gin::CreateHandle(isolate, controller);
+  if (handle.IsEmpty())
+    return nullptr;
+
+  v8::Local<v8::Object> chrome =
+      content::GetOrCreateChromeObject(isolate, context);
+  chrome->Set(context, gin::StringToV8(isolate, "readAnything"), handle.ToV8())
+      .Check();
+  return controller;
+}
+
+ReadAnythingAppController::ReadAnythingAppController(
+    content::RenderFrame* render_frame)
+    : render_frame_(render_frame) {}
+
+ReadAnythingAppController::~ReadAnythingAppController() = default;
+
+void ReadAnythingAppController::OnAXTreeDistilled(
+    const ui::AXTreeUpdate& snapshot,
+    const std::vector<ui::AXNodeID>& content_node_ids) {
+  content_node_ids_ = content_node_ids;
+  tree_ = std::make_unique<ui::AXTree>();
+
+  // Unserialize the snapshot. Failure to unserialize doesn't result in a crash:
+  // we control both ends of the serialization-unserialization so any failures
+  // are programming error.
+  if (!tree_->Unserialize(snapshot))
+    NOTREACHED() << tree_->error();
+
+  // TODO(abigailbklein): Use v8::Function rather than javascript. If possible,
+  // replace this function call with firing an event.
+  std::string script = "chrome.readAnything.updateContent();";
+  render_frame_->ExecuteJavaScript(base::ASCIIToUTF16(script));
+}
+
+void ReadAnythingAppController::OnFontNameChange(
+    const std::string& new_font_name) {
+  font_name_ = new_font_name;
+  // TODO(abigailbklein): Use v8::Function rather than javascript. If possible,
+  // replace this function call with firing an event.
+  std::string script = "chrome.readAnything.updateFontName();";
+  render_frame_->ExecuteJavaScript(base::ASCIIToUTF16(script));
+}
+
+gin::ObjectTemplateBuilder ReadAnythingAppController::GetObjectTemplateBuilder(
+    v8::Isolate* isolate) {
+  return gin::Wrappable<ReadAnythingAppController>::GetObjectTemplateBuilder(
+             isolate)
+      .SetProperty("contentNodeIds", &ReadAnythingAppController::ContentNodeIds)
+      .SetProperty("fontName", &ReadAnythingAppController::FontName)
+      .SetMethod("getChildren", &ReadAnythingAppController::GetChildren)
+      .SetMethod("getHeadingLevel", &ReadAnythingAppController::GetHeadingLevel)
+      .SetMethod("getTextContent", &ReadAnythingAppController::GetTextContent)
+      .SetMethod("getUrl", &ReadAnythingAppController::GetUrl)
+      .SetMethod("isHeading", &ReadAnythingAppController::IsHeading)
+      .SetMethod("isLink", &ReadAnythingAppController::IsLink)
+      .SetMethod("isParagraph", &ReadAnythingAppController::IsParagraph)
+      .SetMethod("isStaticText", &ReadAnythingAppController::IsStaticText)
+      .SetMethod("onConnected", &ReadAnythingAppController::OnConnected);
+}
+
+std::vector<ui::AXNodeID> ReadAnythingAppController::ContentNodeIds() {
+  return content_node_ids_;
+}
+
+std::string ReadAnythingAppController::FontName() {
+  return font_name_;
+}
+
+std::vector<ui::AXNodeID> ReadAnythingAppController::GetChildren(
+    ui::AXNodeID ax_node_id) {
+  std::vector<ui::AXNodeID> child_ids;
+  ui::AXNode* ax_node = GetAXNode(ax_node_id);
+  if (!ax_node)
+    return std::vector<ui::AXNodeID>();
+  for (auto it = ax_node->UnignoredChildrenBegin();
+       it != ax_node->UnignoredChildrenEnd(); ++it) {
+    child_ids.push_back(it->id());
+  }
+  return child_ids;
+}
+
+uint32_t ReadAnythingAppController::GetHeadingLevel(ui::AXNodeID ax_node_id) {
+  ui::AXNode* ax_node = GetAXNode(ax_node_id);
+  if (!ax_node)
+    return -1;
+  return ax_node->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel);
+}
+
+std::string ReadAnythingAppController::GetTextContent(ui::AXNodeID ax_node_id) {
+  ui::AXNode* ax_node = GetAXNode(ax_node_id);
+  if (!ax_node)
+    return std::string();
+  return ax_node->GetTextContentUTF8();
+}
+
+std::string ReadAnythingAppController::GetUrl(ui::AXNodeID ax_node_id) {
+  ui::AXNode* ax_node = GetAXNode(ax_node_id);
+  if (!ax_node)
+    return std::string();
+  return ax_node->GetStringAttribute(ax::mojom::StringAttribute::kUrl);
+}
+
+bool ReadAnythingAppController::IsHeading(ui::AXNodeID ax_node_id) {
+  ui::AXNode* ax_node = GetAXNode(ax_node_id);
+  if (!ax_node)
+    return false;
+  return ui::IsHeading(ax_node->GetRole());
+}
+
+bool ReadAnythingAppController::IsLink(ui::AXNodeID ax_node_id) {
+  ui::AXNode* ax_node = GetAXNode(ax_node_id);
+  if (!ax_node)
+    return false;
+  return ui::IsLink(ax_node->GetRole());
+}
+
+bool ReadAnythingAppController::IsParagraph(ui::AXNodeID ax_node_id) {
+  ui::AXNode* ax_node = GetAXNode(ax_node_id);
+  if (!ax_node)
+    return false;
+  return ax_node->GetRole() == ax::mojom::Role::kParagraph;
+}
+
+bool ReadAnythingAppController::IsStaticText(ui::AXNodeID ax_node_id) {
+  ui::AXNode* ax_node = GetAXNode(ax_node_id);
+  if (!ax_node)
+    return false;
+  return ax_node->GetRole() == ax::mojom::Role::kStaticText;
+}
+
+void ReadAnythingAppController::OnConnected() {
+  // TODO(abigailbklein): Connect via mojo to browser.
+}
+
+ui::AXNode* ReadAnythingAppController::GetAXNode(ui::AXNodeID ax_node_id) {
+  if (!tree_)
+    return nullptr;
+  return tree_->GetFromId(ax_node_id);
+}
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.h b/chrome/renderer/accessibility/read_anything_app_controller.h
new file mode 100644
index 0000000..3abd4f8
--- /dev/null
+++ b/chrome/renderer/accessibility/read_anything_app_controller.h
@@ -0,0 +1,91 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_ACCESSIBILITY_READ_ANYTHING_APP_CONTROLLER_H_
+#define CHROME_RENDERER_ACCESSIBILITY_READ_ANYTHING_APP_CONTROLLER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "gin/wrappable.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "ui/accessibility/ax_node_id_forward.h"
+#include "ui/accessibility/ax_tree_update_forward.h"
+
+namespace content {
+class RenderFrame;
+}  // namespace content
+
+namespace ui {
+class AXNode;
+class AXTree;
+}  // namespace ui
+
+class ReadAnythingAppControllerTest;
+
+///////////////////////////////////////////////////////////////////////////////
+// ReadAnythingAppController
+//
+//  A class that controls the Read Anything WebUI app. It serves two purposes:
+//  1. Communicate with ReadAnythingPageHandler (written in c++) via mojom.
+//  2. Communicate with ReadAnythingApp (written in ts) via gin bindings.
+//  The ReadAnythingAppController unserializes the AXTreeUpdate and exposes
+//  methods on it to the ts resource for accessing information about the AXTree.
+//  This class is owned by the ChromeRenderFrameObserver and has the same
+//  lifetime as the render frame.
+//
+class ReadAnythingAppController
+    : public gin::Wrappable<ReadAnythingAppController> {
+ public:
+  static gin::WrapperInfo kWrapperInfo;
+
+  ReadAnythingAppController(const ReadAnythingAppController&) = delete;
+  ReadAnythingAppController& operator=(const ReadAnythingAppController&) =
+      delete;
+
+  // Installs v8 context for Read Anything and adds chrome.readAnything binding
+  // to page.
+  static ReadAnythingAppController* Install(content::RenderFrame* render_frame);
+
+ private:
+  friend ReadAnythingAppControllerTest;
+
+  explicit ReadAnythingAppController(content::RenderFrame* render_frame);
+  ~ReadAnythingAppController() override;
+
+  // gin::WrappableBase:
+  gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+      v8::Isolate* isolate) override;
+
+  // TODO(abigailbklein): Add these methods to read_anything::mojom::Page.
+  void OnAXTreeDistilled(const ui::AXTreeUpdate& snapshot,
+                         const std::vector<ui::AXNodeID>& content_node_ids);
+  void OnFontNameChange(const std::string& new_font_name);
+
+  // gin templates:
+  std::vector<ui::AXNodeID> ContentNodeIds();
+  std::string FontName();
+  std::vector<ui::AXNodeID> GetChildren(ui::AXNodeID ax_node_id);
+  uint32_t GetHeadingLevel(ui::AXNodeID ax_node_id);
+  std::string GetTextContent(ui::AXNodeID ax_node_id);
+  std::string GetUrl(ui::AXNodeID ax_node_id);
+  bool IsHeading(ui::AXNodeID ax_node_id);
+  bool IsLink(ui::AXNodeID ax_node_id);
+  bool IsParagraph(ui::AXNodeID ax_node_id);
+  bool IsStaticText(ui::AXNodeID ax_node_id);
+  void OnConnected();
+
+  ui::AXNode* GetAXNode(ui::AXNodeID ax_node_id);
+
+  content::RenderFrame* render_frame_;
+
+  // State
+  std::unique_ptr<ui::AXTree> tree_;
+  std::vector<ui::AXNodeID> content_node_ids_;
+  std::string font_name_;
+};
+
+#endif  // CHROME_RENDERER_ACCESSIBILITY_READ_ANYTHING_APP_CONTROLLER_H_
diff --git a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
new file mode 100644
index 0000000..e5b94b99
--- /dev/null
+++ b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
@@ -0,0 +1,209 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/accessibility/read_anything_app_controller.h"
+
+#include <string>
+#include <vector>
+
+#include "chrome/test/base/chrome_render_view_test.h"
+#include "content/public/renderer/render_frame.h"
+
+class ReadAnythingAppControllerTest : public ChromeRenderViewTest {
+ public:
+  ReadAnythingAppControllerTest() = default;
+  ~ReadAnythingAppControllerTest() override = default;
+  ReadAnythingAppControllerTest(const ReadAnythingAppControllerTest&) = delete;
+  ReadAnythingAppControllerTest& operator=(
+      const ReadAnythingAppControllerTest&) = delete;
+
+  void SetUp() override {
+    ChromeRenderViewTest::SetUp();
+    content::RenderFrame* render_frame =
+        content::RenderFrame::FromWebFrame(GetMainFrame());
+    controller_ = ReadAnythingAppController::Install(render_frame);
+
+    // Create simple AXTreeUpdate with a root node and 3 children.
+    basic_snapshot_.root_id = 1;
+    basic_snapshot_.nodes.resize(4);
+    basic_snapshot_.nodes[0].id = 1;
+    basic_snapshot_.nodes[0].child_ids = {2, 3, 4};
+    basic_snapshot_.nodes[1].id = 2;
+    basic_snapshot_.nodes[2].id = 3;
+    basic_snapshot_.nodes[3].id = 4;
+  }
+
+  void OnFontNameChange(const std::string& new_font_name) {
+    controller_->OnFontNameChange(new_font_name);
+  }
+
+  void OnAXTreeDistilled(const ui::AXTreeUpdate& snapshot,
+                         const std::vector<ui::AXNodeID>& content_node_ids) {
+    controller_->OnAXTreeDistilled(snapshot, content_node_ids);
+  }
+
+  std::vector<ui::AXNodeID> ContentNodeIds() {
+    return controller_->ContentNodeIds();
+  }
+
+  std::string FontName() { return controller_->FontName(); }
+
+  std::vector<ui::AXNodeID> GetChildren(ui::AXNodeID ax_node_id) {
+    return controller_->GetChildren(ax_node_id);
+  }
+
+  uint32_t GetHeadingLevel(ui::AXNodeID ax_node_id) {
+    return controller_->GetHeadingLevel(ax_node_id);
+  }
+
+  std::string GetTextContent(ui::AXNodeID ax_node_id) {
+    return controller_->GetTextContent(ax_node_id);
+  }
+
+  std::string GetUrl(ui::AXNodeID ax_node_id) {
+    return controller_->GetUrl(ax_node_id);
+  }
+
+  bool IsHeading(ui::AXNodeID ax_node_id) {
+    return controller_->IsHeading(ax_node_id);
+  }
+
+  bool IsLink(ui::AXNodeID ax_node_id) {
+    return controller_->IsLink(ax_node_id);
+  }
+
+  bool IsParagraph(ui::AXNodeID ax_node_id) {
+    return controller_->IsParagraph(ax_node_id);
+  }
+
+  bool IsStaticText(ui::AXNodeID ax_node_id) {
+    return controller_->IsStaticText(ax_node_id);
+  }
+
+  ui::AXTreeUpdate basic_snapshot_;
+
+ private:
+  // ReadAnythingAppController constructor and destructor are private so it's
+  // not accessible by std::make_unique.
+  ReadAnythingAppController* controller_ = nullptr;
+};
+
+TEST_F(ReadAnythingAppControllerTest, FontName) {
+  std::string font_name = "Roboto";
+  OnFontNameChange(font_name);
+  EXPECT_EQ(font_name, FontName());
+}
+
+TEST_F(ReadAnythingAppControllerTest, ContentNodeIds) {
+  std::vector<ui::AXNodeID> content_node_ids = {2, 4};
+  OnAXTreeDistilled(basic_snapshot_, content_node_ids);
+  EXPECT_EQ(content_node_ids.size(), ContentNodeIds().size());
+  for (size_t i = 0; i < content_node_ids.size(); i++) {
+    EXPECT_EQ(content_node_ids[i], ContentNodeIds()[i]);
+  }
+}
+
+TEST_F(ReadAnythingAppControllerTest, GetChildren) {
+  basic_snapshot_.nodes[2].role = ax::mojom::Role::kNone;
+  OnAXTreeDistilled(basic_snapshot_, {});
+  EXPECT_EQ(2u, GetChildren(1).size());
+  EXPECT_EQ(0u, GetChildren(2).size());
+  EXPECT_EQ(0u, GetChildren(3).size());
+  EXPECT_EQ(0u, GetChildren(4).size());
+
+  EXPECT_EQ(2, GetChildren(1)[0]);
+  EXPECT_EQ(4, GetChildren(1)[1]);
+}
+
+TEST_F(ReadAnythingAppControllerTest, GetHeadingLevel) {
+  uint32_t heading_level = 3;
+  basic_snapshot_.nodes[1].role = ax::mojom::Role::kHeading;
+  basic_snapshot_.nodes[1].AddIntAttribute(
+      ax::mojom::IntAttribute::kHierarchicalLevel, heading_level);
+  OnAXTreeDistilled(basic_snapshot_, {});
+  EXPECT_EQ(heading_level, GetHeadingLevel(2));
+}
+
+TEST_F(ReadAnythingAppControllerTest, GetTextContent) {
+  std::string text_content = "Hello";
+  std::string missing_text_content = "";
+  std::string more_text_content = " world";
+  basic_snapshot_.nodes[1].SetName(text_content);
+  basic_snapshot_.nodes[1].SetNameFrom(ax::mojom::NameFrom::kContents);
+  basic_snapshot_.nodes[2].SetName(missing_text_content);
+  basic_snapshot_.nodes[2].SetNameFrom(ax::mojom::NameFrom::kContents);
+  basic_snapshot_.nodes[3].SetName(more_text_content);
+  basic_snapshot_.nodes[3].SetNameFrom(ax::mojom::NameFrom::kContents);
+  OnAXTreeDistilled(basic_snapshot_, {});
+  EXPECT_EQ("Hello world", GetTextContent(1));
+  EXPECT_EQ(text_content, GetTextContent(2));
+  EXPECT_EQ(missing_text_content, GetTextContent(3));
+  EXPECT_EQ(more_text_content, GetTextContent(4));
+}
+
+TEST_F(ReadAnythingAppControllerTest, GetUrl) {
+  std::string url = "http://www.google.com";
+  std::string invalid_url = "cats";
+  std::string missing_url = "";
+  basic_snapshot_.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kUrl,
+                                              url);
+  basic_snapshot_.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kUrl,
+                                              invalid_url);
+  basic_snapshot_.nodes[3].AddStringAttribute(ax::mojom::StringAttribute::kUrl,
+                                              missing_url);
+  OnAXTreeDistilled(basic_snapshot_, {});
+  EXPECT_EQ(url, GetUrl(2));
+  EXPECT_EQ(invalid_url, GetUrl(3));
+  EXPECT_EQ(missing_url, GetUrl(4));
+}
+
+TEST_F(ReadAnythingAppControllerTest, IsHeading) {
+  basic_snapshot_.nodes[1].role = ax::mojom::Role::kHeading;
+  basic_snapshot_.nodes[2].role = ax::mojom::Role::kDocSubtitle;
+  basic_snapshot_.nodes[3].role = ax::mojom::Role::kLink;
+  OnAXTreeDistilled(basic_snapshot_, {});
+  EXPECT_TRUE(IsHeading(2));
+  EXPECT_TRUE(IsHeading(3));
+  EXPECT_FALSE(IsHeading(4));
+}
+
+TEST_F(ReadAnythingAppControllerTest, IsLink) {
+  basic_snapshot_.nodes.resize(7);
+  for (int i = 4; i < 7; i++) {
+    basic_snapshot_.nodes[0].child_ids.push_back(i + 1);
+    basic_snapshot_.nodes[i].id = i + 1;
+  }
+
+  basic_snapshot_.nodes[1].role = ax::mojom::Role::kDocBackLink;
+  basic_snapshot_.nodes[2].role = ax::mojom::Role::kDocBiblioRef;
+  basic_snapshot_.nodes[3].role = ax::mojom::Role::kDocGlossRef;
+  basic_snapshot_.nodes[4].role = ax::mojom::Role::kDocNoteRef;
+  basic_snapshot_.nodes[5].role = ax::mojom::Role::kLink;
+  basic_snapshot_.nodes[6].role = ax::mojom::Role::kParagraph;
+  OnAXTreeDistilled(basic_snapshot_, {});
+  EXPECT_TRUE(IsLink(2));
+  EXPECT_TRUE(IsLink(3));
+  EXPECT_TRUE(IsLink(4));
+  EXPECT_TRUE(IsLink(5));
+  EXPECT_TRUE(IsLink(6));
+  EXPECT_FALSE(IsLink(7));
+}
+
+TEST_F(ReadAnythingAppControllerTest, IsParagraph) {
+  basic_snapshot_.nodes[1].role = ax::mojom::Role::kParagraph;
+  basic_snapshot_.nodes[2].role = ax::mojom::Role::kListBox;
+  OnAXTreeDistilled(basic_snapshot_, {});
+  EXPECT_TRUE(IsParagraph(2));
+  EXPECT_FALSE(IsParagraph(3));
+}
+
+TEST_F(ReadAnythingAppControllerTest, IsStaticText) {
+  basic_snapshot_.nodes[1].role = ax::mojom::Role::kStaticText;
+  basic_snapshot_.nodes[2].role = ax::mojom::Role::kInlineTextBox;
+  basic_snapshot_.nodes[3].role = ax::mojom::Role::kLabelText;
+  OnAXTreeDistilled(basic_snapshot_, {});
+  EXPECT_TRUE(IsStaticText(2));
+  EXPECT_FALSE(IsStaticText(3));
+  EXPECT_FALSE(IsStaticText(4));
+}
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc
index d75d567..dfc5243 100644
--- a/chrome/renderer/chrome_render_frame_observer.cc
+++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -64,7 +64,9 @@
 #include "url/gurl.h"
 
 #if !BUILDFLAG(IS_ANDROID)
+#include "chrome/renderer/accessibility/read_anything_app_controller.h"
 #include "chrome/renderer/searchbox/searchbox_extension.h"
+#include "ui/accessibility/accessibility_features.h"
 #endif  // !BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
@@ -315,6 +317,16 @@
       *base::CommandLine::ForCurrentProcess();
   if (command_line.HasSwitch(switches::kInstantProcess))
     SearchBoxExtension::Install(render_frame()->GetWebFrame());
+
+  // Install ReadAnythingAppController on render frames belonging to a WebUIs.
+  // ReadAnythingAppController installs v8 bindings in the chrome.readAnything
+  // namespace which are consumed by read_anything/app.ts, the resource of the
+  // Read Anything WebUI.
+  if (features::IsReadAnythingEnabled() &&
+      render_frame()->GetEnabledBindings() &
+          content::kWebUIBindingsPolicyMask) {
+    ReadAnythingAppController::Install(render_frame());
+  }
 #endif  // !BUILDFLAG(IS_ANDROID)
 }
 
diff --git a/chrome/renderer/resources/extensions/file_manager_private_custom_bindings.js b/chrome/renderer/resources/extensions/file_manager_private_custom_bindings.js
index 24f8f72..44119d1 100644
--- a/chrome/renderer/resources/extensions/file_manager_private_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/file_manager_private_custom_bindings.js
@@ -385,6 +385,9 @@
         if (params.password) {
           newParams.password = params.password;
         }
+        if (params.restorePaths) {
+          newParams.restorePaths = params.restorePaths;
+        }
         fileManagerPrivateInternal.startIOTask(type, urls, newParams, callback);
       });
 });
diff --git a/chrome/services/speech/soda/soda_client.cc b/chrome/services/speech/soda/soda_client.cc
index 97e503b..e4c09ba 100644
--- a/chrome/services/speech/soda/soda_client.cc
+++ b/chrome/services/speech/soda/soda_client.cc
@@ -11,7 +11,6 @@
 #include "build/build_config.h"
 
 #if BUILDFLAG(IS_MAC)
-#include "base/debug/dump_without_crashing.h"
 #include "base/mac/mac_util.h"
 #endif
 
@@ -63,15 +62,6 @@
                              lib_.GetError()->code);
   }
 #endif  // BUILDFLAG(IS_WIN)
-
-#if BUILDFLAG(IS_MAC)
-  if (load_soda_result_ == LoadSodaResultValue::kBinaryInvalid) {
-    base::UmaHistogramSparse(
-        "Accessibility.LiveCaption.LoadSodaErrorMacOsVersion",
-        base::mac::internal::MacOSVersion());
-    base::debug::DumpWithoutCrashing();
-  }
-#endif  // BUILDFLAG(IS_MAC)
 }
 
 NO_SANITIZE("cfi-icall")
diff --git a/chrome/services/wilco_dtc_supportd/public/mojom/BUILD.gn b/chrome/services/wilco_dtc_supportd/public/mojom/BUILD.gn
index 597100c..cda21731 100644
--- a/chrome/services/wilco_dtc_supportd/public/mojom/BUILD.gn
+++ b/chrome/services/wilco_dtc_supportd/public/mojom/BUILD.gn
@@ -11,7 +11,7 @@
   sources = [ "wilco_dtc_supportd.mojom" ]
 
   public_deps = [
-    "//chromeos/services/cros_healthd/public/mojom",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//mojo/public/mojom/base",
   ]
 }
diff --git a/chrome/services/wilco_dtc_supportd/public/mojom/wilco_dtc_supportd.mojom b/chrome/services/wilco_dtc_supportd/public/mojom/wilco_dtc_supportd.mojom
index c162b6d..ed7ef97 100644
--- a/chrome/services/wilco_dtc_supportd/public/mojom/wilco_dtc_supportd.mojom
+++ b/chrome/services/wilco_dtc_supportd/public/mojom/wilco_dtc_supportd.mojom
@@ -10,7 +10,7 @@
 
 module chromeos.wilco_dtc_supportd.mojom;
 
-import "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom";
+import "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom";
 
 [Extensible]
 enum WilcoDtcSupportdWebRequestHttpMethod {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index e2c5bec..450fa8a 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -534,8 +534,8 @@
       "//ash/public/cpp:test_support",
       "//chrome/browser/ash",
       "//chromeos/ash/components/dbus/session_manager",
+      "//chromeos/ash/components/dbus/userdataauth",
       "//chromeos/dbus/tpm_manager",
-      "//chromeos/dbus/userdataauth",
       "//chromeos/login/login_state",
       "//components/exo",
       "//components/ownership",
@@ -679,6 +679,7 @@
 
     deps += [
       "//build:chromeos_buildflags",
+      "//chrome/browser/ash/system_web_apps/test_support",
       "//chrome/browser/web_applications:web_applications_test_support",
       "//components/webapps/browser",
       "//third_party/zlib/google:zip",
@@ -1189,6 +1190,7 @@
       "//chrome/browser/accessibility:test_support",
       "//chrome/browser/apps/app_service:test_support",
       "//chrome/browser/ash/system_web_apps:browser_tests",
+      "//chrome/browser/ash/system_web_apps/test_support",
       "//chrome/browser/ash/system_web_apps/test_support:test_support_ui",
       "//chrome/browser/ash/system_web_apps/types:types",
       "//chrome/browser/breadcrumbs:browser_tests",
@@ -2270,6 +2272,7 @@
       "../browser/window_placement/window_placement_browsertest.cc",
       "../browser/window_placement/window_placement_permission_context_browsertest.cc",
       "../common/time_format_browsertest.cc",
+      "../renderer/accessibility/read_anything_app_controller_browsertest.cc",
       "../renderer/autofill/autofill_renderer_browsertest.cc",
       "../renderer/autofill/fake_mojo_password_manager_driver.cc",
       "../renderer/autofill/fake_mojo_password_manager_driver.h",
@@ -2411,7 +2414,7 @@
       deps += [ "//components/safe_browsing/content/common/proto:download_file_types_proto" ]
     }
 
-    if (enable_basic_printing) {
+    if (enable_basic_printing && enable_pdf) {
       sources +=
           [ "../browser/devtools/protocol/devtools_printtopdf_browsertest.cc" ]
     }
@@ -3443,6 +3446,7 @@
         "../browser/apps/app_service/intent_util_browsertest.cc",
         "../browser/apps/app_service/media_access_browsertest.cc",
         "../browser/apps/app_service/metrics/app_platform_metrics_browsertest.cc",
+        "../browser/apps/app_service/metrics/website_metrics_browsertest.cc",
         "../browser/apps/app_service/notifications_browsertest.cc",
         "../browser/apps/app_service/publishers/web_apps_crosapi_browsertest.cc",
         "../browser/apps/app_service/webapk/webapk_policy_browsertest.cc",
@@ -3946,12 +3950,8 @@
         # data or data_deps and through which dependencies.
         "//chrome/browser/resources/chromeos/wallpaper_manager/",
         "//chromeos/test/data/",
-        "//ui/file_manager/base/",
-        "//ui/file_manager/file_manager/",
-        "//ui/file_manager/image_loader/",
         "//ui/file_manager/integration_tests/",
         "//third_party/polymer/v1_0/components-chromium/",
-        "$root_gen_dir/ui/file_manager/file_manager/",
         "$root_out_dir/chromevox_test_data/",
         "$root_out_dir/content_shell.pak",
         "$root_out_dir/resources/chromeos/",
@@ -3961,7 +3961,6 @@
         "//ash/keyboard/ui:resources",
         "//chrome",
         "//testing/buildbot/filters:chromeos_filters",
-        "//ui/file_manager:unit_test_data",
       ]
       if (!is_official_build) {
         sources += [
@@ -4049,6 +4048,7 @@
         "//ash/components/drivefs/mojom",
         "//ash/components/geolocation",
         "//ash/components/hid_detection:hid_detection",
+        "//ash/components/hid_detection:test_support",
         "//ash/components/login/auth",
         "//ash/components/login/auth:challenge_response_key",
         "//ash/components/login/auth:test_support",
@@ -4121,6 +4121,7 @@
         "//chromeos/ash/components/network/portal_detector",
         "//chromeos/ash/services/assistant:lib",
         "//chromeos/ash/services/assistant/public/cpp",
+        "//chromeos/ash/services/cros_healthd/public/cpp",
         "//chromeos/components/onc:test_support",
         "//chromeos/components/quick_answers/public/cpp:cpp",
         "//chromeos/components/remote_apps/mojom:mojom",
@@ -4139,7 +4140,6 @@
         "//chromeos/login/login_state:test_support",
         "//chromeos/process_proxy",
         "//chromeos/services/assistant/public/proto",
-        "//chromeos/services/cros_healthd/public/cpp",
         "//chromeos/services/machine_learning/public/cpp:stub",
         "//chromeos/services/tts",
         "//chromeos/system",
@@ -4653,6 +4653,7 @@
       ":test_support",
       ":test_support_ui",
       "//chrome/app:command_ids",
+      "//chrome/browser/ash/system_web_apps/test_support",
       "//chrome/browser/chromeos/extensions/vpn_provider",
       "//chrome/browser/metrics/structured",
       "//chrome/browser/web_applications:web_applications_test_support",
@@ -6838,6 +6839,7 @@
       "//chrome:packed_resources_integrity_hash",
       "//chrome/browser:cart_db_content_proto",
       "//chrome/browser:coupon_db_content_proto",
+      "//chrome/browser/ash/system_web_apps/test_support",
       "//chrome/browser/autofill_assistant/password_change/proto:proto",
       "//chrome/browser/enterprise/connectors/analysis:features",
       "//chrome/browser/media/router:test_support",
@@ -8160,10 +8162,10 @@
       "../browser/enterprise/connectors/device_trust/key_management/core/persistence:test_support",
       "../browser/enterprise/connectors/device_trust/key_management/installer:unit_tests",
       "../browser/enterprise/connectors/device_trust/signals/decorators/browser:unit_tests",
-      "../browser/enterprise/signals:features",
-      "../browser/enterprise/signals:unit_tests",
       "//components/device_signals/core/browser",
       "//components/device_signals/core/browser:test_support",
+      "//components/device_signals/core/common:features",
+      "//components/device_signals/core/common:unit_tests",
     ]
   }
 
@@ -8738,6 +8740,7 @@
       "//chrome/browser",
       "//chrome/browser:browser_process",
       "//chrome/browser/ash/system_web_apps",
+      "//chrome/browser/ash/system_web_apps/test_support",
       "//chrome/browser/devtools",
       "//chrome/browser/profiles:profile",
       "//chrome/browser/ui",
@@ -9093,6 +9096,7 @@
       "//chrome/app:command_ids",
       "//chrome/browser",
       "//chrome/browser:unexpire_flags",
+      "//chrome/browser/ash/system_web_apps/test_support",
       "//chrome/browser/ash/system_web_apps/test_support:test_support_ui",
       "//chrome/browser/devtools",
       "//chrome/browser/devtools:test_support",
@@ -9415,6 +9419,7 @@
         "../browser/notifications/notification_platform_bridge_win_interactive_uitest.cc",
         "../browser/notifications/win/fake_itoastnotifier.cc",
         "../browser/notifications/win/fake_itoastnotifier.h",
+        "../browser/os_crypt/app_bound_encryption_win_browsertest.cc",
         "../browser/ui/send_mouse_move_uitest_win.cc",
         "../browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc",
         "../browser/ui/views/accessibility/uia_accessibility_event_waiter.cc",
@@ -9429,6 +9434,7 @@
       deps += [
         "//chrome:other_version",
         "//chrome/app:chrome_dll_resources",
+        "//chrome/elevation_service:public_headers",
         "//chrome/install_static:install_static_util",
         "//chrome/installer/util:strings",
         "//third_party/isimpledom",
@@ -9437,6 +9443,8 @@
         "//ui/resources",
       ]
 
+      data_deps += [ "//chrome/elevation_service" ]
+
       libs = [
         "oleacc.lib",
         "runtimeobject.lib",
@@ -9806,6 +9814,7 @@
     deps += [ ":sync_integration_test_support_jni_headers" ]
   } else {
     deps += [
+      "//chrome/browser/ash/system_web_apps/test_support",
       "//chrome/browser/web_applications:web_applications_test_support",
       "//components/send_tab_to_self",
       "//components/webapps/browser",
@@ -9842,6 +9851,7 @@
       "//chrome:strings",
       "//chrome/app:chrome_dll_resources",
       "//chrome/app:command_ids",
+      "//chrome/browser/ash/system_web_apps/test_support",
       "//chrome/browser/browsing_data:constants",
       "//chrome/browser/web_applications:web_applications_test_support",
       "//chrome/common",
@@ -9922,6 +9932,7 @@
         "//chromeos/components/sync_wifi:test_support",
         "//chromeos/dbus/shill",
         "//chromeos/printing",
+        "//chromeos/services/network_config/public/cpp",
         "//components/desks_storage",
       ]
     }
diff --git a/chrome/test/data/autofill/autofill_creditcard_form_with_date_formatter.html b/chrome/test/data/autofill/autofill_creditcard_form_with_date_formatter.html
index 24d9336..ca8710d8 100644
--- a/chrome/test/data/autofill/autofill_creditcard_form_with_date_formatter.html
+++ b/chrome/test/data/autofill/autofill_creditcard_form_with_date_formatter.html
@@ -48,9 +48,12 @@
 document.getElementById('CREDIT_CARD_EXP_DATE').addEventListener('change',
   () => {
     const matches = [...element.value.match(/(\d+)\s*\/\s*(\d+)/)];
-    const formatedValue = matches[1] + ' / ' + matches[2].substr(0,2);
-    if (element.value !== formatedValue) {
-      element.value = formatedValue;
+    const formattedValue = matches[1] + ' / ' + matches[2].substr(0,2);
+    if (formattedValue === '09 / 99') {
+      window.unblock = true;  // Unblocks the C++ call ListenForValueChange().
+    }
+    if (element.value !== formattedValue) {
+      element.value = formattedValue;
     }
   });
 </script>
diff --git a/chrome/test/data/back_forward_cache/page_with_embed_html.html b/chrome/test/data/back_forward_cache/page_with_embed_html.html
new file mode 100644
index 0000000..13765a5
--- /dev/null
+++ b/chrome/test/data/back_forward_cache/page_with_embed_html.html
@@ -0,0 +1,7 @@
+<head>
+  <title>Page embedding a HTML</title>
+</head>
+<body>
+  <p> This page embeds a HTML. </p>
+  <embed id="embed" src="/title1.html" type="text/html"/>
+</body>
diff --git a/chrome/test/data/back_forward_cache/page_with_embed_pdf.html b/chrome/test/data/back_forward_cache/page_with_embed_pdf.html
new file mode 100644
index 0000000..d332f6b
--- /dev/null
+++ b/chrome/test/data/back_forward_cache/page_with_embed_pdf.html
@@ -0,0 +1,7 @@
+<head>
+  <title>Page embedding a PDF</title>
+</head>
+<body>
+  <p> This page embeds a PDF. </p>
+  <embed id="embed" src="/pdf/test.pdf" type="application/pdf"/>
+</body>
diff --git a/chrome/test/data/back_forward_cache/page_with_embed_plugin.html b/chrome/test/data/back_forward_cache/page_with_embed_plugin.html
new file mode 100644
index 0000000..72f7a14
--- /dev/null
+++ b/chrome/test/data/back_forward_cache/page_with_embed_plugin.html
@@ -0,0 +1,7 @@
+<head>
+  <title>Page embedding a plugin</title>
+</head>
+<body>
+  <p> This page embeds a plugin. </p>
+  <embed id="embed" type="application/x-blink-test-plugin" />
+</body>
diff --git a/chrome/test/data/back_forward_cache/page_with_object_html.html b/chrome/test/data/back_forward_cache/page_with_object_html.html
new file mode 100644
index 0000000..7d3cecb
--- /dev/null
+++ b/chrome/test/data/back_forward_cache/page_with_object_html.html
@@ -0,0 +1,7 @@
+<head>
+  <title>Page embedding a HTML</title>
+</head>
+<body>
+  <p> This page embeds a HTML. </p>
+  <object id="object" data="/title1.html" type="text/html"/>
+</body>
diff --git a/chrome/test/data/back_forward_cache/page_with_object_pdf.html b/chrome/test/data/back_forward_cache/page_with_object_pdf.html
new file mode 100644
index 0000000..9f5c5a4
--- /dev/null
+++ b/chrome/test/data/back_forward_cache/page_with_object_pdf.html
@@ -0,0 +1,7 @@
+<head>
+  <title>Page embedding a PDF</title>
+</head>
+<body>
+  <p> This page embeds a PDF. </p>
+  <object id="object" data="/pdf/test.pdf" type="application/pdf"/>
+</body>
diff --git a/chrome/test/data/back_forward_cache/page_with_object_plugin.html b/chrome/test/data/back_forward_cache/page_with_object_plugin.html
new file mode 100644
index 0000000..d8e4a11
--- /dev/null
+++ b/chrome/test/data/back_forward_cache/page_with_object_plugin.html
@@ -0,0 +1,7 @@
+<head>
+  <title>Page embedding a plugin</title>
+</head>
+<body>
+  <p> This page embeds a plugin. </p>
+  <object id="object" type="application/x-blink-test-plugin"/>
+</body>
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 5bc80510..137d188 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -16911,18 +16911,23 @@
     ],
     "policy_pref_mapping_tests": [
       {
+        "note": "default value",
+        "policies": {},
+        "prefs": {
+          "net.explicitly_allowed_network_ports": {
+            "default_value": [],
+            "location": "local_state"
+          }
+        }
+      },
+      {
+        "note": "no ports are currently allowed to be blocked, but policy remains in place for potential future use",
         "policies": {
-          "ExplicitlyAllowedNetworkPorts": [
-            "554",
-            "10080"
-          ]
+          "ExplicitlyAllowedNetworkPorts": []
         },
         "prefs": {
           "net.explicitly_allowed_network_ports": {
-            "value": [
-              554,
-              10080
-            ],
+            "value": [],
             "location": "local_state"
           }
         }
diff --git a/chrome/test/data/webrtc/region_capture_main.html b/chrome/test/data/webrtc/region_capture_main.html
index 50b7b6bc3..0bde5787 100644
--- a/chrome/test/data/webrtc/region_capture_main.html
+++ b/chrome/test/data/webrtc/region_capture_main.html
@@ -52,6 +52,16 @@
           window.domAutomationController.send("deallocate-failure");
         }
       }
+
+      function hideElement(elementId) {
+        const element = document.getElementById(elementId);
+        if (!element) {
+          window.domAutomationController.send("hide-element-failure");
+          return;
+        }
+        element.hidden = true;
+        window.domAutomationController.send("hide-element-success");
+      }
     </script>
   </head>
   <body onload="onLoad();">
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 2399004d..1967a8e0 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -180,7 +180,7 @@
       ]
     }
 
-    if (use_nss_certs && use_aura) {
+    if (enable_webui_certificate_viewer) {
       sources += [ "certificate_viewer_dialog_browsertest.js" ]
     }
     if (enable_extensions) {
diff --git a/chrome/test/data/webui/chromeos/account_manager/account_manager_browsertest.js b/chrome/test/data/webui/chromeos/account_manager/account_manager_browsertest.js
index 8931a62..55878ed 100644
--- a/chrome/test/data/webui/chromeos/account_manager/account_manager_browsertest.js
+++ b/chrome/test/data/webui/chromeos/account_manager/account_manager_browsertest.js
@@ -13,7 +13,7 @@
 var AccountMigrationWelcomeTest = class extends PolymerTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://account-migration-welcome/test_loader.html?module=chromeos/account_manager/account_migration_welcome_test.js';
+    return 'chrome://account-migration-welcome/test_loader.html?module=chromeos/account_manager/account_migration_welcome_test.js&host=test';
   }
 };
 
diff --git a/chrome/test/data/webui/chromeos/arc_account_picker/arc_account_picker_browsertest.js b/chrome/test/data/webui/chromeos/arc_account_picker/arc_account_picker_browsertest.js
index 4e152c1..57b341c3 100644
--- a/chrome/test/data/webui/chromeos/arc_account_picker/arc_account_picker_browsertest.js
+++ b/chrome/test/data/webui/chromeos/arc_account_picker/arc_account_picker_browsertest.js
@@ -15,7 +15,7 @@
 var ArcAccountPickerTest = class extends PolymerTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://chrome-signin/test_loader.html?module=chromeos/arc_account_picker/arc_account_picker_test.js';
+    return 'chrome://chrome-signin/test_loader.html?module=chromeos/arc_account_picker/arc_account_picker_test.js&host=test';
   }
 
   get suiteName() {
diff --git a/chrome/test/data/webui/chromeos/ash_common/ash_common_browsertest.js b/chrome/test/data/webui/chromeos/ash_common/ash_common_browsertest.js
index 753e5d5..be5d904 100644
--- a/chrome/test/data/webui/chromeos/ash_common/ash_common_browsertest.js
+++ b/chrome/test/data/webui/chromeos/ash_common/ash_common_browsertest.js
@@ -27,7 +27,8 @@
   /** @override */
   get browsePreload() {
     // TODO(joonbug): Find a more generic way to load tests
-    return `chrome://new-tab-page/test_loader.html?module=${testSuites}`;
+    return `chrome://new-tab-page/test_loader.html?module=${
+        testSuites}&host=test`;
   }
 };
 
diff --git a/chrome/test/data/webui/chromeos/crostini_installer_browsertest.js b/chrome/test/data/webui/chromeos/crostini_installer_browsertest.js
index cfa469e..74a16e25 100644
--- a/chrome/test/data/webui/chromeos/crostini_installer_browsertest.js
+++ b/chrome/test/data/webui/chromeos/crostini_installer_browsertest.js
@@ -15,7 +15,7 @@
   __proto__: PolymerTest.prototype,
 
   browsePreload:
-      'chrome://crostini-installer/test_loader.html?module=chromeos/crostini_installer_app_test.js',
+      'chrome://crostini-installer/test_loader.html?module=chromeos/crostini_installer_app_test.js&host=test',
 };
 
 
diff --git a/chrome/test/data/webui/chromeos/crostini_upgrader_browsertest.js b/chrome/test/data/webui/chromeos/crostini_upgrader_browsertest.js
index 652a7a8..ac98965f 100644
--- a/chrome/test/data/webui/chromeos/crostini_upgrader_browsertest.js
+++ b/chrome/test/data/webui/chromeos/crostini_upgrader_browsertest.js
@@ -16,7 +16,7 @@
   __proto__: PolymerTest.prototype,
 
   browsePreload:
-      'chrome://crostini-upgrader/test_loader.html?module=chromeos/crostini_upgrader_app_test.js',
+      'chrome://crostini-upgrader/test_loader.html?module=chromeos/crostini_upgrader_app_test.js&host=test',
 };
 
 
diff --git a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_browsertest.js b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_browsertest.js
index ee264bd7..7b6931fd 100644
--- a/chrome/test/data/webui/chromeos/firmware_update/firmware_update_browsertest.js
+++ b/chrome/test/data/webui/chromeos/firmware_update/firmware_update_browsertest.js
@@ -32,7 +32,7 @@
 
   browsePreload: 'chrome://accessory-update/test_loader.html' +
       '?module=chromeos/firmware_update/' +
-      'firmware_update_unified_test.js',
+      'firmware_update_unified_test.js&host=test',
 
   featureList: {enabled: ['ash::features::kFirmwareUpdaterApp']},
 };
diff --git a/chrome/test/data/webui/chromeos/gaia_action_buttons/gaia_action_buttons_browsertest.js b/chrome/test/data/webui/chromeos/gaia_action_buttons/gaia_action_buttons_browsertest.js
index 913a435..a846460 100644
--- a/chrome/test/data/webui/chromeos/gaia_action_buttons/gaia_action_buttons_browsertest.js
+++ b/chrome/test/data/webui/chromeos/gaia_action_buttons/gaia_action_buttons_browsertest.js
@@ -15,7 +15,7 @@
 var GaiaActionButtonsTest = class extends PolymerTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://chrome-signin/test_loader.html?module=chromeos/gaia_action_buttons/gaia_action_buttons_test.js';
+    return 'chrome://chrome-signin/test_loader.html?module=chromeos/gaia_action_buttons/gaia_action_buttons_test.js&host=test';
   }
 
   get suiteName() {
diff --git a/chrome/test/data/webui/chromeos/internet_detail_dialog_browsertest.js b/chrome/test/data/webui/chromeos/internet_detail_dialog_browsertest.js
index 12786f5..fc857c1 100644
--- a/chrome/test/data/webui/chromeos/internet_detail_dialog_browsertest.js
+++ b/chrome/test/data/webui/chromeos/internet_detail_dialog_browsertest.js
@@ -12,7 +12,7 @@
 var InternetDetailDialogBrowserTest = class extends PolymerTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://internet-detail-dialog/test_loader.html?module=chromeos/internet_detail_dialog_test.js';
+    return 'chrome://internet-detail-dialog/test_loader.html?module=chromeos/internet_detail_dialog_test.js&host=test';
   }
 };
 
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
index e1b53488..9e789fd8 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
@@ -26,7 +26,7 @@
 const OFFLINE_MESSAGE =
     'Thanks for the feedback. Your feedback helps improve Chrome OS ' +
     'and will be reviewed by the Chrome OS team. Because of the number ' +
-    ' of reports submitted, you won’t receive a direct reply.';
+    'of reports submitted, you won’t receive a direct reply.';
 
 export function confirmationPageTest() {
   /** @type {?ConfirmationPageElement} */
@@ -87,6 +87,7 @@
       assertEquals(ONLINE_MESSAGE, getElementContent(page, '#message'));
     } else {
       assertEquals(OFFLINE_TITLE, getElementContent(page, '.page-title'));
+      assertTrue(page.i18nExists('thankYouNoteOffline'));
       assertEquals(OFFLINE_MESSAGE, getElementContent(page, '#message'));
     }
 
@@ -105,6 +106,7 @@
     assertEquals(
         'help-resources:explore', getElement(exploreLink, '#startIcon').icon);
     assertEquals('Explore app', getElementContent(exploreLink, '#label'));
+    assertTrue(page.i18nExists('exploreAppLabel'));
     assertEquals(
         'Find help articles and answers to common Chromebook questions',
         getElementContent(exploreLink, '#subLabel'));
@@ -122,6 +124,7 @@
     assertEquals(
         'Run tests and troubleshooting for hardware issues',
         getElementContent(diagnosticsLink, '#subLabel'));
+    assertTrue(page.i18nExists('diagnosticsAppDescription'));
 
     // Verify the community link.
     const communityLink = helpLinks[2];
@@ -138,6 +141,8 @@
     assertEquals(
         'Ask the experts in the Chromebook help forum',
         getElementContent(communityLink, '#subLabel'));
+    assertTrue(page.i18nExists('askCommunityLabel'));
+    assertTrue(page.i18nExists('askCommunityDescription'));
 
     // Verify buttons.
     assertEquals(
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/os_feedback_browsertest.js b/chrome/test/data/webui/chromeos/os_feedback_ui/os_feedback_browsertest.js
index 3dd478f9..37a77c5e 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/os_feedback_browsertest.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/os_feedback_browsertest.js
@@ -27,7 +27,7 @@
   /** @override */
   get browsePreload() {
     return 'chrome://os-feedback/test_loader.html?module=chromeos/' +
-        'os_feedback_ui/os_feedback_unified_test.js';
+        'os_feedback_ui/os_feedback_unified_test.js&host=test';
   }
 
   /** @override */
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
index fa2f997..190c37f 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
@@ -87,6 +87,7 @@
     await initializePage();
     // Verify the title is in the page.
     assertEquals('Send feedback', getElementContent('.page-title'));
+    assertTrue(page.i18nExists('pageTitle'));
 
     // Verify the back button is in the page.
     assertEquals('Back', getElementContent('#buttonBack'));
@@ -104,6 +105,11 @@
     assertTrue(page.i18nExists('userEmailLabel'));
     assertEquals('Email', getElementContent('#userEmailLabel'));
 
+    // Verify don't include email address is in the page.
+    assertTrue(page.i18nExists('anonymousUser'));
+    assertEquals(
+        `Don't include email address`, getElementContent('#anonymousUser'));
+
     // Verify the share diagnostic data label is in the page.
     assertTrue(page.i18nExists('shareDiagnosticDataLabel'));
     assertEquals(
diff --git a/chrome/test/data/webui/chromeos/parent_access/parent_access_browsertest.js b/chrome/test/data/webui/chromeos/parent_access/parent_access_browsertest.js
index d37c52901..9afe77e 100644
--- a/chrome/test/data/webui/chromeos/parent_access/parent_access_browsertest.js
+++ b/chrome/test/data/webui/chromeos/parent_access/parent_access_browsertest.js
@@ -14,7 +14,7 @@
   /** @override */
   get browsePreload() {
     return 'chrome://parent-access/test_loader.html?module=' +
-        'chromeos/parent_access/parent_access_app_test.js';
+        'chromeos/parent_access/parent_access_app_test.js&host=test';
   }
 
   /** @param {string} testName The name of the test to run. */
@@ -31,7 +31,7 @@
   /** @override */
   get browsePreload() {
     return 'chrome://parent-access/test_loader.html?module=' +
-        'chromeos/parent_access/parent_access_controller_test.js';
+        'chromeos/parent_access/parent_access_controller_test.js&host=test';
   }
 
   /** @override */
@@ -54,7 +54,7 @@
   /** @override */
   get browsePreload() {
     return 'chrome://parent-access/test_loader.html?module=' +
-        'chromeos/parent_access/parent_access_ui_test.js';
+        'chromeos/parent_access/parent_access_ui_test.js&host=test';
   }
 
   /** @override */
@@ -87,7 +87,7 @@
   /** @override */
   get browsePreload() {
     return 'chrome://parent-access/test_loader.html?module=' +
-        'chromeos/parent_access/parent_access_ui_handler_test.js';
+        'chromeos/parent_access/parent_access_ui_handler_test.js&host=test';
   }
 
   /** @override */
diff --git a/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts
index ff7a332e..8e1d076 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts
@@ -583,6 +583,12 @@
     const albumList = albumsSubpage.shadowRoot!.querySelector('album-list');
     assertTrue(!!albumList, '!!albumList');
 
+    // The grid may not have templated all the items yet since it was just
+    // instantiated. See crbug/1334962.
+    const grid = albumList.shadowRoot!.getElementById('grid');
+    assertTrue(!!grid, 'albums subpage has a grid');
+    await waitAfterNextRender(grid);
+
     const albums = albumList.shadowRoot!.querySelectorAll<WallpaperGridItem>(
         'wallpaper-grid-item:not([hidden])');
     assertEquals(3, albums.length);
@@ -635,6 +641,12 @@
     const albumList = albumsSubpage.shadowRoot!.querySelector('album-list');
     assertTrue(!!albumList);
 
+    // The grid may not have templated all the items yet since it was just
+    // instantiated. See crbug/1334962.
+    const grid = albumList.shadowRoot!.getElementById('grid');
+    assertTrue(!!grid, 'albums subpage has a grid');
+    await waitAfterNextRender(grid);
+
     const albums = albumList.shadowRoot!.querySelectorAll<WallpaperGridItem>(
         'wallpaper-grid-item:not([hidden])');
     assertEquals(3, albums.length);
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_browsertest.js b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_browsertest.js
index 0393796..806fabf 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_browsertest.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_browsertest.js
@@ -24,8 +24,7 @@
 };
 
 [['AmbientPreviewTest', 'ambient_preview_element_test.js'],
- // TODO(crbug/1334962) re-enable this test case.
- ['AmbientSubpageTest', 'ambient_subpage_element_test.js', 'DISABLED_All'],
+ ['AmbientSubpageTest', 'ambient_subpage_element_test.js'],
  ['AvatarCameraTest', 'avatar_list_element_test.js'],
  ['AvatarListTest', 'avatar_list_element_test.js'],
  ['GooglePhotosAlbumsTest', 'google_photos_albums_element_test.js'],
diff --git a/chrome/test/data/webui/chromeos/print_management/print_management_browsertest.js b/chrome/test/data/webui/chromeos/print_management/print_management_browsertest.js
index 218726e6..f284865 100644
--- a/chrome/test/data/webui/chromeos/print_management/print_management_browsertest.js
+++ b/chrome/test/data/webui/chromeos/print_management/print_management_browsertest.js
@@ -20,7 +20,7 @@
   __proto__: PolymerTest.prototype,
 
   browsePreload: 'chrome://print-management/test_loader.html?module=chromeos/' +
-      'print_management/print_management_test.js',
+      'print_management/print_management_test.js&host=test',
 };
 
 TEST_F('PrintManagementBrowserTest', 'All', function() {
diff --git a/chrome/test/data/webui/chromeos/scanning/scanning_app_browsertest.js b/chrome/test/data/webui/chromeos/scanning/scanning_app_browsertest.js
index 1c518ec..14053ecf 100644
--- a/chrome/test/data/webui/chromeos/scanning/scanning_app_browsertest.js
+++ b/chrome/test/data/webui/chromeos/scanning/scanning_app_browsertest.js
@@ -31,7 +31,7 @@
 ScanningAppBrowserTest.prototype = {
   __proto__: PolymerTest.prototype,
   browsePreload: 'chrome://scanning/test_loader.html?module=chromeos/' +
-      'scanning/scanning_app_unified_test.js',
+      'scanning/scanning_app_unified_test.js&host=test',
 };
 
 // List of names of suites in unified test to register for individual debugging.
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js
index b87337a..51dccc721 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js
@@ -27,7 +27,7 @@
   /** @override */
   get browsePreload() {
     return 'chrome://shimless-rma/test_loader.html?module=chromeos/' +
-        'shimless_rma/shimless_rma_unified_test.js';
+        'shimless_rma/shimless_rma_unified_test.js&host=test';
   }
 
   /** @override */
diff --git a/chrome/test/data/webui/chromeos/shortcut_customization/shortcut_customization_browsertest.js b/chrome/test/data/webui/chromeos/shortcut_customization/shortcut_customization_browsertest.js
index bbe3df55..de35b11 100644
--- a/chrome/test/data/webui/chromeos/shortcut_customization/shortcut_customization_browsertest.js
+++ b/chrome/test/data/webui/chromeos/shortcut_customization/shortcut_customization_browsertest.js
@@ -32,7 +32,7 @@
 
   browsePreload: 'chrome://shortcut-customization/test_loader.html' +
       '?module=chromeos/shortcut_customization/' +
-      'shortcut_customization_unified_test.js',
+      'shortcut_customization_unified_test.js&host=test',
 
   featureList: {enabled: ['features::kShortcutCustomizationApp']},
 };
diff --git a/chrome/test/data/webui/cr_components/BUILD.gn b/chrome/test/data/webui/cr_components/BUILD.gn
index 87e3030..cc1fb5cf 100644
--- a/chrome/test/data/webui/cr_components/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/BUILD.gn
@@ -26,6 +26,7 @@
   "app_management/file_handling_item_test.ts",
   "app_management/permission_item_test.ts",
   "app_management/window_mode_item_test.ts",
+  "color_change_listener_test.ts",
   "customize_themes_test.ts",
   "history_clusters_test.ts",
   "localized_link_test.ts",
@@ -67,6 +68,7 @@
   in_files = non_preprocessed_files + preprocessed_files
   deps = [
     "//ui/webui/resources/cr_components/app_management:build_ts",
+    "//ui/webui/resources/cr_components/color_change_listener:build_ts",
     "//ui/webui/resources/cr_components/customize_themes:build_ts",
     "//ui/webui/resources/cr_components/history_clusters:build_ts",
     "//ui/webui/resources/cr_components/most_visited:build_ts",
diff --git a/chrome/test/data/webui/cr_components/color_change_listener_test.js b/chrome/test/data/webui/cr_components/color_change_listener_test.ts
similarity index 85%
rename from chrome/test/data/webui/cr_components/color_change_listener_test.js
rename to chrome/test/data/webui/cr_components/color_change_listener_test.ts
index cf318ef..d0d6531 100644
--- a/chrome/test/data/webui/cr_components/color_change_listener_test.js
+++ b/chrome/test/data/webui/cr_components/color_change_listener_test.ts
@@ -3,8 +3,7 @@
 // found in the LICENSE file.
 
 import {COLORS_CSS_SELECTOR, refreshColorCss} from 'chrome://resources/cr_components/color_change_listener/colors_css_updater.js';
-
-import {assertFalse, assertNotEquals, assertTrue} from '../chai_assert.js';
+import {assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 suite('ColorChangeListenerTest', () => {
   setup(() => {
@@ -13,15 +12,18 @@
   });
 
   test('CorrectlyUpdatesColorsStylesheetURL', () => {
-    const colorCssNode = document.querySelector(COLORS_CSS_SELECTOR);
+    const colorCssNode =
+        document.querySelector<HTMLLinkElement>(COLORS_CSS_SELECTOR);
     assertTrue(!!colorCssNode);
     const initialHref = colorCssNode.getAttribute('href');
+    assertTrue(!!initialHref);
     assertTrue(initialHref.startsWith('chrome://theme/colors.css'));
 
     // refreshColorCss() should append search params to the colors CSS href.
     assertTrue(refreshColorCss());
 
     const finalHref = colorCssNode.getAttribute('href');
+    assertTrue(!!finalHref);
     assertTrue(finalHref.startsWith('chrome://theme/colors.css'));
     assertTrue(!!new URL(finalHref).search);
 
diff --git a/chrome/test/data/webui/cr_components/cr_components_browsertest.js b/chrome/test/data/webui/cr_components/cr_components_browsertest.js
index fafd899..081e119 100644
--- a/chrome/test/data/webui/cr_components/cr_components_browsertest.js
+++ b/chrome/test/data/webui/cr_components/cr_components_browsertest.js
@@ -32,7 +32,7 @@
     class extends CrComponentsBrowserTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://test/test_loader.html?module=cr_components/color_change_listener_test.js';
+    return 'chrome://test/test_loader.html?module=cr_components/color_change_listener_test.js&host=webui-test';
   }
 };
 
diff --git a/chrome/test/data/webui/post_message_api/post_message_api_browsertest.js b/chrome/test/data/webui/post_message_api/post_message_api_browsertest.js
index d58cd74..f80d043 100644
--- a/chrome/test/data/webui/post_message_api/post_message_api_browsertest.js
+++ b/chrome/test/data/webui/post_message_api/post_message_api_browsertest.js
@@ -15,7 +15,7 @@
 
   /** @override */
   browsePreload:
-      'chrome://chrome-signin/test_loader.html?module=post_message_api/post_message_api_test.js',
+      'chrome://chrome-signin/test_loader.html?module=post_message_api/post_message_api_test.js&host=test',
 
   extraLibraries: [
     '//third_party/mocha/mocha.js',
diff --git a/chrome/test/data/webui/set_time_dialog_browsertest.js b/chrome/test/data/webui/set_time_dialog_browsertest.js
index a77ed2d..4050c824 100644
--- a/chrome/test/data/webui/set_time_dialog_browsertest.js
+++ b/chrome/test/data/webui/set_time_dialog_browsertest.js
@@ -11,7 +11,7 @@
 var SetTimeDialogBrowserTest = class extends PolymerTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://set-time/test_loader.html?module=set_time_dialog_test.js';
+    return 'chrome://set-time/test_loader.html?module=set_time_dialog_test.js&host=test';
   }
 };
 
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.ts b/chrome/test/data/webui/settings/people_page_sync_page_test.ts
index a23daba0..efceb4c 100644
--- a/chrome/test/data/webui/settings/people_page_sync_page_test.ts
+++ b/chrome/test/data/webui/settings/people_page_sync_page_test.ts
@@ -40,7 +40,6 @@
   let encryptWithPassphrase: CrRadioButtonElement;
 
   function setupSyncPage() {
-    loadTimeData.overrideValues({nonSyncingProfilesEnabled: true});
     document.body.innerHTML = '';
     syncPage = document.createElement('settings-sync-page');
     const router = Router.getInstance();
diff --git a/chrome/test/data/webui/settings/sync_account_control_test.ts b/chrome/test/data/webui/settings/sync_account_control_test.ts
index 385ea5c..b29cefe7 100644
--- a/chrome/test/data/webui/settings/sync_account_control_test.ts
+++ b/chrome/test/data/webui/settings/sync_account_control_test.ts
@@ -37,9 +37,6 @@
   }
 
   setup(async function() {
-    // <if expr="chromeos_lacros">
-    loadTimeData.overrideValues({nonSyncingProfilesEnabled: true});
-    // </if>
     setupRouterWithSyncRoutes();
     browserProxy = new TestSyncBrowserProxy();
     SyncBrowserProxyImpl.setInstance(browserProxy);
diff --git a/chrome/test/data/webui/signin/signin_browsertest.js b/chrome/test/data/webui/signin/signin_browsertest.js
index 23eb44fa8a..302496d 100644
--- a/chrome/test/data/webui/signin/signin_browsertest.js
+++ b/chrome/test/data/webui/signin/signin_browsertest.js
@@ -14,16 +14,6 @@
 GEN('#include "components/signin/public/base/signin_buildflags.h"');
 GEN('#include "content/public/test/browser_test.h"');
 
-GEN('#if BUILDFLAG(IS_CHROMEOS_LACROS)');
-GEN('#include "components/signin/public/base/signin_switches.h"');
-GEN('#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)');
-
-GEN('#if BUILDFLAG(IS_CHROMEOS_LACROS)');
-GEN('#define MAYBE_LACROS_NON_SYNCING_PROFILES switches::kLacrosNonSyncingProfiles');
-GEN('#else');
-GEN('#define MAYBE_LACROS_NON_SYNCING_PROFILES');
-GEN('#endif // BUILDFLAG(IS_CHROMEOS_LACROS)');
-
 /* eslint-disable no-var */
 
 class SigninBrowserTest extends PolymerTest {
@@ -31,15 +21,6 @@
   get browsePreload() {
     throw new Error('this is abstract and should be overriden by subclasses');
   }
-
-  /** @override */
-  get featureList() {
-    return {
-      enabled: [
-        'MAYBE_LACROS_NON_SYNCING_PROFILES',
-      ]
-    };
-  }
 }
 
 /**
diff --git a/chrome/test/data/webui/signin/sync_confirmation_test.ts b/chrome/test/data/webui/signin/sync_confirmation_test.ts
index 5418c37..1015690 100644
--- a/chrome/test/data/webui/signin/sync_confirmation_test.ts
+++ b/chrome/test/data/webui/signin/sync_confirmation_test.ts
@@ -17,79 +17,68 @@
 
   const STANDARD_CONSENT_CONFIRMATION = 'Yes, I\'m in';
 
-  [true, false].forEach(syncForcedEnabled => {
-    const suiteForcedSuffix = syncForcedEnabled ? 'SyncForced' : 'SyncOptional';
+  suite(`SigninSyncConfirmationTest${suiteDesignSuffix}`, function() {
+    let app: SyncConfirmationAppElement;
+    let browserProxy: TestSyncConfirmationBrowserProxy;
 
-    suite(
-        `SigninSyncConfirmationTest${suiteDesignSuffix}${suiteForcedSuffix}`,
-        function() {
-          let app: SyncConfirmationAppElement;
-          let browserProxy: TestSyncConfirmationBrowserProxy;
+    function testButtonClick(buttonSelector: string) {
+      const allButtons =
+          Array.from(app.shadowRoot!.querySelectorAll('cr-button')) as
+          Array<CrButtonElement>;
+      const actionButton =
+          app.shadowRoot!.querySelector(buttonSelector) as CrButtonElement;
+      const spinner = app.shadowRoot!.querySelector('paper-spinner-lite');
 
-          function testButtonClick(buttonSelector: string) {
-            const allButtons =
-                Array.from(app.shadowRoot!.querySelectorAll('cr-button')) as
-                Array<CrButtonElement>;
-            const actionButton = app.shadowRoot!.querySelector(
-                                     buttonSelector) as CrButtonElement;
-            const spinner = app.shadowRoot!.querySelector('paper-spinner-lite');
+      allButtons.forEach(button => assertFalse(button.disabled));
+      assertFalse(spinner!.active);
 
-            allButtons.forEach(button => assertFalse(button.disabled));
-            assertFalse(spinner!.active);
+      actionButton.click();
 
-            actionButton.click();
+      allButtons.forEach(button => assertTrue(button.disabled));
+      assertTrue(spinner!.active);
+    }
 
-            allButtons.forEach(button => assertTrue(button.disabled));
-            assertTrue(spinner!.active);
-          }
+    setup(async function() {
+      browserProxy = new TestSyncConfirmationBrowserProxy();
+      SyncConfirmationBrowserProxyImpl.setInstance(browserProxy);
+      loadTimeData.overrideValues({
+        isModalDialog: isModalDialogDesignEnabled,
+      });
+      document.body.innerHTML = '';
+      app = document.createElement('sync-confirmation-app');
+      document.body.append(app);
+      // Check that the account image is requested when the app element is
+      // attached to the document.
+      await browserProxy.whenCalled('requestAccountInfo');
+    });
 
-          setup(async function() {
-            browserProxy = new TestSyncConfirmationBrowserProxy();
-            SyncConfirmationBrowserProxyImpl.setInstance(browserProxy);
-            loadTimeData.overrideValues({
-              isModalDialog: isModalDialogDesignEnabled,
-              syncForced: syncForcedEnabled
-            });
-            document.body.innerHTML = '';
-            app = document.createElement('sync-confirmation-app');
-            document.body.append(app);
-            // Check that the account image is requested when the app element is
-            // attached to the document.
-            await browserProxy.whenCalled('requestAccountInfo');
-          });
+    // Tests that no DCHECKS are thrown during initialization of the UI.
+    test('LoadPage', function() {
+      const cancelButton =
+          app.shadowRoot!.querySelector(
+              isModalDialogDesignEnabled ? '#cancelButton' : '#notNowButton') as
+          HTMLElement;
+      assertFalse(cancelButton!.hidden);
+    });
 
-          // Tests that no DCHECKS are thrown during initialization of the UI.
-          test('LoadPage', function() {
-            const cancelButton = app.shadowRoot!.querySelector(
-                                     isModalDialogDesignEnabled ?
-                                         '#cancelButton' :
-                                         '#notNowButton') as HTMLElement;
-            if (syncForcedEnabled) {
-              assertTrue(cancelButton!.hidden);
-            } else {
-              assertFalse(cancelButton!.hidden);
-            }
-          });
+    // Tests clicking on confirm button.
+    test('ConfirmClicked', async function() {
+      testButtonClick('#confirmButton');
+      await browserProxy.whenCalled('confirm');
+    });
 
-          // Tests clicking on confirm button.
-          test('ConfirmClicked', async function() {
-            testButtonClick('#confirmButton');
-            await browserProxy.whenCalled('confirm');
-          });
+    // Tests clicking on cancel button.
+    test('CancelClicked', async function() {
+      testButtonClick(
+          isModalDialogDesignEnabled ? '#cancelButton' : '#notNowButton');
+      await browserProxy.whenCalled('undo');
+    });
 
-          // Tests clicking on cancel button.
-          test('CancelClicked', async function() {
-            testButtonClick(
-                isModalDialogDesignEnabled ? '#cancelButton' : '#notNowButton');
-            await browserProxy.whenCalled('undo');
-          });
-
-          // Tests clicking on settings button.
-          test('SettingsClicked', async function() {
-            testButtonClick('#settingsButton');
-            await browserProxy.whenCalled('goToSettings');
-          });
-        });
+    // Tests clicking on settings button.
+    test('SettingsClicked', async function() {
+      testButtonClick('#settingsButton');
+      await browserProxy.whenCalled('goToSettings');
+    });
   });
 
   // This test suite verifies that the consent strings recorded in various
diff --git a/chrome/test/data/webui/sys_internals/sys_internals_browsertest.js b/chrome/test/data/webui/sys_internals/sys_internals_browsertest.js
index a5d6923..d7c2666 100644
--- a/chrome/test/data/webui/sys_internals/sys_internals_browsertest.js
+++ b/chrome/test/data/webui/sys_internals/sys_internals_browsertest.js
@@ -18,7 +18,7 @@
   __proto__: testing.Test.prototype,
 
   browsePreload:
-      'chrome://sys-internals/index.html?module=sys_internals/all_tests.js',
+      'chrome://sys-internals/index.html?module=sys_internals/all_tests.js&host=test',
 
   isAsync: true,
 
diff --git a/chrome/test/data/webui/webview_manager/webview_manager_browsertest.js b/chrome/test/data/webui/webview_manager/webview_manager_browsertest.js
index 809d93f..0a18f2c 100644
--- a/chrome/test/data/webui/webview_manager/webview_manager_browsertest.js
+++ b/chrome/test/data/webui/webview_manager/webview_manager_browsertest.js
@@ -15,7 +15,7 @@
 
   /** @override */
   browsePreload:
-      'chrome://chrome-signin/test_loader.html?module=webview_manager/webview_manager_test.js',
+      'chrome://chrome-signin/test_loader.html?module=webview_manager/webview_manager_test.js&host=test',
 
   extraLibraries: [
     '//third_party/mocha/mocha.js',
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 6de97862..50fbedf7 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -44,7 +44,7 @@
       ":cast_shell",
     ]
   }
-  if (is_linux || is_chromeos) {
+  if (is_linux) {
     deps += [
       "//chromecast/browser/webview/client:wayland_webview_client",
       "//chromecast/tracing",
@@ -100,7 +100,7 @@
     "//chromecast/ui/display_settings:cast_display_settings_unittests",
     "//chromecast/shared:cast_shared_unittests",
     "//chromecast/system/reboot:cast_reboot_unittests",
-    "//content/test:content_unittests",
+    "//components/viz:viz_unittests",
     "//crypto:crypto_unittests",
     "//media:media_unittests",
     "//media/midi:midi_unittests",
@@ -110,6 +110,10 @@
     "//ui/base:ui_base_unittests",
   ]
 
+  if (!is_fuchsia) {
+    tests += [ "//content/test:content_unittests" ]
+  }
+
   if (!is_cast_audio_only) {
     tests += [ "//gpu:gpu_unittests" ]
 
@@ -122,7 +126,7 @@
     tests += [ "//media/gpu:video_decode_accelerator_tests" ]
   }
 
-  if (is_linux || is_chromeos) {
+  if (is_linux) {
     tests += [
       "//chromecast/crash:cast_crash_unittests",
       "//components/exo:exo_unittests",
@@ -141,7 +145,7 @@
   # TODO(crbug/1319009): `media_use_ffmpeg` should not largely affect top-level
   # test list. Better create another flag to do this or handle the ffmpeg flag
   # in //chromecast/media/cma/decoder.
-  if (media_use_ffmpeg) {
+  if (media_use_ffmpeg && !is_fuchsia) {
     tests += [
       "//chromecast/cast_core:cast_cast_core_unittests",
       "//chromecast/media:cast_media_unittests",
@@ -158,7 +162,7 @@
     filters += [ cast_media_unittests_filter ]
   }
 
-  if (is_linux || is_chromeos || is_fuchsia) {
+  if (is_linux) {
     tests += [ "//chromecast/media/cma/backend:cast_audio_backend_unittests" ]
     cast_audio_backend_unittests_filter = {
       test_name = "cast_audio_backend_unittests"
@@ -319,40 +323,61 @@
   }
   filters += [ cc_unittests_filter ]
 
-  content_unittests_filter = {
-    test_name = "content_unittests"
+  viz_unittests_filter = {
+    test_name = "viz_unittests"
 
-    # IsSupportedVideoConfig_VP9TransferFunctions fails on all cast builds since
-    # the cast IsSupporedVideoConfigs ignore the transfer function parameter.
-    # (b/36984215).
-    gtest_excludes = [ "*.IsSupportedVideoConfig_VP9TransferFunctions" ]
-    if (target_os == "linux" && !is_cast_desktop_build) {
-      # DesktopCaptureDeviceTest.*: No capture device on Eureka
-      # Disable PepperGamepadHostTest.WaitForReply (pepper not supported on Eureka)
-      # Disable RenderWidgetHostTest.Background because we disable the
-      # blacklist to enable WebGL (b/16142554)
-      gtest_excludes += [
-        "LegacyDomStorageDatabaseTest.TestCanOpenAndReadWebCoreDatabase",
-        "DesktopCaptureDeviceTest.Capture",
-        "GamepadProviderTest.PollingAccess",
-        "PepperGamepadHostTest.WaitForReply",
-        "RenderWidgetHostTest.Background",
-      ]
-    }
-    if (is_cast_audio_only) {
-      # No way to display URL's on audio only cast devices.
-      gtest_excludes += [ "NavigationEntryTest.NavigationEntryURLs" ]
-    }
-    if (enable_assistant && !is_cast_desktop_build) {
-      # Temporarily disable DefaultConstructor on assistant device builds. Cause
-      # of failure is unclear, but it's highly likely it's related to them being
-      # DEATH tests. These were passing until the is_official_build flag was
-      # enabled. These tests are considered non-critical in this context.
-      # (b/62469368)
-      gtest_excludes += [ "WebBluetoothDeviceIdTest.DefaultConstructor" ]
-    }
+    # TODO(crbug.com/1338342): Make these tests pass.
+    gtest_excludes = [
+      "PromotedTrueFalse/MultiUnderlayPromotedTest.UnderlaysBlendPrimaryPlane/0",
+      "UnderlayCastTest.BlackOutsideOverlayContentBounds",
+      "UnderlayCastTest.FullScreenOverlayContentBounds",
+      "UnderlayCastTest.OverlayOccludedContentBounds",
+      "UnderlayCastTest.OverlayOccludedUnionContentBounds",
+      "UnderlayCastTest.OverlayPromotionWithMaskFilter",
+      "UnderlayCastTest.ReplacementQuad",
+      "UnderlayCastTest.RoundContentBounds",
+      "UnderlayCastTest.RoundOverlayContentBounds",
+    ]
   }
-  filters += [ content_unittests_filter ]
+  filters += [ viz_unittests_filter ]
+
+  # content_unittests are not run on Fuchsia.
+  if (!is_fuchsia) {
+    content_unittests_filter = {
+      test_name = "content_unittests"
+
+      # IsSupportedVideoConfig_VP9TransferFunctions fails on all cast builds since
+      # the cast IsSupportedVideoConfigs ignore the transfer function parameter.
+      # (b/36984215).
+      gtest_excludes = [ "*.IsSupportedVideoConfig_VP9TransferFunctions" ]
+      if (target_os == "linux" && !is_cast_desktop_build) {
+        # DesktopCaptureDeviceTest.*: No capture device on Eureka
+        # Disable PepperGamepadHostTest.WaitForReply (pepper not supported on Eureka)
+        # Disable RenderWidgetHostTest.Background because we disable the
+        # blacklist to enable WebGL (b/16142554)
+        gtest_excludes += [
+          "LegacyDomStorageDatabaseTest.TestCanOpenAndReadWebCoreDatabase",
+          "DesktopCaptureDeviceTest.Capture",
+          "GamepadProviderTest.PollingAccess",
+          "PepperGamepadHostTest.WaitForReply",
+          "RenderWidgetHostTest.Background",
+        ]
+      }
+      if (is_cast_audio_only) {
+        # No way to display URL's on audio only cast devices.
+        gtest_excludes += [ "NavigationEntryTest.NavigationEntryURLs" ]
+      }
+      if (enable_assistant && !is_cast_desktop_build) {
+        # Temporarily disable DefaultConstructor on assistant device builds. Cause
+        # of failure is unclear, but it's highly likely it's related to them being
+        # DEATH tests. These were passing until the is_official_build flag was
+        # enabled. These tests are considered non-critical in this context.
+        # (b/62469368)
+        gtest_excludes += [ "WebBluetoothDeviceIdTest.DefaultConstructor" ]
+      }
+    }
+    filters += [ content_unittests_filter ]
+  }
 
   media_unittests_filter = {
     test_name = "media_unittests"
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index 821f8e0ff..764c339 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -39,8 +39,11 @@
     "//base",
     "//chromecast:chromecast_buildflags",
     "//chromecast/base",
-    "//components/cdm/browser",
   ]
+
+  if (enable_media_drm_storage) {
+    deps += [ "//components/cdm/browser" ]
+  }
 }
 
 cast_source_set("prefs_simple") {
@@ -255,7 +258,6 @@
     "//chromecast/ui:display_settings_manager",
     "//chromecast/ui:display_settings_public",
     "//components/cast/message_port:message_port_cast",
-    "//components/cdm/browser",
     "//components/download/public/common:public",
     "//components/heap_profiling/multi_process",
     "//components/media_control/browser",
@@ -314,6 +316,10 @@
     "//ui/gl",
   ]
 
+  if (enable_media_drm_storage) {
+    deps += [ "//components/cdm/browser" ]
+  }
+
   if (is_android) {
     sources += [
       "android/cast_content_window_android.cc",
diff --git a/chromecast/browser/cast_download_manager_delegate.cc b/chromecast/browser/cast_download_manager_delegate.cc
index bd47823..0232b19 100644
--- a/chromecast/browser/cast_download_manager_delegate.cc
+++ b/chromecast/browser/cast_download_manager_delegate.cc
@@ -33,7 +33,7 @@
       empty, download::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
       download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT,
       download::DownloadItem::MixedContentStatus::UNKNOWN, empty, empty,
-      std::string() /*mime_type*/, absl::nullopt /*download_schedule*/,
+      std::string() /*mime_type*/,
       download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
   return true;
 }
diff --git a/chromecast/common/BUILD.gn b/chromecast/common/BUILD.gn
index 7e31143..f733f0d5770 100644
--- a/chromecast/common/BUILD.gn
+++ b/chromecast/common/BUILD.gn
@@ -38,7 +38,9 @@
   deps = [
     "//base",
     "//components/url_matcher",
-    "//content/public/common",
+    "//services/network/public/cpp:cpp_base",
+    "//third_party/blink/public/common:common",
+    "//third_party/blink/public/common:headers",
     "//url",
   ]
 }
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 569ac60cd..85f807e 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -76,9 +76,9 @@
   ]
   if (is_chromeos_ash) {
     deps += [
+      "//chromeos/ash/components/network:test_support",
       "//chromeos/dbus:test_support",
       "//chromeos/login/login_state:test_support",
-      "//chromeos/network:test_support",
       "//google_apis",
       "//net:test_support",
       "//services/network:test_support",
@@ -115,13 +115,14 @@
     deps += [
       ":test_support",
       "//chromeos/ash/components:unit_tests",
+      "//chromeos/ash/components/network:test_support",
+      "//chromeos/ash/services:unit_tests",
       "//chromeos/crosapi/cpp:unit_tests",
       "//chromeos/crosapi/mojom:unit_tests",
       "//chromeos/dbus:test_support",
       "//chromeos/dbus:unit_tests",
       "//chromeos/language/language_packs:unit_tests",
       "//chromeos/login/login_state:unit_tests",
-      "//chromeos/network:test_support",
       "//chromeos/network:unit_tests",
       "//chromeos/printing:unit_tests",
       "//chromeos/process_proxy:unit_tests",
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 7e04d77..0f1c655 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-14917.0.0
\ No newline at end of file
+14929.0.0
\ No newline at end of file
diff --git a/chromeos/ash/components/dbus/BUILD.gn b/chromeos/ash/components/dbus/BUILD.gn
index 54ae8239..ce218ec8 100644
--- a/chromeos/ash/components/dbus/BUILD.gn
+++ b/chromeos/ash/components/dbus/BUILD.gn
@@ -24,6 +24,8 @@
     "//chromeos/ash/components/dbus/services:unit_tests",
     "//chromeos/ash/components/dbus/session_manager",
     "//chromeos/ash/components/dbus/system_clock:unit_tests",
+    "//chromeos/ash/components/dbus/userdataauth",
+    "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus:test_support",
     "//components/account_id",
     "//dbus",
@@ -37,5 +39,10 @@
     "biod/biod_client_unittest.cc",
     "biod/fake_biod_client_unittest.cc",
     "hiberman/hiberman_client_unittest.cc",
+    "userdataauth/arc_quota_client_unittest.cc",
+    "userdataauth/cryptohome_misc_client_unittest.cc",
+    "userdataauth/cryptohome_pkcs11_client_unittest.cc",
+    "userdataauth/install_attributes_client_unittest.cc",
+    "userdataauth/userdataauth_client_unittest.cc",
   ]
 }
diff --git a/chromeos/ash/components/dbus/cicerone/fake_cicerone_client.cc b/chromeos/ash/components/dbus/cicerone/fake_cicerone_client.cc
index 5e73eed..bb4e707 100644
--- a/chromeos/ash/components/dbus/cicerone/fake_cicerone_client.cc
+++ b/chromeos/ash/components/dbus/cicerone/fake_cicerone_client.cc
@@ -439,6 +439,7 @@
 void FakeCiceroneClient::AddFileWatch(
     const vm_tools::cicerone::AddFileWatchRequest& request,
     DBusMethodCallback<vm_tools::cicerone::AddFileWatchResponse> callback) {
+  add_file_watch_call_count_++;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), add_file_watch_response_));
 }
@@ -446,6 +447,7 @@
 void FakeCiceroneClient::RemoveFileWatch(
     const vm_tools::cicerone::RemoveFileWatchRequest& request,
     DBusMethodCallback<vm_tools::cicerone::RemoveFileWatchResponse> callback) {
+  remove_file_watch_call_count_++;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::BindOnce(std::move(callback), remove_file_watch_response_));
diff --git a/chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h b/chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h
index d6886aa..701d8e9 100644
--- a/chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h
+++ b/chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h
@@ -374,6 +374,9 @@
     return configure_for_arc_sideload_called_;
   }
 
+  int add_file_watch_call_count() { return add_file_watch_call_count_; }
+  int remove_file_watch_call_count() { return remove_file_watch_call_count_; }
+
   // Additional functions to allow tests to trigger Signals.
   void NotifyLxdContainerCreated(
       const vm_tools::cicerone::LxdContainerCreatedSignal& signal);
@@ -442,6 +445,9 @@
 
   bool configure_for_arc_sideload_called_ = false;
 
+  int add_file_watch_call_count_ = 0;
+  int remove_file_watch_call_count_ = 0;
+
   vm_tools::cicerone::LxdContainerCreatedSignal_Status
       lxd_container_created_signal_status_ =
           vm_tools::cicerone::LxdContainerCreatedSignal::CREATED;
diff --git a/chromeos/ash/components/dbus/cros_healthd/BUILD.gn b/chromeos/ash/components/dbus/cros_healthd/BUILD.gn
index 9b2e41ac..983ae514 100644
--- a/chromeos/ash/components/dbus/cros_healthd/BUILD.gn
+++ b/chromeos/ash/components/dbus/cros_healthd/BUILD.gn
@@ -11,7 +11,7 @@
 
   deps = [
     "//base",
-    "//chromeos/services/cros_healthd/public/mojom",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//chromeos/services/network_health/public/mojom",
     "//dbus",
     "//mojo/public/cpp/bindings",
diff --git a/chromeos/ash/components/dbus/cros_healthd/DEPS b/chromeos/ash/components/dbus/cros_healthd/DEPS
index c939e19..022112e 100644
--- a/chromeos/ash/components/dbus/cros_healthd/DEPS
+++ b/chromeos/ash/components/dbus/cros_healthd/DEPS
@@ -1,5 +1,5 @@
 include_rules = [
-  "+chromeos/services/cros_healthd/public/mojom",
+  "+chromeos/ash/services/cros_healthd/public/mojom",
   "+chromeos/services/network_health/public/mojom",
   "+mojo/public",
 ]
diff --git a/chromeos/ash/components/dbus/cros_healthd/cros_healthd_client.h b/chromeos/ash/components/dbus/cros_healthd/cros_healthd_client.h
index ea7aa8d1..04ff1ff 100644
--- a/chromeos/ash/components/dbus/cros_healthd/cros_healthd_client.h
+++ b/chromeos/ash/components/dbus/cros_healthd/cros_healthd_client.h
@@ -8,8 +8,8 @@
 #include "base/callback_forward.h"
 #include "base/component_export.h"
 #include "base/files/scoped_file.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
diff --git a/chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.cc b/chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.cc
index a5330d1..552f0da 100644
--- a/chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.cc
+++ b/chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.cc
@@ -5,7 +5,7 @@
 #include "chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.h"
 
 #include "base/callback.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 
 namespace ash::cros_healthd {
 
diff --git a/chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.h b/chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.h
index 1f303a0..03fd7c3 100644
--- a/chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.h
+++ b/chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.h
@@ -7,7 +7,7 @@
 
 #include "base/callback_forward.h"
 #include "chromeos/ash/components/dbus/cros_healthd/cros_healthd_client.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 namespace ash::cros_healthd {
diff --git a/chromeos/dbus/fusebox/DIR_METADATA b/chromeos/ash/components/dbus/fusebox/DIR_METADATA
similarity index 100%
rename from chromeos/dbus/fusebox/DIR_METADATA
rename to chromeos/ash/components/dbus/fusebox/DIR_METADATA
diff --git a/chromeos/ash/components/dbus/rgbkbd/rgbkbd_client.cc b/chromeos/ash/components/dbus/rgbkbd/rgbkbd_client.cc
index 2e9e696..da77420 100644
--- a/chromeos/ash/components/dbus/rgbkbd/rgbkbd_client.cc
+++ b/chromeos/ash/components/dbus/rgbkbd/rgbkbd_client.cc
@@ -26,7 +26,11 @@
   RgbkbdClientImpl() = default;
   RgbkbdClientImpl(const RgbkbdClientImpl&) = delete;
   RgbkbdClientImpl& operator=(const RgbkbdClientImpl&) = delete;
-  ~RgbkbdClientImpl() override = default;
+  ~RgbkbdClientImpl() override {
+    for (auto& observer : observers_) {
+      observer.OnShutdown();
+    }
+  }
 
   void GetRgbKeyboardCapabilities(
       GetRgbKeyboardCapabilitiesCallback callback) override {
@@ -118,6 +122,28 @@
         rgbkbd::RgbKeyboardCapabilities(keyboard_capabilities));
   }
 
+  void CapabilityUpdatedForTestingReceived(dbus::Signal* signal) {
+    dbus::MessageReader reader(signal);
+    uint32_t capability;
+
+    if (!reader.PopUint32(&capability)) {
+      LOG(ERROR) << "rgbkbd: Error reading capability for testing response: "
+                 << signal->ToString();
+      return;
+    }
+    for (auto& observer : observers_) {
+      observer.OnCapabilityUpdatedForTesting(  // IN-TEST
+          rgbkbd::RgbKeyboardCapabilities(capability));
+    }
+  }
+
+  void CapabilityUpdatedForTestingConnected(const std::string& interface_name,
+                                            const std::string& signal_name,
+                                            bool success) {
+    LOG_IF(WARNING, !success)
+        << "Failed to connect to CapabilityUpdatedForTesting signal.";
+  }
+
   dbus::ObjectProxy* rgbkbd_proxy_ = nullptr;
 
   // Note: This should remain the last member so it'll be destroyed and
@@ -131,6 +157,14 @@
   CHECK(bus);
   rgbkbd_proxy_ = bus->GetObjectProxy(
       rgbkbd::kRgbkbdServiceName, dbus::ObjectPath(rgbkbd::kRgbkbdServicePath));
+
+  rgbkbd_proxy_->ConnectToSignal(
+      rgbkbd::kRgbkbdServiceName, rgbkbd::kCapabilityUpdatedForTesting,
+      base::BindRepeating(
+          &RgbkbdClientImpl::CapabilityUpdatedForTestingReceived,
+          weak_ptr_factory_.GetWeakPtr()),
+      base::BindOnce(&RgbkbdClientImpl::CapabilityUpdatedForTestingConnected,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 RgbkbdClient::RgbkbdClient() {
@@ -165,4 +199,12 @@
   return g_instance;
 }
 
+void RgbkbdClient::AddObserver(RgbkbdClient::Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void RgbkbdClient::RemoveObserver(RgbkbdClient::Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 }  // namespace ash
diff --git a/chromeos/ash/components/dbus/rgbkbd/rgbkbd_client.h b/chromeos/ash/components/dbus/rgbkbd/rgbkbd_client.h
index 6466416..a4f7be5 100644
--- a/chromeos/ash/components/dbus/rgbkbd/rgbkbd_client.h
+++ b/chromeos/ash/components/dbus/rgbkbd/rgbkbd_client.h
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include "base/component_export.h"
+#include "base/observer_list.h"
 #include "chromeos/dbus/common/dbus_client.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
 #include "third_party/cros_system_api/dbus/rgbkbd/dbus-constants.h"
@@ -24,6 +25,17 @@
   using GetRgbKeyboardCapabilitiesCallback =
       DBusMethodCallback<rgbkbd::RgbKeyboardCapabilities>;
 
+  class Observer : public base::CheckedObserver {
+   public:
+    ~Observer() override = default;
+    virtual void OnCapabilityUpdatedForTesting(
+        rgbkbd::RgbKeyboardCapabilities capability) = 0;
+    virtual void OnShutdown() = 0;
+  };
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
   RgbkbdClient(const RgbkbdClient&) = delete;
   RgbkbdClient& operator=(const RgbkbdClient&) = delete;
 
@@ -54,6 +66,8 @@
   // Initialize/Shutdown should be used instead.
   RgbkbdClient();
   virtual ~RgbkbdClient();
+
+  base::ObserverList<Observer> observers_;
 };
 
 }  // namespace ash
diff --git a/chromeos/ash/components/dbus/session_manager/BUILD.gn b/chromeos/ash/components/dbus/session_manager/BUILD.gn
index 71848e0f..ffc1ad13 100644
--- a/chromeos/ash/components/dbus/session_manager/BUILD.gn
+++ b/chromeos/ash/components/dbus/session_manager/BUILD.gn
@@ -14,11 +14,11 @@
 
   deps = [
     "//base",
+    "//chromeos/ash/components/dbus/userdataauth",
     "//chromeos/dbus/common",
     "//chromeos/dbus/constants",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
-    "//chromeos/dbus/userdataauth",
     "//components/policy/proto",
     "//crypto",
     "//dbus",
diff --git a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
index e622be9..5dc975dcd 100644
--- a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
+++ b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
@@ -25,15 +25,15 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chromeos/ash/components/dbus/login_manager/policy_descriptor.pb.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/cryptohome/account_identifier_operators.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "crypto/sha2.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cros_system_api/switches/chrome_switches.h"
 
-namespace chromeos {
+namespace ash {
 
 using RetrievePolicyCallback = FakeSessionManagerClient::RetrievePolicyCallback;
 using RetrievePolicyResponseType =
@@ -181,8 +181,8 @@
   switch (descriptor.account_type()) {
     case login_manager::ACCOUNT_TYPE_DEVICE: {
       base::FilePath owner_key_path;
-      CHECK(
-          base::PathService::Get(dbus_paths::FILE_OWNER_KEY, &owner_key_path));
+      CHECK(base::PathService::Get(chromeos::dbus_paths::FILE_OWNER_KEY,
+                                   &owner_key_path));
       if (key_path)
         *key_path = owner_key_path;
       return owner_key_path.DirName().Append(relative_policy_path);
@@ -191,8 +191,8 @@
     case login_manager::ACCOUNT_TYPE_USER:
     case login_manager::ACCOUNT_TYPE_DEVICE_LOCAL_ACCOUNT: {
       base::FilePath base_path;
-      CHECK(
-          base::PathService::Get(dbus_paths::DIR_USER_POLICY_KEYS, &base_path));
+      CHECK(base::PathService::Get(chromeos::dbus_paths::DIR_USER_POLICY_KEYS,
+                                   &base_path));
       if (key_path) {
         *key_path = base_path.Append(relative_policy_path.DirName())
                         .AppendASCII(kStubPerAccountPolicyKeyFileName);
@@ -646,7 +646,8 @@
 
   if (policy_storage_ == PolicyStorageType::kOnDisk) {
     base::FilePath owner_key_path;
-    CHECK(base::PathService::Get(dbus_paths::FILE_OWNER_KEY, &owner_key_path));
+    CHECK(base::PathService::Get(chromeos::dbus_paths::FILE_OWNER_KEY,
+                                 &owner_key_path));
     const base::FilePath state_keys_path =
         owner_key_path.DirName().AppendASCII(kStubStateKeysFileName);
     base::ThreadPool::PostTaskAndReplyWithResult(
@@ -878,4 +879,4 @@
   SessionManagerClient::Shutdown();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h
index 4755c351..ccc7504 100644
--- a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h
+++ b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h
@@ -18,7 +18,7 @@
 #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-namespace chromeos {
+namespace ash {
 
 // A fake implementation of session_manager. Accepts policy blobs to be set and
 // returns them unmodified.
@@ -444,11 +444,11 @@
   ~ScopedFakeInMemorySessionManagerClient();
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-// TODO(https://crbug.com/1164001): remove when moved to ash.
-namespace ash {
-using ::chromeos::FakeSessionManagerClient;
+// TODO(https://crbug.com/1164001): remove when the migration is finished.
+namespace chromeos {
+using ::ash::FakeSessionManagerClient;
 }
 
 #endif  // CHROMEOS_ASH_COMPONENTS_DBUS_SESSION_MANAGER_FAKE_SESSION_MANAGER_CLIENT_H_
diff --git a/chromeos/ash/components/dbus/session_manager/session_manager_client.cc b/chromeos/ash/components/dbus/session_manager/session_manager_client.cc
index b551fd7f..cd3c171 100644
--- a/chromeos/ash/components/dbus/session_manager/session_manager_client.cc
+++ b/chromeos/ash/components/dbus/session_manager/session_manager_client.cc
@@ -43,7 +43,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -708,8 +708,8 @@
     session_manager_proxy_ = bus->GetObjectProxy(
         login_manager::kSessionManagerServiceName,
         dbus::ObjectPath(login_manager::kSessionManagerServicePath));
-    blocking_method_caller_ =
-        std::make_unique<BlockingMethodCaller>(bus, session_manager_proxy_);
+    blocking_method_caller_ = std::make_unique<chromeos::BlockingMethodCaller>(
+        bus, session_manager_proxy_);
 
     // Signals emitted on the session manager's interface.
     session_manager_proxy_->ConnectToSignal(
@@ -1143,7 +1143,7 @@
   }
 
   dbus::ObjectProxy* session_manager_proxy_ = nullptr;
-  std::unique_ptr<BlockingMethodCaller> blocking_method_caller_;
+  std::unique_ptr<chromeos::BlockingMethodCaller> blocking_method_caller_;
   base::ObserverList<Observer>::Unchecked observers_{
       SessionManagerClient::kObserverListPolicy};
 
@@ -1200,4 +1200,4 @@
   return g_instance;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/ash/components/dbus/session_manager/session_manager_client.h b/chromeos/ash/components/dbus/session_manager/session_manager_client.h
index c2aee28..1d58c12 100644
--- a/chromeos/ash/components/dbus/session_manager/session_manager_client.h
+++ b/chromeos/ash/components/dbus/session_manager/session_manager_client.h
@@ -36,7 +36,7 @@
 class UpgradeArcContainerRequest;
 }  // namespace login_manager
 
-namespace chromeos {
+namespace ash {
 
 // SessionManagerClient is used to communicate with the session manager.
 class COMPONENT_EXPORT(SESSION_MANAGER) SessionManagerClient {
@@ -502,11 +502,11 @@
   virtual ~SessionManagerClient();
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-// TODO(https://crbug.com/1164001): remove when moved to ash.
-namespace ash {
-using ::chromeos::SessionManagerClient;
+// TODO(https://crbug.com/1164001): remove when the migration is finished.
+namespace chromeos {
+using ash::SessionManagerClient;
 }
 
 #endif  // CHROMEOS_ASH_COMPONENTS_DBUS_SESSION_MANAGER_SESSION_MANAGER_CLIENT_H_
diff --git a/chromeos/ash/components/dbus/spaced/fake_spaced_client.cc b/chromeos/ash/components/dbus/spaced/fake_spaced_client.cc
index c749bf1..5a3839a 100644
--- a/chromeos/ash/components/dbus/spaced/fake_spaced_client.cc
+++ b/chromeos/ash/components/dbus/spaced/fake_spaced_client.cc
@@ -6,22 +6,39 @@
 
 namespace ash {
 
-FakeSpacedClient::FakeSpacedClient() = default;
+namespace {
 
-FakeSpacedClient::~FakeSpacedClient() = default;
+FakeSpacedClient* g_instance = nullptr;
+
+}  // namespace
+
+// static
+FakeSpacedClient* FakeSpacedClient::Get() {
+  return g_instance;
+}
+
+FakeSpacedClient::FakeSpacedClient() {
+  DCHECK(!g_instance);
+  g_instance = this;
+}
+
+FakeSpacedClient::~FakeSpacedClient() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
 
 void FakeSpacedClient::GetFreeDiskSpace(const std::string& path,
                                         GetSizeCallback callback) {
-  std::move(callback).Run(absl::nullopt);
+  std::move(callback).Run(free_disk_space_);
 }
 
 void FakeSpacedClient::GetTotalDiskSpace(const std::string& path,
                                          GetSizeCallback callback) {
-  std::move(callback).Run(absl::nullopt);
+  std::move(callback).Run(total_disk_space_);
 }
 
 void FakeSpacedClient::GetRootDeviceSize(GetSizeCallback callback) {
-  std::move(callback).Run(absl::nullopt);
+  std::move(callback).Run(root_device_size_);
 }
 
 }  // namespace ash
diff --git a/chromeos/ash/components/dbus/spaced/fake_spaced_client.h b/chromeos/ash/components/dbus/spaced/fake_spaced_client.h
index 9bf9b82..33bd9f9 100644
--- a/chromeos/ash/components/dbus/spaced/fake_spaced_client.h
+++ b/chromeos/ash/components/dbus/spaced/fake_spaced_client.h
@@ -22,6 +22,9 @@
   FakeSpacedClient(const FakeSpacedClient&) = delete;
   FakeSpacedClient& operator=(const FakeSpacedClient&) = delete;
 
+  // Returns the fake global instance if initialized. May return null.
+  static FakeSpacedClient* Get();
+
   // FakeSpacedClient override:
   void GetFreeDiskSpace(const std::string& path,
                         GetSizeCallback callback) override;
@@ -31,6 +34,23 @@
 
   void GetRootDeviceSize(GetSizeCallback callback) override;
 
+  void set_free_disk_space(absl::optional<int64_t> space) {
+    free_disk_space_ = space;
+  }
+
+  void set_total_disk_space(absl::optional<int64_t> space) {
+    total_disk_space_ = space;
+  }
+
+  void set_root_device_size(absl::optional<int64_t> size) {
+    root_device_size_ = size;
+  }
+
+ private:
+  absl::optional<int64_t> free_disk_space_;
+  absl::optional<int64_t> total_disk_space_;
+  absl::optional<int64_t> root_device_size_;
+
   base::WeakPtrFactory<FakeSpacedClient> weak_ptr_factory_{this};
 };
 
diff --git a/chromeos/dbus/userdataauth/BUILD.gn b/chromeos/ash/components/dbus/userdataauth/BUILD.gn
similarity index 91%
rename from chromeos/dbus/userdataauth/BUILD.gn
rename to chromeos/ash/components/dbus/userdataauth/BUILD.gn
index 7c6421c..7f44bc4 100644
--- a/chromeos/dbus/userdataauth/BUILD.gn
+++ b/chromeos/ash/components/dbus/userdataauth/BUILD.gn
@@ -2,12 +2,13 @@
 # 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("//third_party/protobuf/proto_library.gni")
 
-assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
+assert(is_chromeos_ash, "Non-ChromeOS builds cannot depend on //chromeos/ash")
 
 component("userdataauth") {
-  output_name = "chromeos_dbus_userdataauth"
+  output_name = "ash_dbus_userdataauth"
 
   defines = [ "IS_USERDATAAUTH_CLIENT_IMPL" ]
 
diff --git a/chromeos/dbus/userdataauth/arc_quota_client.cc b/chromeos/ash/components/dbus/userdataauth/arc_quota_client.cc
similarity index 97%
rename from chromeos/dbus/userdataauth/arc_quota_client.cc
rename to chromeos/ash/components/dbus/userdataauth/arc_quota_client.cc
index b353054d..dfa80ca 100644
--- a/chromeos/dbus/userdataauth/arc_quota_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/arc_quota_client.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/dbus/userdataauth/arc_quota_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/arc_quota_client.h"
 
 #include <utility>
 
@@ -13,8 +13,8 @@
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_arc_quota_client.h"
 #include "chromeos/dbus/common/blocking_method_caller.h"
-#include "chromeos/dbus/userdataauth/fake_arc_quota_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/dbus/userdataauth/arc_quota_client.h b/chromeos/ash/components/dbus/userdataauth/arc_quota_client.h
similarity index 93%
rename from chromeos/dbus/userdataauth/arc_quota_client.h
rename to chromeos/ash/components/dbus/userdataauth/arc_quota_client.h
index 4e49a4b6..0e9066d 100644
--- a/chromeos/dbus/userdataauth/arc_quota_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/arc_quota_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_ARC_QUOTA_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_ARC_QUOTA_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_ARC_QUOTA_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_ARC_QUOTA_CLIENT_H_
 
 #include "base/callback.h"
 #include "base/component_export.h"
@@ -95,4 +95,4 @@
 using ::chromeos::ArcQuotaClient;
 }  // namespace ash
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_ARC_QUOTA_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_ARC_QUOTA_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/arc_quota_client_unittest.cc b/chromeos/ash/components/dbus/userdataauth/arc_quota_client_unittest.cc
similarity index 98%
rename from chromeos/dbus/userdataauth/arc_quota_client_unittest.cc
rename to chromeos/ash/components/dbus/userdataauth/arc_quota_client_unittest.cc
index 706ac40..7be010565 100644
--- a/chromeos/dbus/userdataauth/arc_quota_client_unittest.cc
+++ b/chromeos/ash/components/dbus/userdataauth/arc_quota_client_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/dbus/userdataauth/arc_quota_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/arc_quota_client.h"
 
 #include <string>
 #include <utility>
diff --git a/chromeos/dbus/userdataauth/cryptohome_misc_client.cc b/chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.cc
similarity index 98%
rename from chromeos/dbus/userdataauth/cryptohome_misc_client.cc
rename to chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.cc
index 054a27d..0b682578 100644
--- a/chromeos/dbus/userdataauth/cryptohome_misc_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.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/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 
 #include <memory>
 #include <utility>
@@ -14,8 +14,8 @@
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "chromeos/dbus/common/blocking_method_caller.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/dbus/userdataauth/cryptohome_misc_client.h b/chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h
similarity index 94%
rename from chromeos/dbus/userdataauth/cryptohome_misc_client.h
rename to chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h
index 4f60bbe..5bedbe68 100644
--- a/chromeos/dbus/userdataauth/cryptohome_misc_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_CRYPTOHOME_MISC_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_CRYPTOHOME_MISC_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_CRYPTOHOME_MISC_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_CRYPTOHOME_MISC_CLIENT_H_
 
 #include "base/callback.h"
 #include "base/component_export.h"
@@ -108,4 +108,4 @@
 using ::chromeos::CryptohomeMiscClient;
 }
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_CRYPTOHOME_MISC_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_CRYPTOHOME_MISC_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/cryptohome_misc_client_unittest.cc b/chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client_unittest.cc
similarity index 99%
rename from chromeos/dbus/userdataauth/cryptohome_misc_client_unittest.cc
rename to chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client_unittest.cc
index a5c6bc7..fd9be23 100644
--- a/chromeos/dbus/userdataauth/cryptohome_misc_client_unittest.cc
+++ b/chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client_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/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 
 #include <string>
 #include <utility>
diff --git a/chromeos/dbus/userdataauth/cryptohome_pkcs11_client.cc b/chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.cc
similarity index 97%
rename from chromeos/dbus/userdataauth/cryptohome_pkcs11_client.cc
rename to chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.cc
index 9a21117..78ea64c 100644
--- a/chromeos/dbus/userdataauth/cryptohome_pkcs11_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.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/dbus/userdataauth/cryptohome_pkcs11_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h"
 
 #include <utility>
 
@@ -13,8 +13,8 @@
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_pkcs11_client.h"
 #include "chromeos/dbus/common/blocking_method_caller.h"
-#include "chromeos/dbus/userdataauth/fake_cryptohome_pkcs11_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h b/chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h
similarity index 91%
rename from chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h
rename to chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h
index 4d794b1..524fc494 100644
--- a/chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_CRYPTOHOME_PKCS11_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_CRYPTOHOME_PKCS11_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_CRYPTOHOME_PKCS11_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_CRYPTOHOME_PKCS11_CLIENT_H_
 
 #include "base/callback.h"
 #include "base/component_export.h"
@@ -74,4 +74,4 @@
 using ::chromeos::CryptohomePkcs11Client;
 }  // namespace ash
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_CRYPTOHOME_PKCS11_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_CRYPTOHOME_PKCS11_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/cryptohome_pkcs11_client_unittest.cc b/chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client_unittest.cc
similarity index 98%
rename from chromeos/dbus/userdataauth/cryptohome_pkcs11_client_unittest.cc
rename to chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client_unittest.cc
index 8ba6510..64eaf16 100644
--- a/chromeos/dbus/userdataauth/cryptohome_pkcs11_client_unittest.cc
+++ b/chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client_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/dbus/userdataauth/cryptohome_pkcs11_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h"
 
 #include <string>
 #include <utility>
diff --git a/chromeos/dbus/userdataauth/fake_arc_quota_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_arc_quota_client.cc
similarity index 97%
rename from chromeos/dbus/userdataauth/fake_arc_quota_client.cc
rename to chromeos/ash/components/dbus/userdataauth/fake_arc_quota_client.cc
index ac493a0..1490b10 100644
--- a/chromeos/dbus/userdataauth/fake_arc_quota_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/fake_arc_quota_client.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/dbus/userdataauth/fake_arc_quota_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_arc_quota_client.h"
 
 #include "base/location.h"
 #include "base/notreached.h"
diff --git a/chromeos/dbus/userdataauth/fake_arc_quota_client.h b/chromeos/ash/components/dbus/userdataauth/fake_arc_quota_client.h
similarity index 89%
rename from chromeos/dbus/userdataauth/fake_arc_quota_client.h
rename to chromeos/ash/components/dbus/userdataauth/fake_arc_quota_client.h
index 0653e64..b466295 100644
--- a/chromeos/dbus/userdataauth/fake_arc_quota_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/fake_arc_quota_client.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_FAKE_ARC_QUOTA_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_FAKE_ARC_QUOTA_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_ARC_QUOTA_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_ARC_QUOTA_CLIENT_H_
 
-#include "chromeos/dbus/userdataauth/arc_quota_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/arc_quota_client.h"
 
 #include "base/component_export.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
@@ -71,4 +71,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_FAKE_ARC_QUOTA_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_ARC_QUOTA_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/fake_cryptohome_misc_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.cc
similarity index 96%
rename from chromeos/dbus/userdataauth/fake_cryptohome_misc_client.cc
rename to chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.cc
index 72724fc..629b98b 100644
--- a/chromeos/dbus/userdataauth/fake_cryptohome_misc_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
 
 #include "base/location.h"
 #include "base/notreached.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 
 namespace chromeos {
 
diff --git a/chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h b/chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h
similarity index 93%
rename from chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h
rename to chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h
index cca8468..10ae7a4 100644
--- a/chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_MISC_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_MISC_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_MISC_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_MISC_CLIENT_H_
 
-#include "chromeos/dbus/userdataauth/cryptohome_misc_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 
 #include "base/component_export.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
@@ -137,4 +137,4 @@
 using ::chromeos::FakeCryptohomeMiscClient;
 }
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_MISC_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_MISC_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/fake_cryptohome_pkcs11_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_cryptohome_pkcs11_client.cc
similarity index 96%
rename from chromeos/dbus/userdataauth/fake_cryptohome_pkcs11_client.cc
rename to chromeos/ash/components/dbus/userdataauth/fake_cryptohome_pkcs11_client.cc
index 0451ca9..4e2eaf9 100644
--- a/chromeos/dbus/userdataauth/fake_cryptohome_pkcs11_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/fake_cryptohome_pkcs11_client.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/dbus/userdataauth/fake_cryptohome_pkcs11_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_pkcs11_client.h"
 
 #include "base/location.h"
 #include "base/notreached.h"
diff --git a/chromeos/dbus/userdataauth/fake_cryptohome_pkcs11_client.h b/chromeos/ash/components/dbus/userdataauth/fake_cryptohome_pkcs11_client.h
similarity index 87%
rename from chromeos/dbus/userdataauth/fake_cryptohome_pkcs11_client.h
rename to chromeos/ash/components/dbus/userdataauth/fake_cryptohome_pkcs11_client.h
index 8d07ea2..7d7efd1 100644
--- a/chromeos/dbus/userdataauth/fake_cryptohome_pkcs11_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/fake_cryptohome_pkcs11_client.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_PKCS11_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_PKCS11_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_PKCS11_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_PKCS11_CLIENT_H_
 
-#include "chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h"
 
 #include "base/component_export.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
@@ -65,4 +65,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_PKCS11_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_CRYPTOHOME_PKCS11_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/fake_install_attributes_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc
similarity index 98%
rename from chromeos/dbus/userdataauth/fake_install_attributes_client.cc
rename to chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.cc
index 3868cde..0c78ae6 100644
--- a/chromeos/dbus/userdataauth/fake_install_attributes_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.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/dbus/userdataauth/fake_install_attributes_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.h"
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
diff --git a/chromeos/dbus/userdataauth/fake_install_attributes_client.h b/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.h
similarity index 93%
rename from chromeos/dbus/userdataauth/fake_install_attributes_client.h
rename to chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.h
index c18fdeb..744f67c 100644
--- a/chromeos/dbus/userdataauth/fake_install_attributes_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_FAKE_INSTALL_ATTRIBUTES_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_FAKE_INSTALL_ATTRIBUTES_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_INSTALL_ATTRIBUTES_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_INSTALL_ATTRIBUTES_CLIENT_H_
 
-#include "chromeos/dbus/userdataauth/install_attributes_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_client.h"
 
 #include "base/component_export.h"
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
@@ -127,4 +127,4 @@
 using ::chromeos::FakeInstallAttributesClient;
 }
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_FAKE_INSTALL_ATTRIBUTES_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_INSTALL_ATTRIBUTES_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/fake_userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc
similarity index 99%
rename from chromeos/dbus/userdataauth/fake_userdataauth_client.cc
rename to chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc
index ed3282f4..82c483a 100644
--- a/chromeos/dbus/userdataauth/fake_userdataauth_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.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/dbus/userdataauth/fake_userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 
 #include <utility>
 
diff --git a/chromeos/dbus/userdataauth/fake_userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h
similarity index 97%
rename from chromeos/dbus/userdataauth/fake_userdataauth_client.h
rename to chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h
index b2226bb..4492a2f 100644
--- a/chromeos/dbus/userdataauth/fake_userdataauth_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_FAKE_USERDATAAUTH_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_FAKE_USERDATAAUTH_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_USERDATAAUTH_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_USERDATAAUTH_CLIENT_H_
 
 #include "base/memory/raw_ptr.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
 
 #include <set>
 
@@ -408,4 +408,4 @@
 using ::chromeos::FakeUserDataAuthClient;
 }
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_FAKE_USERDATAAUTH_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_FAKE_USERDATAAUTH_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/install_attributes_client.cc b/chromeos/ash/components/dbus/userdataauth/install_attributes_client.cc
similarity index 98%
rename from chromeos/dbus/userdataauth/install_attributes_client.cc
rename to chromeos/ash/components/dbus/userdataauth/install_attributes_client.cc
index 5b4632e..2daa8e1d 100644
--- a/chromeos/dbus/userdataauth/install_attributes_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/install_attributes_client.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/dbus/userdataauth/install_attributes_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_client.h"
 
 #include <memory>
 #include <utility>
@@ -14,8 +14,8 @@
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_install_attributes_client.h"
 #include "chromeos/dbus/common/blocking_method_caller.h"
-#include "chromeos/dbus/userdataauth/fake_install_attributes_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/dbus/userdataauth/install_attributes_client.h b/chromeos/ash/components/dbus/userdataauth/install_attributes_client.h
similarity index 95%
rename from chromeos/dbus/userdataauth/install_attributes_client.h
rename to chromeos/ash/components/dbus/userdataauth/install_attributes_client.h
index 0226793..5b7668f1 100644
--- a/chromeos/dbus/userdataauth/install_attributes_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/install_attributes_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_CLIENT_H_
 
 #include "base/callback.h"
 #include "base/component_export.h"
@@ -125,4 +125,4 @@
 using ::chromeos::InstallAttributesClient;
 }
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/install_attributes_client_unittest.cc b/chromeos/ash/components/dbus/userdataauth/install_attributes_client_unittest.cc
similarity index 99%
rename from chromeos/dbus/userdataauth/install_attributes_client_unittest.cc
rename to chromeos/ash/components/dbus/userdataauth/install_attributes_client_unittest.cc
index 96f6f85..ba1fe26 100644
--- a/chromeos/dbus/userdataauth/install_attributes_client_unittest.cc
+++ b/chromeos/ash/components/dbus/userdataauth/install_attributes_client_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/dbus/userdataauth/install_attributes_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_client.h"
 
 #include <string>
 #include <utility>
diff --git a/chromeos/dbus/userdataauth/install_attributes_util.cc b/chromeos/ash/components/dbus/userdataauth/install_attributes_util.cc
similarity index 95%
rename from chromeos/dbus/userdataauth/install_attributes_util.cc
rename to chromeos/ash/components/dbus/userdataauth/install_attributes_util.cc
index 2609f01..a8851ce 100644
--- a/chromeos/dbus/userdataauth/install_attributes_util.cc
+++ b/chromeos/ash/components/dbus/userdataauth/install_attributes_util.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/userdataauth/install_attributes_util.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_util.h"
 
 #include <stdint.h>
 
 #include "base/bind.h"
 #include "base/check_op.h"
 #include "base/logging.h"
-#include "chromeos/dbus/userdataauth/install_attributes_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_client.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace chromeos {
diff --git a/chromeos/dbus/userdataauth/install_attributes_util.h b/chromeos/ash/components/dbus/userdataauth/install_attributes_util.h
similarity index 84%
rename from chromeos/dbus/userdataauth/install_attributes_util.h
rename to chromeos/ash/components/dbus/userdataauth/install_attributes_util.h
index 57bd2c4..a157a82 100644
--- a/chromeos/dbus/userdataauth/install_attributes_util.h
+++ b/chromeos/ash/components/dbus/userdataauth/install_attributes_util.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_UTIL_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_UTIL_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_UTIL_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_UTIL_H_
 
 #include <string>
 
 #include "base/component_export.h"
-#include "chromeos/dbus/userdataauth/install_attributes_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/install_attributes_client.h"
 
 namespace chromeos {
 
@@ -41,4 +41,4 @@
 using ::chromeos::install_attributes_util::InstallAttributesSet;
 }  // namespace ash::install_attributes_util
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_UTIL_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_INSTALL_ATTRIBUTES_UTIL_H_
diff --git a/chromeos/dbus/userdataauth/mock_userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.cc
similarity index 89%
rename from chromeos/dbus/userdataauth/mock_userdataauth_client.cc
rename to chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.cc
index e840f37f..fa0df208 100644
--- a/chromeos/dbus/userdataauth/mock_userdataauth_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.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/dbus/userdataauth/mock_userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h"
 
 #include <utility>
 
diff --git a/chromeos/dbus/userdataauth/mock_userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h
similarity index 95%
rename from chromeos/dbus/userdataauth/mock_userdataauth_client.h
rename to chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h
index b86515e..a95e340 100644
--- a/chromeos/dbus/userdataauth/mock_userdataauth_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_MOCK_USERDATAAUTH_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_MOCK_USERDATAAUTH_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_MOCK_USERDATAAUTH_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_MOCK_USERDATAAUTH_CLIENT_H_
 
-#include "chromeos/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 
 #include "base/component_export.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -190,4 +190,4 @@
 using ::chromeos::UserDataAuthClient;
 }
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_MOCK_USERDATAAUTH_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_MOCK_USERDATAAUTH_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc
similarity index 98%
rename from chromeos/dbus/userdataauth/userdataauth_client.cc
rename to chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc
index 33dace7..dc5b77ca 100644
--- a/chromeos/dbus/userdataauth/userdataauth_client.cc
+++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.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/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 
 #include <utility>
 
@@ -13,7 +13,7 @@
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/userdataauth/fake_userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/dbus/userdataauth/userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h
similarity index 97%
rename from chromeos/dbus/userdataauth/userdataauth_client.h
rename to chromeos/ash/components/dbus/userdataauth/userdataauth_client.h
index 63388cc..b3ace823 100644
--- a/chromeos/dbus/userdataauth/userdataauth_client.h
+++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_USERDATAAUTH_USERDATAAUTH_CLIENT_H_
-#define CHROMEOS_DBUS_USERDATAAUTH_USERDATAAUTH_CLIENT_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_USERDATAAUTH_CLIENT_H_
+#define CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_USERDATAAUTH_CLIENT_H_
 
 #include "base/callback.h"
 #include "base/component_export.h"
@@ -301,4 +301,4 @@
 using ::chromeos::UserDataAuthClient;
 }
 
-#endif  // CHROMEOS_DBUS_USERDATAAUTH_USERDATAAUTH_CLIENT_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_DBUS_USERDATAAUTH_USERDATAAUTH_CLIENT_H_
diff --git a/chromeos/dbus/userdataauth/userdataauth_client_unittest.cc b/chromeos/ash/components/dbus/userdataauth/userdataauth_client_unittest.cc
similarity index 99%
rename from chromeos/dbus/userdataauth/userdataauth_client_unittest.cc
rename to chromeos/ash/components/dbus/userdataauth/userdataauth_client_unittest.cc
index 6b2d705..6862347 100644
--- a/chromeos/dbus/userdataauth/userdataauth_client_unittest.cc
+++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client_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/dbus/userdataauth/userdataauth_client.h"
+#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
 
 #include <string>
 #include <utility>
diff --git a/chromeos/ash/components/network/BUILD.gn b/chromeos/ash/components/network/BUILD.gn
index 8214a1a..11b41bd 100644
--- a/chromeos/ash/components/network/BUILD.gn
+++ b/chromeos/ash/components/network/BUILD.gn
@@ -65,9 +65,60 @@
   ]
 }
 
+source_set("test_support") {
+  testonly = true
+  public_deps = [
+    "//chromeos/components/onc",
+    "//chromeos/dbus/hermes",
+    "//chromeos/network",
+    "//dbus",
+  ]
+  deps = [
+    "//base",
+    "//chromeos:test_utils",
+    "//chromeos/components/onc:test_support",
+    "//chromeos/dbus:test_support",
+    "//chromeos/services/network_config/public/cpp",
+    "//chromeos/services/network_config/public/mojom",
+    "//components/onc",
+    "//components/sync_preferences:test_support",
+    "//dbus",
+    "//net:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+  sources = [
+    "fake_network_activation_handler.cc",
+    "fake_network_activation_handler.h",
+    "fake_network_connection_handler.cc",
+    "fake_network_connection_handler.h",
+    "fake_network_device_handler.cc",
+    "fake_network_device_handler.h",
+    "fake_stub_cellular_networks_provider.cc",
+    "fake_stub_cellular_networks_provider.h",
+    "mock_managed_network_configuration_handler.cc",
+    "mock_managed_network_configuration_handler.h",
+    "mock_network_device_handler.cc",
+    "mock_network_device_handler.h",
+    "mock_network_state_handler.cc",
+    "mock_network_state_handler.h",
+    "network_handler_test_helper.cc",
+    "network_handler_test_helper.h",
+    "network_state_test_helper.cc",
+    "network_state_test_helper.h",
+    "network_test_helper_base.cc",
+    "network_test_helper_base.h",
+    "system_token_cert_db_storage_test_util.cc",
+    "system_token_cert_db_storage_test_util.h",
+    "test_cellular_esim_profile_handler.cc",
+    "test_cellular_esim_profile_handler.h",
+  ]
+}
+
 source_set("unit_tests") {
   testonly = true
   deps = [
+    ":test_support",
     "//ash/constants",
     "//base",
     "//base/test:test_support",
@@ -78,7 +129,6 @@
     "//chromeos/dbus/shill",
     "//chromeos/login/login_state",
     "//chromeos/network",
-    "//chromeos/network:test_support",
     "//components/onc",
     "//components/prefs:test_support",
     "//crypto",
diff --git a/chromeos/ash/components/network/auto_connect_handler_unittest.cc b/chromeos/ash/components/network/auto_connect_handler_unittest.cc
index a74cc93e..7ba3cc7e 100644
--- a/chromeos/ash/components/network/auto_connect_handler_unittest.cc
+++ b/chromeos/ash/components/network/auto_connect_handler_unittest.cc
@@ -18,13 +18,13 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "chromeos/ash/components/network/client_cert_resolver.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/managed_network_configuration_handler_impl.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/system_token_cert_db_storage.h"
 #include "components/onc/onc_constants.h"
 #include "crypto/scoped_nss_types.h"
diff --git a/chromeos/ash/components/network/cellular_connection_handler_unittest.cc b/chromeos/ash/components/network/cellular_connection_handler_unittest.cc
index 8d3b1f3..d9bab65 100644
--- a/chromeos/ash/components/network/cellular_connection_handler_unittest.cc
+++ b/chromeos/ash/components/network/cellular_connection_handler_unittest.cc
@@ -15,11 +15,11 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
-#include "chromeos/network/fake_stub_cellular_networks_provider.h"
+#include "chromeos/ash/components/network/fake_stub_cellular_networks_provider.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/chromeos/ash/components/network/cellular_esim_installer_unittest.cc b/chromeos/ash/components/network/cellular_esim_installer_unittest.cc
index 9d72726..9111923 100644
--- a/chromeos/ash/components/network/cellular_esim_installer_unittest.cc
+++ b/chromeos/ash/components/network/cellular_esim_installer_unittest.cc
@@ -12,6 +12,9 @@
 #include "base/test/task_environment.h"
 #include "chromeos/ash/components/network/cellular_connection_handler.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/fake_stub_cellular_networks_provider.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/dbus/hermes/hermes_clients.h"
 #include "chromeos/dbus/hermes/hermes_euicc_client.h"
 #include "chromeos/dbus/hermes/hermes_manager_client.h"
@@ -21,14 +24,11 @@
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
-#include "chromeos/network/fake_network_connection_handler.h"
-#include "chromeos/network/fake_stub_cellular_networks_provider.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_device_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_ui_data.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "dbus/object_path.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/chromeos/ash/components/network/cellular_esim_profile_handler_impl_unittest.cc b/chromeos/ash/components/network/cellular_esim_profile_handler_impl_unittest.cc
index d7576ce..9d61075 100644
--- a/chromeos/ash/components/network/cellular_esim_profile_handler_impl_unittest.cc
+++ b/chromeos/ash/components/network/cellular_esim_profile_handler_impl_unittest.cc
@@ -14,11 +14,11 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/hermes/hermes_euicc_client.h"
 #include "chromeos/dbus/hermes/hermes_manager_client.h"
 #include "chromeos/dbus/hermes/hermes_profile_client.h"
 #include "chromeos/dbus/shill/fake_shill_device_client.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/network_type_pattern.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/ash/components/network/cellular_esim_uninstall_handler_unittest.cc b/chromeos/ash/components/network/cellular_esim_uninstall_handler_unittest.cc
index 485aff7..f86d3826 100644
--- a/chromeos/ash/components/network/cellular_esim_uninstall_handler_unittest.cc
+++ b/chromeos/ash/components/network/cellular_esim_uninstall_handler_unittest.cc
@@ -11,6 +11,9 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/fake_stub_cellular_networks_provider.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/dbus/hermes/hermes_clients.h"
 #include "chromeos/dbus/hermes/hermes_euicc_client.h"
 #include "chromeos/dbus/hermes/hermes_manager_client.h"
@@ -18,14 +21,11 @@
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
-#include "chromeos/network/fake_network_connection_handler.h"
-#include "chromeos/network/fake_stub_cellular_networks_provider.h"
 #include "chromeos/network/managed_cellular_pref_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_device_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "components/prefs/testing_pref_service.h"
 #include "dbus/object_path.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/ash/components/network/cellular_inhibitor_unittest.cc b/chromeos/ash/components/network/cellular_inhibitor_unittest.cc
index 386f372..bac5e34 100644
--- a/chromeos/ash/components/network/cellular_inhibitor_unittest.cc
+++ b/chromeos/ash/components/network/cellular_inhibitor_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill/fake_shill_device_client.h"
 #include "chromeos/dbus/shill/shill_clients.h"
@@ -20,7 +21,6 @@
 #include "chromeos/network/network_device_handler_impl.h"
 #include "chromeos/network/network_handler_callbacks.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/chromeos/ash/components/network/cellular_metrics_logger_unittest.cc b/chromeos/ash/components/network/cellular_metrics_logger_unittest.cc
index 080e00c..b7abb16 100644
--- a/chromeos/ash/components/network/cellular_metrics_logger_unittest.cc
+++ b/chromeos/ash/components/network/cellular_metrics_logger_unittest.cc
@@ -13,13 +13,13 @@
 #include "base/time/time.h"
 #include "chromeos/ash/components/network/cellular_esim_profile.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/components/feature_usage/feature_usage_metrics.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/network_ui_data.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "dbus/object_path.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/chromeos/ash/components/network/cellular_policy_handler_unittest.cc b/chromeos/ash/components/network/cellular_policy_handler_unittest.cc
index 50dd57f..c6bd1826 100644
--- a/chromeos/ash/components/network/cellular_policy_handler_unittest.cc
+++ b/chromeos/ash/components/network/cellular_policy_handler_unittest.cc
@@ -15,12 +15,13 @@
 #include "chromeos/ash/components/network/cellular_connection_handler.h"
 #include "chromeos/ash/components/network/cellular_esim_installer.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/components/onc/onc_utils.h"
 #include "chromeos/dbus/hermes/hermes_clients.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
-#include "chromeos/network/fake_network_connection_handler.h"
 #include "chromeos/network/managed_cellular_pref_handler.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
@@ -29,7 +30,6 @@
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/shill_property_util.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/chromeos/network/fake_network_activation_handler.cc b/chromeos/ash/components/network/fake_network_activation_handler.cc
similarity index 94%
rename from chromeos/network/fake_network_activation_handler.cc
rename to chromeos/ash/components/network/fake_network_activation_handler.cc
index 1d078ad..cf2712e 100644
--- a/chromeos/network/fake_network_activation_handler.cc
+++ b/chromeos/ash/components/network/fake_network_activation_handler.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/network/fake_network_activation_handler.h"
+#include "chromeos/ash/components/network/fake_network_activation_handler.h"
 
 #include "base/callback.h"
 
diff --git a/chromeos/network/fake_network_activation_handler.h b/chromeos/ash/components/network/fake_network_activation_handler.h
similarity index 89%
rename from chromeos/network/fake_network_activation_handler.h
rename to chromeos/ash/components/network/fake_network_activation_handler.h
index cd461d2e..49e109e 100644
--- a/chromeos/network/fake_network_activation_handler.h
+++ b/chromeos/ash/components/network/fake_network_activation_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_FAKE_NETWORK_ACTIVATION_HANDLER_H_
-#define CHROMEOS_NETWORK_FAKE_NETWORK_ACTIVATION_HANDLER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_NETWORK_ACTIVATION_HANDLER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_NETWORK_ACTIVATION_HANDLER_H_
 
 #include <string>
 
@@ -68,4 +68,4 @@
 using ::chromeos::FakeNetworkActivationHandler;
 }
 
-#endif  // CHROMEOS_NETWORK_FAKE_NETWORK_ACTIVATION_HANDLER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_NETWORK_ACTIVATION_HANDLER_H_
diff --git a/chromeos/network/fake_network_connection_handler.cc b/chromeos/ash/components/network/fake_network_connection_handler.cc
similarity index 97%
rename from chromeos/network/fake_network_connection_handler.cc
rename to chromeos/ash/components/network/fake_network_connection_handler.cc
index 7b7ffdb..78181e42 100644
--- a/chromeos/network/fake_network_connection_handler.cc
+++ b/chromeos/ash/components/network/fake_network_connection_handler.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/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
 
 #include <utility>
 
diff --git a/chromeos/network/fake_network_connection_handler.h b/chromeos/ash/components/network/fake_network_connection_handler.h
similarity index 93%
rename from chromeos/network/fake_network_connection_handler.h
rename to chromeos/ash/components/network/fake_network_connection_handler.h
index a14f62fc..0757cf40 100644
--- a/chromeos/network/fake_network_connection_handler.h
+++ b/chromeos/ash/components/network/fake_network_connection_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_FAKE_NETWORK_CONNECTION_HANDLER_H_
-#define CHROMEOS_NETWORK_FAKE_NETWORK_CONNECTION_HANDLER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_NETWORK_CONNECTION_HANDLER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_NETWORK_CONNECTION_HANDLER_H_
 
 #include <string>
 #include <vector>
@@ -99,4 +99,4 @@
 using ::chromeos::FakeNetworkConnectionHandler;
 }
 
-#endif  // CHROMEOS_NETWORK_FAKE_NETWORK_CONNECTION_HANDLER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_NETWORK_CONNECTION_HANDLER_H_
diff --git a/chromeos/network/fake_network_device_handler.cc b/chromeos/ash/components/network/fake_network_device_handler.cc
similarity index 96%
rename from chromeos/network/fake_network_device_handler.cc
rename to chromeos/ash/components/network/fake_network_device_handler.cc
index 635c1e0..8a4d656 100644
--- a/chromeos/network/fake_network_device_handler.cc
+++ b/chromeos/ash/components/network/fake_network_device_handler.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/network/fake_network_device_handler.h"
+#include "chromeos/ash/components/network/fake_network_device_handler.h"
 
 namespace chromeos {
 
diff --git a/chromeos/network/fake_network_device_handler.h b/chromeos/ash/components/network/fake_network_device_handler.h
similarity index 92%
rename from chromeos/network/fake_network_device_handler.h
rename to chromeos/ash/components/network/fake_network_device_handler.h
index 104c7b311..810ff85c 100644
--- a/chromeos/network/fake_network_device_handler.h
+++ b/chromeos/ash/components/network/fake_network_device_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_FAKE_NETWORK_DEVICE_HANDLER_H_
-#define CHROMEOS_NETWORK_FAKE_NETWORK_DEVICE_HANDLER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_NETWORK_DEVICE_HANDLER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_NETWORK_DEVICE_HANDLER_H_
 
 #include <string>
 #include <vector>
@@ -76,4 +76,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_NETWORK_FAKE_NETWORK_DEVICE_HANDLER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_NETWORK_DEVICE_HANDLER_H_
diff --git a/chromeos/network/fake_stub_cellular_networks_provider.cc b/chromeos/ash/components/network/fake_stub_cellular_networks_provider.cc
similarity index 98%
rename from chromeos/network/fake_stub_cellular_networks_provider.cc
rename to chromeos/ash/components/network/fake_stub_cellular_networks_provider.cc
index f367e6c..cc39900 100644
--- a/chromeos/network/fake_stub_cellular_networks_provider.cc
+++ b/chromeos/ash/components/network/fake_stub_cellular_networks_provider.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/network/fake_stub_cellular_networks_provider.h"
+#include "chromeos/ash/components/network/fake_stub_cellular_networks_provider.h"
 
 #include <algorithm>
 
diff --git a/chromeos/network/fake_stub_cellular_networks_provider.h b/chromeos/ash/components/network/fake_stub_cellular_networks_provider.h
similarity index 90%
rename from chromeos/network/fake_stub_cellular_networks_provider.h
rename to chromeos/ash/components/network/fake_stub_cellular_networks_provider.h
index 2485c68..5bcc4ce3 100644
--- a/chromeos/network/fake_stub_cellular_networks_provider.h
+++ b/chromeos/ash/components/network/fake_stub_cellular_networks_provider.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_FAKE_STUB_CELLULAR_NETWORKS_PROVIDER_H_
-#define CHROMEOS_NETWORK_FAKE_STUB_CELLULAR_NETWORKS_PROVIDER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_STUB_CELLULAR_NETWORKS_PROVIDER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_STUB_CELLULAR_NETWORKS_PROVIDER_H_
 
 #include <string>
 #include <utility>
@@ -60,4 +60,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_NETWORK_FAKE_STUB_CELLULAR_NETWORKS_PROVIDER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_FAKE_STUB_CELLULAR_NETWORKS_PROVIDER_H_
diff --git a/chromeos/ash/components/network/metrics/BUILD.gn b/chromeos/ash/components/network/metrics/BUILD.gn
index 8783043..7678a96 100644
--- a/chromeos/ash/components/network/metrics/BUILD.gn
+++ b/chromeos/ash/components/network/metrics/BUILD.gn
@@ -36,10 +36,10 @@
     "//ash/constants",
     "//base",
     "//base/test:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus/shill",
     "//chromeos/login/login_state",
     "//chromeos/network",
-    "//chromeos/network:test_support",
     "//components/prefs",
     "//components/prefs:test_support",
     "//testing/gtest",
diff --git a/chromeos/ash/components/network/metrics/connection_info_metrics_logger_unittest.cc b/chromeos/ash/components/network/metrics/connection_info_metrics_logger_unittest.cc
index fdf3064..47cfaf8 100644
--- a/chromeos/ash/components/network/metrics/connection_info_metrics_logger_unittest.cc
+++ b/chromeos/ash/components/network/metrics/connection_info_metrics_logger_unittest.cc
@@ -11,9 +11,9 @@
 #include "base/test/task_environment.h"
 #include "chromeos/ash/components/network/metrics/connection_results.h"
 #include "chromeos/ash/components/network/metrics/network_metrics_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_connection_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/ash/components/network/metrics/esim_policy_login_metrics_logger_unittest.cc b/chromeos/ash/components/network/metrics/esim_policy_login_metrics_logger_unittest.cc
index bc57ae89..e7b6964 100644
--- a/chromeos/ash/components/network/metrics/esim_policy_login_metrics_logger_unittest.cc
+++ b/chromeos/ash/components/network/metrics/esim_policy_login_metrics_logger_unittest.cc
@@ -10,12 +10,12 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/managed_network_configuration_handler_impl.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/network_ui_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/chromeos/ash/components/network/metrics/network_metrics_helper_unittest.cc b/chromeos/ash/components/network/metrics/network_metrics_helper_unittest.cc
index 798ad8e..e5cb2ce 100644
--- a/chromeos/ash/components/network/metrics/network_metrics_helper_unittest.cc
+++ b/chromeos/ash/components/network/metrics/network_metrics_helper_unittest.cc
@@ -9,9 +9,9 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_ui_data.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest-spi.h"
diff --git a/chromeos/ash/components/network/metrics/vpn_network_metrics_helper_unittest.cc b/chromeos/ash/components/network/metrics/vpn_network_metrics_helper_unittest.cc
index c424bfb..7b7db10 100644
--- a/chromeos/ash/components/network/metrics/vpn_network_metrics_helper_unittest.cc
+++ b/chromeos/ash/components/network/metrics/vpn_network_metrics_helper_unittest.cc
@@ -12,9 +12,9 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_configuration_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_ui_data.h"
 #include "chromeos/network/shill_property_util.h"
diff --git a/chromeos/network/mock_managed_network_configuration_handler.cc b/chromeos/ash/components/network/mock_managed_network_configuration_handler.cc
similarity index 82%
rename from chromeos/network/mock_managed_network_configuration_handler.cc
rename to chromeos/ash/components/network/mock_managed_network_configuration_handler.cc
index 7c227430..2a2fafc7 100644
--- a/chromeos/network/mock_managed_network_configuration_handler.cc
+++ b/chromeos/ash/components/network/mock_managed_network_configuration_handler.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/network/mock_managed_network_configuration_handler.h"
+#include "chromeos/ash/components/network/mock_managed_network_configuration_handler.h"
 
 namespace chromeos {
 
diff --git a/chromeos/network/mock_managed_network_configuration_handler.h b/chromeos/ash/components/network/mock_managed_network_configuration_handler.h
similarity index 95%
rename from chromeos/network/mock_managed_network_configuration_handler.h
rename to chromeos/ash/components/network/mock_managed_network_configuration_handler.h
index bb740904..10ebf00b 100644
--- a/chromeos/network/mock_managed_network_configuration_handler.h
+++ b/chromeos/ash/components/network/mock_managed_network_configuration_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_MOCK_MANAGED_NETWORK_CONFIGURATION_HANDLER_H_
-#define CHROMEOS_NETWORK_MOCK_MANAGED_NETWORK_CONFIGURATION_HANDLER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_MOCK_MANAGED_NETWORK_CONFIGURATION_HANDLER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_MOCK_MANAGED_NETWORK_CONFIGURATION_HANDLER_H_
 
 #include <string>
 
@@ -111,4 +111,4 @@
 using ::chromeos::MockManagedNetworkConfigurationHandler;
 }  // namespace ash
 
-#endif  // CHROMEOS_NETWORK_MOCK_MANAGED_NETWORK_CONFIGURATION_HANDLER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_MOCK_MANAGED_NETWORK_CONFIGURATION_HANDLER_H_
diff --git a/chromeos/network/mock_network_device_handler.cc b/chromeos/ash/components/network/mock_network_device_handler.cc
similarity index 82%
rename from chromeos/network/mock_network_device_handler.cc
rename to chromeos/ash/components/network/mock_network_device_handler.cc
index ffce5c1..ef97917 100644
--- a/chromeos/network/mock_network_device_handler.cc
+++ b/chromeos/ash/components/network/mock_network_device_handler.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/network/mock_network_device_handler.h"
+#include "chromeos/ash/components/network/mock_network_device_handler.h"
 
 namespace chromeos {
 
diff --git a/chromeos/network/mock_network_device_handler.h b/chromeos/ash/components/network/mock_network_device_handler.h
similarity index 93%
rename from chromeos/network/mock_network_device_handler.h
rename to chromeos/ash/components/network/mock_network_device_handler.h
index 863dc64..29361605 100644
--- a/chromeos/network/mock_network_device_handler.h
+++ b/chromeos/ash/components/network/mock_network_device_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_MOCK_NETWORK_DEVICE_HANDLER_H_
-#define CHROMEOS_NETWORK_MOCK_NETWORK_DEVICE_HANDLER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_MOCK_NETWORK_DEVICE_HANDLER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_MOCK_NETWORK_DEVICE_HANDLER_H_
 
 #include <string>
 #include <vector>
@@ -84,4 +84,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_NETWORK_MOCK_NETWORK_DEVICE_HANDLER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_MOCK_NETWORK_DEVICE_HANDLER_H_
diff --git a/chromeos/network/mock_network_state_handler.cc b/chromeos/ash/components/network/mock_network_state_handler.cc
similarity index 88%
rename from chromeos/network/mock_network_state_handler.cc
rename to chromeos/ash/components/network/mock_network_state_handler.cc
index 91343a2..d3e4a14 100644
--- a/chromeos/network/mock_network_state_handler.cc
+++ b/chromeos/ash/components/network/mock_network_state_handler.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/network/mock_network_state_handler.h"
+#include "chromeos/ash/components/network/mock_network_state_handler.h"
 
 namespace chromeos {
 
diff --git a/chromeos/network/mock_network_state_handler.h b/chromeos/ash/components/network/mock_network_state_handler.h
similarity index 81%
rename from chromeos/network/mock_network_state_handler.h
rename to chromeos/ash/components/network/mock_network_state_handler.h
index 445507e2..189bb5e 100644
--- a/chromeos/network/mock_network_state_handler.h
+++ b/chromeos/ash/components/network/mock_network_state_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_MOCK_NETWORK_STATE_HANDLER_H_
-#define CHROMEOS_NETWORK_MOCK_NETWORK_STATE_HANDLER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_MOCK_NETWORK_STATE_HANDLER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_MOCK_NETWORK_STATE_HANDLER_H_
 
 #include "chromeos/network/network_state_handler.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -32,4 +32,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_NETWORK_MOCK_NETWORK_STATE_HANDLER_H_
\ No newline at end of file
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_MOCK_NETWORK_STATE_HANDLER_H_
\ No newline at end of file
diff --git a/chromeos/network/network_handler_test_helper.cc b/chromeos/ash/components/network/network_handler_test_helper.cc
similarity index 91%
rename from chromeos/network/network_handler_test_helper.cc
rename to chromeos/ash/components/network/network_handler_test_helper.cc
index 390e0179..381228b 100644
--- a/chromeos/network/network_handler_test_helper.cc
+++ b/chromeos/ash/components/network/network_handler_test_helper.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 
 #include "chromeos/ash/components/network/cellular_esim_profile_handler_impl.h"
+#include "chromeos/ash/components/network/network_test_helper_base.h"
 #include "chromeos/network/managed_cellular_pref_handler.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_metadata_store.h"
-#include "chromeos/network/network_test_helper_base.h"
 #include "components/onc/onc_pref_names.h"
 
 namespace chromeos {
diff --git a/chromeos/network/network_handler_test_helper.h b/chromeos/ash/components/network/network_handler_test_helper.h
similarity index 82%
rename from chromeos/network/network_handler_test_helper.h
rename to chromeos/ash/components/network/network_handler_test_helper.h
index 0b1e744..55fd7c4 100644
--- a/chromeos/network/network_handler_test_helper.h
+++ b/chromeos/ash/components/network/network_handler_test_helper.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_NETWORK_HANDLER_TEST_HELPER_H_
-#define CHROMEOS_NETWORK_NETWORK_HANDLER_TEST_HELPER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_HANDLER_TEST_HELPER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_HANDLER_TEST_HELPER_H_
 
-#include "chromeos/network/network_test_helper_base.h"
+#include "chromeos/ash/components/network/network_test_helper_base.h"
 
 class PrefRegistrySimple;
 class PrefService;
@@ -44,4 +44,4 @@
 using ::chromeos::NetworkHandlerTestHelper;
 }
 
-#endif  // CHROMEOS_NETWORK_NETWORK_HANDLER_TEST_HELPER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_HANDLER_TEST_HELPER_H_
diff --git a/chromeos/network/network_state_test_helper.cc b/chromeos/ash/components/network/network_state_test_helper.cc
similarity index 95%
rename from chromeos/network/network_state_test_helper.cc
rename to chromeos/ash/components/network/network_state_test_helper.cc
index 9bae1e0..d55bfd5 100644
--- a/chromeos/network/network_state_test_helper.cc
+++ b/chromeos/ash/components/network/network_state_test_helper.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/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 
 #include "base/run_loop.h"
 #include "chromeos/dbus/hermes/hermes_clients.h"
diff --git a/chromeos/network/network_state_test_helper.h b/chromeos/ash/components/network/network_state_test_helper.h
similarity index 86%
rename from chromeos/network/network_state_test_helper.h
rename to chromeos/ash/components/network/network_state_test_helper.h
index 63e1b62b..a125eee5 100644
--- a/chromeos/network/network_state_test_helper.h
+++ b/chromeos/ash/components/network/network_state_test_helper.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_NETWORK_STATE_TEST_HELPER_H_
-#define CHROMEOS_NETWORK_NETWORK_STATE_TEST_HELPER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_STATE_TEST_HELPER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_STATE_TEST_HELPER_H_
 
-#include "chromeos/network/network_test_helper_base.h"
+#include "chromeos/ash/components/network/network_test_helper_base.h"
 
 namespace chromeos {
 
@@ -57,4 +57,4 @@
 using ::chromeos::NetworkStateTestHelper;
 }  // namespace ash
 
-#endif  // CHROMEOS_NETWORK_NETWORK_STATE_TEST_HELPER_H_
\ No newline at end of file
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_STATE_TEST_HELPER_H_
\ No newline at end of file
diff --git a/chromeos/network/network_test_helper_base.cc b/chromeos/ash/components/network/network_test_helper_base.cc
similarity index 98%
rename from chromeos/network/network_test_helper_base.cc
rename to chromeos/ash/components/network/network_test_helper_base.cc
index 09843376..24757f87 100644
--- a/chromeos/network/network_test_helper_base.cc
+++ b/chromeos/ash/components/network/network_test_helper_base.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/network/network_test_helper_base.h"
+#include "chromeos/ash/components/network/network_test_helper_base.h"
 
 #include "base/bind.h"
 #include "base/json/json_reader.h"
diff --git a/chromeos/network/network_test_helper_base.h b/chromeos/ash/components/network/network_test_helper_base.h
similarity index 95%
rename from chromeos/network/network_test_helper_base.h
rename to chromeos/ash/components/network/network_test_helper_base.h
index 1834c568..2beed63a 100644
--- a/chromeos/network/network_test_helper_base.h
+++ b/chromeos/ash/components/network/network_test_helper_base.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_NETWORK_TEST_HELPER_BASE_H_
-#define CHROMEOS_NETWORK_NETWORK_TEST_HELPER_BASE_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_TEST_HELPER_BASE_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_TEST_HELPER_BASE_H_
 
 #include <memory>
 #include <string>
@@ -125,4 +125,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_NETWORK_NETWORK_TEST_HELPER_BASE_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_NETWORK_TEST_HELPER_BASE_H_
diff --git a/chromeos/ash/components/network/proxy/BUILD.gn b/chromeos/ash/components/network/proxy/BUILD.gn
index 82fad61..83c8b65 100644
--- a/chromeos/ash/components/network/proxy/BUILD.gn
+++ b/chromeos/ash/components/network/proxy/BUILD.gn
@@ -37,9 +37,9 @@
   testonly = true
   deps = [
     "//base",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus/shill",
     "//chromeos/network",
-    "//chromeos/network:test_support",
     "//components/onc",
     "//components/prefs",
     "//components/prefs:test_support",
diff --git a/chromeos/ash/components/network/proxy/proxy_config_service_impl_unittest.cc b/chromeos/ash/components/network/proxy/proxy_config_service_impl_unittest.cc
index 1f21adb..819bea0 100644
--- a/chromeos/ash/components/network/proxy/proxy_config_service_impl_unittest.cc
+++ b/chromeos/ash/components/network/proxy/proxy_config_service_impl_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
-#include "chromeos/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
diff --git a/chromeos/ash/components/network/proxy/ui_proxy_config_service_unittest.cc b/chromeos/ash/components/network/proxy/ui_proxy_config_service_unittest.cc
index 747bb4bb..4df2710 100644
--- a/chromeos/ash/components/network/proxy/ui_proxy_config_service_unittest.cc
+++ b/chromeos/ash/components/network/proxy/ui_proxy_config_service_unittest.cc
@@ -13,10 +13,10 @@
 #include "base/strings/string_util.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/components/onc/onc_utils.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/onc/onc_pref_names.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
diff --git a/chromeos/network/system_token_cert_db_storage_test_util.cc b/chromeos/ash/components/network/system_token_cert_db_storage_test_util.cc
similarity index 95%
rename from chromeos/network/system_token_cert_db_storage_test_util.cc
rename to chromeos/ash/components/network/system_token_cert_db_storage_test_util.cc
index 50f3d7ab..883e186 100644
--- a/chromeos/network/system_token_cert_db_storage_test_util.cc
+++ b/chromeos/ash/components/network/system_token_cert_db_storage_test_util.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/network/system_token_cert_db_storage_test_util.h"
+#include "chromeos/ash/components/network/system_token_cert_db_storage_test_util.h"
 
 #include <memory>
 
diff --git a/chromeos/network/system_token_cert_db_storage_test_util.h b/chromeos/ash/components/network/system_token_cert_db_storage_test_util.h
similarity index 89%
rename from chromeos/network/system_token_cert_db_storage_test_util.h
rename to chromeos/ash/components/network/system_token_cert_db_storage_test_util.h
index d0d9f0f7..96dfaf73 100644
--- a/chromeos/network/system_token_cert_db_storage_test_util.h
+++ b/chromeos/ash/components/network/system_token_cert_db_storage_test_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_SYSTEM_TOKEN_CERT_DB_STORAGE_TEST_UTIL_H_
-#define CHROMEOS_NETWORK_SYSTEM_TOKEN_CERT_DB_STORAGE_TEST_UTIL_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_SYSTEM_TOKEN_CERT_DB_STORAGE_TEST_UTIL_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_SYSTEM_TOKEN_CERT_DB_STORAGE_TEST_UTIL_H_
 
 #include "chromeos/network/system_token_cert_db_storage.h"
 
@@ -76,4 +76,4 @@
 using ::chromeos::GetSystemTokenCertDbCallbackWrapper;
 }
 
-#endif  // CHROMEOS_NETWORK_SYSTEM_TOKEN_CERT_DB_STORAGE_TEST_UTIL_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_SYSTEM_TOKEN_CERT_DB_STORAGE_TEST_UTIL_H_
diff --git a/chromeos/network/test_cellular_esim_profile_handler.cc b/chromeos/ash/components/network/test_cellular_esim_profile_handler.cc
similarity index 96%
rename from chromeos/network/test_cellular_esim_profile_handler.cc
rename to chromeos/ash/components/network/test_cellular_esim_profile_handler.cc
index b690d60..b1ccd365 100644
--- a/chromeos/network/test_cellular_esim_profile_handler.cc
+++ b/chromeos/ash/components/network/test_cellular_esim_profile_handler.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/network/test_cellular_esim_profile_handler.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 
 #include "base/containers/contains.h"
 #include "chromeos/ash/components/network/cellular_utils.h"
diff --git a/chromeos/network/test_cellular_esim_profile_handler.h b/chromeos/ash/components/network/test_cellular_esim_profile_handler.h
similarity index 89%
rename from chromeos/network/test_cellular_esim_profile_handler.h
rename to chromeos/ash/components/network/test_cellular_esim_profile_handler.h
index 922eab7e..d5bfadd3 100644
--- a/chromeos/network/test_cellular_esim_profile_handler.h
+++ b/chromeos/ash/components/network/test_cellular_esim_profile_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_NETWORK_TEST_CELLULAR_ESIM_PROFILE_HANDLER_H_
-#define CHROMEOS_NETWORK_TEST_CELLULAR_ESIM_PROFILE_HANDLER_H_
+#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_TEST_CELLULAR_ESIM_PROFILE_HANDLER_H_
+#define CHROMEOS_ASH_COMPONENTS_NETWORK_TEST_CELLULAR_ESIM_PROFILE_HANDLER_H_
 
 #include <string>
 
@@ -54,4 +54,4 @@
 using ::chromeos::TestCellularESimProfileHandler;
 }
 
-#endif  // CHROMEOS_NETWORK_TEST_CELLULAR_ESIM_PROFILE_HANDLER_H_
+#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_TEST_CELLULAR_ESIM_PROFILE_HANDLER_H_
diff --git a/chromeos/ash/services/BUILD.gn b/chromeos/ash/services/BUILD.gn
new file mode 100644
index 0000000..28f2f6b
--- /dev/null
+++ b/chromeos/ash/services/BUILD.gn
@@ -0,0 +1,22 @@
+# 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.
+
+import("//build/config/chromeos/ui_mode.gni")
+
+assert(is_chromeos_ash)
+
+# Use this target for adding new unit tests. To add a unit test to this target,
+# create a "unit_tests" source_set in your service and add it as a dependency
+# here.
+#
+# Unit tests are generally preferred over service tests as they are simpler to
+# create and maintain. Check out service_manager::TestConnectorFactory for an
+# easy way to test your services.
+source_set("unit_tests") {
+  testonly = true
+  deps = [
+    "//chromeos/ash/services/cros_healthd/private/cpp:unit_tests",
+    "//chromeos/ash/services/cros_healthd/public/cpp:unit_tests",
+  ]
+}
diff --git a/chromeos/services/cros_healthd/DIR_METADATA b/chromeos/ash/services/cros_healthd/DIR_METADATA
similarity index 100%
rename from chromeos/services/cros_healthd/DIR_METADATA
rename to chromeos/ash/services/cros_healthd/DIR_METADATA
diff --git a/chromeos/services/cros_healthd/OWNERS b/chromeos/ash/services/cros_healthd/OWNERS
similarity index 100%
rename from chromeos/services/cros_healthd/OWNERS
rename to chromeos/ash/services/cros_healthd/OWNERS
diff --git a/chromeos/services/cros_healthd/private/cpp/BUILD.gn b/chromeos/ash/services/cros_healthd/private/cpp/BUILD.gn
similarity index 86%
rename from chromeos/services/cros_healthd/private/cpp/BUILD.gn
rename to chromeos/ash/services/cros_healthd/private/cpp/BUILD.gn
index 3714d2e..edce0db 100644
--- a/chromeos/services/cros_healthd/private/cpp/BUILD.gn
+++ b/chromeos/ash/services/cros_healthd/private/cpp/BUILD.gn
@@ -5,7 +5,7 @@
 import("//build/config/chromeos/args.gni")
 import("//build/config/chromeos/ui_mode.gni")
 
-assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
+assert(is_chromeos_ash)
 
 source_set("cpp") {
   sources = [
@@ -18,7 +18,7 @@
     "//ui/events/devices",
     "//ui/events/ozone/evdev:event_device_info",
   ]
-  public_deps = [ "//chromeos/services/cros_healthd/private/mojom" ]
+  public_deps = [ "//chromeos/ash/services/cros_healthd/private/mojom" ]
   defines = []
   if (is_chromeos_device) {
     defines += [ "USE_EVDEV_GESTURES" ]
diff --git a/chromeos/services/cros_healthd/private/cpp/DEPS b/chromeos/ash/services/cros_healthd/private/cpp/DEPS
similarity index 100%
rename from chromeos/services/cros_healthd/private/cpp/DEPS
rename to chromeos/ash/services/cros_healthd/private/cpp/DEPS
diff --git a/chromeos/services/cros_healthd/private/cpp/data_collector.cc b/chromeos/ash/services/cros_healthd/private/cpp/data_collector.cc
similarity index 98%
rename from chromeos/services/cros_healthd/private/cpp/data_collector.cc
rename to chromeos/ash/services/cros_healthd/private/cpp/data_collector.cc
index f70a4367..142df148 100644
--- a/chromeos/services/cros_healthd/private/cpp/data_collector.cc
+++ b/chromeos/ash/services/cros_healthd/private/cpp/data_collector.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/services/cros_healthd/private/cpp/data_collector.h"
+#include "chromeos/ash/services/cros_healthd/private/cpp/data_collector.h"
 
 #include <fcntl.h>
 
diff --git a/chromeos/services/cros_healthd/private/cpp/data_collector.h b/chromeos/ash/services/cros_healthd/private/cpp/data_collector.h
similarity index 83%
rename from chromeos/services/cros_healthd/private/cpp/data_collector.h
rename to chromeos/ash/services/cros_healthd/private/cpp/data_collector.h
index 13cd8bc4..8d68ffb3 100644
--- a/chromeos/services/cros_healthd/private/cpp/data_collector.h
+++ b/chromeos/ash/services/cros_healthd/private/cpp/data_collector.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_CROS_HEALTHD_PRIVATE_CPP_DATA_COLLECTOR_H_
-#define CHROMEOS_SERVICES_CROS_HEALTHD_PRIVATE_CPP_DATA_COLLECTOR_H_
+#ifndef CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PRIVATE_CPP_DATA_COLLECTOR_H_
+#define CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PRIVATE_CPP_DATA_COLLECTOR_H_
 
-#include "chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom.h"
+#include "chromeos/ash/services/cros_healthd/private/mojom/cros_healthd_internal.mojom.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 
 namespace chromeos {
@@ -57,4 +57,4 @@
 }  // namespace cros_healthd
 }  // namespace ash
 
-#endif  // CHROMEOS_SERVICES_CROS_HEALTHD_PRIVATE_CPP_DATA_COLLECTOR_H_
+#endif  // CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PRIVATE_CPP_DATA_COLLECTOR_H_
diff --git a/chromeos/services/cros_healthd/private/cpp/data_collector_unittest.cc b/chromeos/ash/services/cros_healthd/private/cpp/data_collector_unittest.cc
similarity index 97%
rename from chromeos/services/cros_healthd/private/cpp/data_collector_unittest.cc
rename to chromeos/ash/services/cros_healthd/private/cpp/data_collector_unittest.cc
index a6d5beb..c090f2a 100644
--- a/chromeos/services/cros_healthd/private/cpp/data_collector_unittest.cc
+++ b/chromeos/ash/services/cros_healthd/private/cpp/data_collector_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/services/cros_healthd/private/cpp/data_collector.h"
+#include "chromeos/ash/services/cros_healthd/private/cpp/data_collector.h"
 
 #include "base/notreached.h"
 #include "base/test/bind.h"
diff --git a/chromeos/services/cros_healthd/private/mojom/BUILD.gn b/chromeos/ash/services/cros_healthd/private/mojom/BUILD.gn
similarity index 81%
rename from chromeos/services/cros_healthd/private/mojom/BUILD.gn
rename to chromeos/ash/services/cros_healthd/private/mojom/BUILD.gn
index ce983ef..aa3736d 100644
--- a/chromeos/services/cros_healthd/private/mojom/BUILD.gn
+++ b/chromeos/ash/services/cros_healthd/private/mojom/BUILD.gn
@@ -2,8 +2,11 @@
 # 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("//mojo/public/tools/bindings/mojom.gni")
 
+assert(is_chromeos_ash)
+
 mojom("mojom") {
   sources = [ "cros_healthd_internal.mojom" ]
   public_deps = [ "//mojo/public/mojom/base" ]
diff --git a/chromeos/services/cros_healthd/private/mojom/OWNERS b/chromeos/ash/services/cros_healthd/private/mojom/OWNERS
similarity index 100%
rename from chromeos/services/cros_healthd/private/mojom/OWNERS
rename to chromeos/ash/services/cros_healthd/private/mojom/OWNERS
diff --git a/chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom b/chromeos/ash/services/cros_healthd/private/mojom/cros_healthd_internal.mojom
similarity index 100%
rename from chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom
rename to chromeos/ash/services/cros_healthd/private/mojom/cros_healthd_internal.mojom
diff --git a/chromeos/services/cros_healthd/public/cpp/BUILD.gn b/chromeos/ash/services/cros_healthd/public/cpp/BUILD.gn
similarity index 82%
rename from chromeos/services/cros_healthd/public/cpp/BUILD.gn
rename to chromeos/ash/services/cros_healthd/public/cpp/BUILD.gn
index fac3481b..c5a664aa 100644
--- a/chromeos/services/cros_healthd/public/cpp/BUILD.gn
+++ b/chromeos/ash/services/cros_healthd/public/cpp/BUILD.gn
@@ -3,9 +3,10 @@
 # found in the LICENSE file.
 
 import("//build/config/chromeos/args.gni")
+import("//build/config/chromeos/ui_mode.gni")
 import("//chromeos/dbus/config/use_real_dbus_clients.gni")
 
-assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
+assert(is_chromeos_ash)
 
 source_set("cpp") {
   defines = []
@@ -22,7 +23,7 @@
   deps = [
     "//base",
     "//chromeos/ash/components/dbus/cros_healthd",
-    "//chromeos/services/cros_healthd/public/mojom",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//ui/events/ozone/evdev:event_device_info",
   ]
   if (use_real_dbus_clients) {
@@ -41,11 +42,10 @@
   deps = [
     ":cpp",
     "//base/test:test_support",
-    "//chromeos/services/cros_healthd/public/mojom",
+    "//chromeos/ash/services/cros_healthd/public/mojom",
     "//mojo/core/embedder",
     "//mojo/public/cpp/bindings",
     "//testing/gmock",
     "//testing/gtest",
-    "//ui/events/ozone/evdev:event_device_info",
   ]
 }
diff --git a/chromeos/services/cros_healthd/public/cpp/DEPS b/chromeos/ash/services/cros_healthd/public/cpp/DEPS
similarity index 100%
rename from chromeos/services/cros_healthd/public/cpp/DEPS
rename to chromeos/ash/services/cros_healthd/public/cpp/DEPS
diff --git a/chromeos/services/cros_healthd/public/cpp/DIR_METADATA b/chromeos/ash/services/cros_healthd/public/cpp/DIR_METADATA
similarity index 100%
rename from chromeos/services/cros_healthd/public/cpp/DIR_METADATA
rename to chromeos/ash/services/cros_healthd/public/cpp/DIR_METADATA
diff --git a/chromeos/services/cros_healthd/public/cpp/OWNERS b/chromeos/ash/services/cros_healthd/public/cpp/OWNERS
similarity index 100%
rename from chromeos/services/cros_healthd/public/cpp/OWNERS
rename to chromeos/ash/services/cros_healthd/public/cpp/OWNERS
diff --git a/chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.cc b/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.cc
similarity index 99%
rename from chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.cc
rename to chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.cc
index 8cb9785..097f3a49 100644
--- a/chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.cc
+++ b/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.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/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
 
 #include <utility>
 
@@ -12,7 +12,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/ash/components/dbus/cros_healthd/cros_healthd_client.h"
 #include "chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.h"
-#include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 #include "mojo/public/cpp/system/handle.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
diff --git a/chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h b/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h
similarity index 96%
rename from chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h
rename to chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h
index 2535401..805cb4e 100644
--- a/chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h
+++ b/chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_CROS_HEALTHD_PUBLIC_CPP_FAKE_CROS_HEALTHD_H_
-#define CHROMEOS_SERVICES_CROS_HEALTHD_PUBLIC_CPP_FAKE_CROS_HEALTHD_H_
+#ifndef CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PUBLIC_CPP_FAKE_CROS_HEALTHD_H_
+#define CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PUBLIC_CPP_FAKE_CROS_HEALTHD_H_
 
 #include <cstdint>
 #include <vector>
 
 #include "base/time/time.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom.h"
 #include "chromeos/services/network_health/public/mojom/network_health.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -407,4 +407,4 @@
 using ::ash::cros_healthd::FakeCrosHealthd;
 }
 
-#endif  // CHROMEOS_SERVICES_CROS_HEALTHD_PUBLIC_CPP_FAKE_CROS_HEALTHD_H_
+#endif  // CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PUBLIC_CPP_FAKE_CROS_HEALTHD_H_
diff --git a/chromeos/services/cros_healthd/public/cpp/service_connection.cc b/chromeos/ash/services/cros_healthd/public/cpp/service_connection.cc
similarity index 98%
rename from chromeos/services/cros_healthd/public/cpp/service_connection.cc
rename to chromeos/ash/services/cros_healthd/public/cpp/service_connection.cc
index 7ec6d19..9368189 100644
--- a/chromeos/services/cros_healthd/public/cpp/service_connection.cc
+++ b/chromeos/ash/services/cros_healthd/public/cpp/service_connection.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/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 
 #include <fcntl.h>
 
@@ -15,12 +15,12 @@
 #include "base/sequence_checker.h"
 #include "chromeos/ash/components/dbus/cros_healthd/cros_healthd_client.h"
 #include "chromeos/ash/components/dbus/cros_healthd/fake_cros_healthd_client.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "mojo/public/cpp/bindings/remote.h"
-#include "ui/events/ozone/evdev/event_device_info.h"  // nogncheck
+#include "ui/events/ozone/evdev/event_device_info.h"
 
 #if !defined(USE_REAL_DBUS_CLIENTS)
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
 #endif
 
 namespace chromeos {
diff --git a/chromeos/services/cros_healthd/public/cpp/service_connection.h b/chromeos/ash/services/cros_healthd/public/cpp/service_connection.h
similarity index 77%
rename from chromeos/services/cros_healthd/public/cpp/service_connection.h
rename to chromeos/ash/services/cros_healthd/public/cpp/service_connection.h
index 4bdb101..df2c8b1 100644
--- a/chromeos/services/cros_healthd/public/cpp/service_connection.h
+++ b/chromeos/ash/services/cros_healthd/public/cpp/service_connection.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_CROS_HEALTHD_PUBLIC_CPP_SERVICE_CONNECTION_H_
-#define CHROMEOS_SERVICES_CROS_HEALTHD_PUBLIC_CPP_SERVICE_CONNECTION_H_
+#ifndef CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PUBLIC_CPP_SERVICE_CONNECTION_H_
+#define CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PUBLIC_CPP_SERVICE_CONNECTION_H_
 
 #include <sys/types.h>
 
@@ -12,9 +12,9 @@
 
 #include "base/callback_forward.h"
 #include "base/time/time.h"
-#include "chromeos/services/cros_healthd/private/mojom/cros_healthd_internal.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
+#include "chromeos/ash/services/cros_healthd/private/mojom/cros_healthd_internal.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom.h"
 #include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom.h"
 #include "chromeos/services/network_health/public/mojom/network_health.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -39,7 +39,7 @@
           chromeos::network_diagnostics::mojom::NetworkDiagnosticsRoutines>()>;
 
   // Retrieve a list of available diagnostic routines. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void GetAvailableRoutines(
       mojom::CrosHealthdDiagnosticsService::GetAvailableRoutinesCallback
@@ -47,7 +47,7 @@
 
   // Send a command to an existing routine. Also returns status information
   // for the routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void GetRoutineUpdate(
       int32_t id,
@@ -57,7 +57,7 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the urandom routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunUrandomRoutine(
       const absl::optional<base::TimeDelta>& length_seconds,
@@ -65,28 +65,28 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the battery capacity routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunBatteryCapacityRoutine(
       mojom::CrosHealthdDiagnosticsService::RunBatteryCapacityRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the battery health routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunBatteryHealthRoutine(
       mojom::CrosHealthdDiagnosticsService::RunBatteryHealthRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the smartcl check routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunSmartctlCheckRoutine(
       mojom::CrosHealthdDiagnosticsService::RunSmartctlCheckRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the AC power routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunAcPowerRoutine(
       mojom::AcPowerStatusEnum expected_status,
@@ -95,7 +95,7 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the CPU cache routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunCpuCacheRoutine(
       const absl::optional<base::TimeDelta>& exec_duration,
@@ -103,7 +103,7 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the CPU stress routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunCpuStressRoutine(
       const absl::optional<base::TimeDelta>& exec_duration,
@@ -111,7 +111,7 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the floating point accuracy routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunFloatingPointAccuracyRoutine(
       const absl::optional<base::TimeDelta>& exec_duration,
@@ -119,7 +119,7 @@
           RunFloatingPointAccuracyRoutineCallback callback) = 0;
 
   // Requests that cros_healthd runs the NVMe wear-level routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunNvmeWearLevelRoutine(
       uint32_t wear_level_threshold,
@@ -127,7 +127,7 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the NVMe self-test routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunNvmeSelfTestRoutine(
       mojom::NvmeSelfTestTypeEnum nvme_self_test_type,
@@ -135,7 +135,7 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the Disk Read routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunDiskReadRoutine(
       mojom::DiskReadRoutineTypeEnum type,
@@ -145,7 +145,7 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the prime search routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunPrimeSearchRoutine(
       const absl::optional<base::TimeDelta>& exec_duration,
@@ -153,7 +153,7 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the battery discharge routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunBatteryDischargeRoutine(
       base::TimeDelta exec_duration,
@@ -162,7 +162,7 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the battery charge routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunBatteryChargeRoutine(
       base::TimeDelta exec_duration,
@@ -171,112 +171,112 @@
           callback) = 0;
 
   // Requests that cros_healthd runs the memory routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunMemoryRoutine(
       mojom::CrosHealthdDiagnosticsService::RunMemoryRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the lan connectivity routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunLanConnectivityRoutine(
       mojom::CrosHealthdDiagnosticsService::RunLanConnectivityRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the signal strength routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunSignalStrengthRoutine(
       mojom::CrosHealthdDiagnosticsService::RunSignalStrengthRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the gateway can be pinged routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunGatewayCanBePingedRoutine(
       mojom::CrosHealthdDiagnosticsService::RunGatewayCanBePingedRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the has secure wifi routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunHasSecureWiFiConnectionRoutine(
       mojom::CrosHealthdDiagnosticsService::
           RunHasSecureWiFiConnectionRoutineCallback callback) = 0;
 
   // Requests that cros_healthd runs DNS resolver present routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunDnsResolverPresentRoutine(
       mojom::CrosHealthdDiagnosticsService::RunDnsResolverPresentRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the DNS latency routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunDnsLatencyRoutine(
       mojom::CrosHealthdDiagnosticsService::RunDnsLatencyRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the DNS resolution routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunDnsResolutionRoutine(
       mojom::CrosHealthdDiagnosticsService::RunDnsResolutionRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the captive portal routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunCaptivePortalRoutine(
       mojom::CrosHealthdDiagnosticsService::RunCaptivePortalRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the HTTP firewall routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunHttpFirewallRoutine(
       mojom::CrosHealthdDiagnosticsService::RunHttpFirewallRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the HTTPS firewall routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunHttpsFirewallRoutine(
       mojom::CrosHealthdDiagnosticsService::RunHttpsFirewallRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the HTTPS latency routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunHttpsLatencyRoutine(
       mojom::CrosHealthdDiagnosticsService::RunHttpsLatencyRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the ARC HTTP routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunArcHttpRoutine(
       mojom::CrosHealthdDiagnosticsService::RunArcHttpRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the ARC PING routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunArcPingRoutine(
       mojom::CrosHealthdDiagnosticsService::RunArcPingRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the ARC DNS resolution routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunArcDnsResolutionRoutine(
       mojom::CrosHealthdDiagnosticsService::RunArcDnsResolutionRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the video conferencing routine. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunVideoConferencingRoutine(
       const absl::optional<std::string>& stun_server_hostname,
@@ -284,27 +284,27 @@
           callback) = 0;
 
   // Subscribes to cros_healthd's Bluetooth-related events. See
-  // src/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void AddBluetoothObserver(
       mojo::PendingRemote<mojom::CrosHealthdBluetoothObserver>
           pending_observer) = 0;
 
   // Subscribes to cros_healthd's lid-related events. See
-  // src/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void AddLidObserver(
       mojo::PendingRemote<mojom::CrosHealthdLidObserver> pending_observer) = 0;
 
   // Subscribes to cros_healthd's power-related events. See
-  // src/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void AddPowerObserver(
       mojo::PendingRemote<mojom::CrosHealthdPowerObserver>
           pending_observer) = 0;
 
   // Subscribes to cros_healthd's network-related events. See
-  // src/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void AddNetworkObserver(
       mojo::PendingRemote<
@@ -312,34 +312,34 @@
           pending_observer) = 0;
 
   // Subscribes to cros_healthd's audio-related events. See
-  // src/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void AddAudioObserver(
       mojo::PendingRemote<mojom::CrosHealthdAudioObserver>
           pending_observer) = 0;
 
   // Subscribes to cros_healthd's Thunderbolt-related events. See
-  // src/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void AddThunderboltObserver(
       mojo::PendingRemote<mojom::CrosHealthdThunderboltObserver>
           pending_observer) = 0;
 
   // Subscribes to cros_healthd's USB-related events. See
-  // src/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void AddUsbObserver(
       mojo::PendingRemote<mojom::CrosHealthdUsbObserver> pending_observer) = 0;
 
   // Gathers pieces of information about the platform. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void ProbeTelemetryInfo(
       const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
       mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback) = 0;
 
   // Gathers information about a particular process on the device. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void ProbeProcessInfo(
       pid_t process_id,
@@ -347,14 +347,14 @@
 
   // Binds |service| to an implementation of CrosHealthdDiagnosticsService. In
   // production, this implementation is provided by cros_healthd. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void GetDiagnosticsService(
       mojo::PendingReceiver<mojom::CrosHealthdDiagnosticsService> service) = 0;
 
   // Binds |service| to an implementation of CrosHealthdProbeService. In
   // production, this implementation is provided by cros_healthd. See
-  // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
+  // src/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void GetProbeService(
       mojo::PendingReceiver<mojom::CrosHealthdProbeService> service) = 0;
@@ -400,4 +400,4 @@
 }  // namespace cros_healthd
 }  // namespace ash
 
-#endif  // CHROMEOS_SERVICES_CROS_HEALTHD_PUBLIC_CPP_SERVICE_CONNECTION_H_
+#endif  // CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PUBLIC_CPP_SERVICE_CONNECTION_H_
diff --git a/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc b/chromeos/ash/services/cros_healthd/public/cpp/service_connection_unittest.cc
similarity index 98%
rename from chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc
rename to chromeos/ash/services/cros_healthd/public/cpp/service_connection_unittest.cc
index e7135fb..9b74de4 100644
--- a/chromeos/services/cros_healthd/public/cpp/service_connection_unittest.cc
+++ b/chromeos/ash/services/cros_healthd/public/cpp/service_connection_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/services/cros_healthd/public/cpp/service_connection.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h"
 
 #include <sys/types.h>
 
@@ -15,10 +15,10 @@
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chromeos/services/cros_healthd/public/cpp/fake_cros_healthd.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/cpp/fake_cros_healthd.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/services/cros_healthd/public/mojom/BUILD.gn b/chromeos/ash/services/cros_healthd/public/mojom/BUILD.gn
similarity index 88%
rename from chromeos/services/cros_healthd/public/mojom/BUILD.gn
rename to chromeos/ash/services/cros_healthd/public/mojom/BUILD.gn
index 1a86ab8..8365c45a 100644
--- a/chromeos/services/cros_healthd/public/mojom/BUILD.gn
+++ b/chromeos/ash/services/cros_healthd/public/mojom/BUILD.gn
@@ -2,8 +2,11 @@
 # 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("//mojo/public/tools/bindings/mojom.gni")
 
+assert(is_chromeos_ash)
+
 mojom("mojom") {
   deps = [ "//chromeos/services/network_health/public/mojom" ]
   sources = [
@@ -16,7 +19,7 @@
   ]
 
   public_deps = [
-    "//chromeos/services/cros_healthd/private/mojom",
+    "//chromeos/ash/services/cros_healthd/private/mojom",
     "//chromeos/services/network_health/public/mojom",
     "//mojo/public/mojom/base",
   ]
diff --git a/chromeos/services/cros_healthd/public/mojom/OWNERS b/chromeos/ash/services/cros_healthd/public/mojom/OWNERS
similarity index 100%
rename from chromeos/services/cros_healthd/public/mojom/OWNERS
rename to chromeos/ash/services/cros_healthd/public/mojom/OWNERS
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom
similarity index 97%
rename from chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom
rename to chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom
index 73bdcaaf..5d6e711b 100644
--- a/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom
+++ b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd.mojom
@@ -10,12 +10,12 @@
 
 module chromeos.cros_healthd.mojom;
 
-import "chromeos/services/cros_healthd/private/mojom//cros_healthd_internal.mojom";
-import "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom";
-import "chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom";
-import "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom";
-import "chromeos/services/cros_healthd/public/mojom/nullable_primitives.mojom";
-import "chromeos/services/cros_healthd/public/mojom/wilco_ec.mojom";
+import "chromeos/ash/services/cros_healthd/private/mojom/cros_healthd_internal.mojom";
+import "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom";
+import "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom";
+import "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom";
+import "chromeos/ash/services/cros_healthd/public/mojom/nullable_primitives.mojom";
+import "chromeos/ash/services/cros_healthd/public/mojom/wilco_ec.mojom";
 import "chromeos/services/network_health/public/mojom/network_diagnostics.mojom";
 import "chromeos/services/network_health/public/mojom/network_health.mojom";
 
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom
similarity index 100%
rename from chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom
rename to chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom
similarity index 100%
rename from chromeos/services/cros_healthd/public/mojom/cros_healthd_events.mojom
rename to chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_events.mojom
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
similarity index 99%
rename from chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
rename to chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
index 149bdba..3863e11 100644
--- a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
+++ b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
@@ -10,7 +10,7 @@
 
 module chromeos.cros_healthd.mojom;
 
-import "chromeos/services/cros_healthd/public/mojom/nullable_primitives.mojom";
+import "chromeos/ash/services/cros_healthd/public/mojom/nullable_primitives.mojom";
 import "chromeos/services/network_health/public/mojom/network_health.mojom";
 
 // An enumeration of CPU architectures.
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.cc b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.cc
similarity index 94%
rename from chromeos/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.cc
rename to chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.cc
index 514623a..06a520b8 100644
--- a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.cc
+++ b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.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/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.h"
 
 #include "base/notreached.h"
 
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.h b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.h
similarity index 67%
rename from chromeos/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.h
rename to chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.h
index 16b33c5d..894045b 100644
--- a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.h
+++ b/chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe_mojom_traits.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_CROS_HEALTHD_PUBLIC_MOJOM_CROS_HEALTHD_PROBE_MOJOM_TRAITS_H_
-#define CHROMEOS_SERVICES_CROS_HEALTHD_PUBLIC_MOJOM_CROS_HEALTHD_PROBE_MOJOM_TRAITS_H_
+#ifndef CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PUBLIC_MOJOM_CROS_HEALTHD_PROBE_MOJOM_TRAITS_H_
+#define CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PUBLIC_MOJOM_CROS_HEALTHD_PROBE_MOJOM_TRAITS_H_
 
-#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-shared.h"
+#include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-shared.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "mojo/public/cpp/bindings/enum_traits.h"
 
@@ -24,4 +24,4 @@
 
 }  // namespace mojo
 
-#endif  // CHROMEOS_SERVICES_CROS_HEALTHD_PUBLIC_MOJOM_CROS_HEALTHD_PROBE_MOJOM_TRAITS_H_
+#endif  // CHROMEOS_ASH_SERVICES_CROS_HEALTHD_PUBLIC_MOJOM_CROS_HEALTHD_PROBE_MOJOM_TRAITS_H_
diff --git a/chromeos/services/cros_healthd/public/mojom/nullable_primitives.mojom b/chromeos/ash/services/cros_healthd/public/mojom/nullable_primitives.mojom
similarity index 100%
rename from chromeos/services/cros_healthd/public/mojom/nullable_primitives.mojom
rename to chromeos/ash/services/cros_healthd/public/mojom/nullable_primitives.mojom
diff --git a/chromeos/services/cros_healthd/public/mojom/wilco_ec.mojom b/chromeos/ash/services/cros_healthd/public/mojom/wilco_ec.mojom
similarity index 100%
rename from chromeos/services/cros_healthd/public/mojom/wilco_ec.mojom
rename to chromeos/ash/services/cros_healthd/public/mojom/wilco_ec.mojom
diff --git a/chromeos/services/cros_healthd/testing/bindings/context.cc b/chromeos/ash/services/cros_healthd/testing/bindings/context.cc
similarity index 84%
rename from chromeos/services/cros_healthd/testing/bindings/context.cc
rename to chromeos/ash/services/cros_healthd/testing/bindings/context.cc
index 74dbdbd..4425c90 100644
--- a/chromeos/services/cros_healthd/testing/bindings/context.cc
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/context.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/services/cros_healthd/testing/bindings/context.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/context.h"
 
 #include <utility>
 
-#include "chromeos/services/cros_healthd/testing/bindings/local_state.h"
-#include "chromeos/services/cros_healthd/testing/bindings/remote_state.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/local_state.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/remote_state.h"
 
 namespace chromeos {
 namespace cros_healthd {
diff --git a/chromeos/services/cros_healthd/testing/bindings/context.h b/chromeos/ash/services/cros_healthd/testing/bindings/context.h
similarity index 81%
rename from chromeos/services/cros_healthd/testing/bindings/context.h
rename to chromeos/ash/services/cros_healthd/testing/bindings/context.h
index 86850bb2..aaec84e4 100644
--- a/chromeos/services/cros_healthd/testing/bindings/context.h
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/context.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_CONTEXT_H_
-#define CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_CONTEXT_H_
+#ifndef CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_CONTEXT_H_
+#define CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_CONTEXT_H_
 
 #include <memory>
 #include <string>
@@ -40,4 +40,4 @@
 }  // namespace cros_healthd
 }  // namespace chromeos
 
-#endif  // CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_CONTEXT_H_
+#endif  // CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_CONTEXT_H_
diff --git a/chromeos/services/cros_healthd/testing/bindings/data_generator.cc b/chromeos/ash/services/cros_healthd/testing/bindings/data_generator.cc
similarity index 88%
rename from chromeos/services/cros_healthd/testing/bindings/data_generator.cc
rename to chromeos/ash/services/cros_healthd/testing/bindings/data_generator.cc
index e1a3464..a794cf68 100644
--- a/chromeos/services/cros_healthd/testing/bindings/data_generator.cc
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/data_generator.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/services/cros_healthd/testing/bindings/data_generator.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/data_generator.h"
 
 #include <fcntl.h>
 
diff --git a/chromeos/services/cros_healthd/testing/bindings/data_generator.h b/chromeos/ash/services/cros_healthd/testing/bindings/data_generator.h
similarity index 95%
rename from chromeos/services/cros_healthd/testing/bindings/data_generator.h
rename to chromeos/ash/services/cros_healthd/testing/bindings/data_generator.h
index 00bb2eb4..a5bf776 100644
--- a/chromeos/services/cros_healthd/testing/bindings/data_generator.h
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/data_generator.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_DATA_GENERATOR_H_
-#define CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_DATA_GENERATOR_H_
+#ifndef CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_DATA_GENERATOR_H_
+#define CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_DATA_GENERATOR_H_
 
 #include <memory>
 #include <string>
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include "base/containers/flat_map.h"
-#include "chromeos/services/cros_healthd/testing/bindings/context.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/context.h"
 #include "mojo/public/cpp/system/handle.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -241,4 +241,4 @@
 }  // namespace cros_healthd
 }  // namespace chromeos
 
-#endif  // CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_DATA_GENERATOR_H_
+#endif  // CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_DATA_GENERATOR_H_
diff --git a/chromeos/services/cros_healthd/testing/bindings/local_state.cc b/chromeos/ash/services/cros_healthd/testing/bindings/local_state.cc
similarity index 95%
rename from chromeos/services/cros_healthd/testing/bindings/local_state.cc
rename to chromeos/ash/services/cros_healthd/testing/bindings/local_state.cc
index b3439e73..e3e03ad 100644
--- a/chromeos/services/cros_healthd/testing/bindings/local_state.cc
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/local_state.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/services/cros_healthd/testing/bindings/local_state.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/local_state.h"
 
 #include <utility>
 #include <vector>
diff --git a/chromeos/services/cros_healthd/testing/bindings/local_state.h b/chromeos/ash/services/cros_healthd/testing/bindings/local_state.h
similarity index 81%
rename from chromeos/services/cros_healthd/testing/bindings/local_state.h
rename to chromeos/ash/services/cros_healthd/testing/bindings/local_state.h
index 1a164ef..e80e46e7 100644
--- a/chromeos/services/cros_healthd/testing/bindings/local_state.h
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/local_state.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_LOCAL_STATE_H_
-#define CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_LOCAL_STATE_H_
+#ifndef CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_LOCAL_STATE_H_
+#define CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_LOCAL_STATE_H_
 
 #include <memory>
 
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 
-#include "chromeos/services/cros_healthd/testing/bindings/mojom/state.mojom.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/mojom/state.mojom.h"
 
 namespace chromeos {
 namespace cros_healthd {
@@ -45,4 +45,4 @@
 }  // namespace cros_healthd
 }  // namespace chromeos
 
-#endif  // CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_LOCAL_STATE_H_
+#endif  // CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_LOCAL_STATE_H_
diff --git a/chromeos/services/cros_healthd/testing/bindings/mojom/BUILD.gn b/chromeos/ash/services/cros_healthd/testing/bindings/mojom/BUILD.gn
similarity index 78%
rename from chromeos/services/cros_healthd/testing/bindings/mojom/BUILD.gn
rename to chromeos/ash/services/cros_healthd/testing/bindings/mojom/BUILD.gn
index 072dc4c70..52ee482 100644
--- a/chromeos/services/cros_healthd/testing/bindings/mojom/BUILD.gn
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/mojom/BUILD.gn
@@ -2,8 +2,11 @@
 # 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("//mojo/public/tools/bindings/mojom.gni")
 
+assert(is_chromeos_ash)
+
 mojom("mojom") {
   sources = [ "state.mojom" ]
 }
diff --git a/chromeos/services/cros_healthd/testing/bindings/mojom/OWNERS b/chromeos/ash/services/cros_healthd/testing/bindings/mojom/OWNERS
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/mojom/OWNERS
rename to chromeos/ash/services/cros_healthd/testing/bindings/mojom/OWNERS
diff --git a/chromeos/services/cros_healthd/testing/bindings/mojom/state.mojom b/chromeos/ash/services/cros_healthd/testing/bindings/mojom/state.mojom
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/mojom/state.mojom
rename to chromeos/ash/services/cros_healthd/testing/bindings/mojom/state.mojom
diff --git a/chromeos/services/cros_healthd/testing/bindings/remote_state.cc b/chromeos/ash/services/cros_healthd/testing/bindings/remote_state.cc
similarity index 95%
rename from chromeos/services/cros_healthd/testing/bindings/remote_state.cc
rename to chromeos/ash/services/cros_healthd/testing/bindings/remote_state.cc
index 51b0ddd..b6b6fe2c 100644
--- a/chromeos/services/cros_healthd/testing/bindings/remote_state.cc
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/remote_state.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/services/cros_healthd/testing/bindings/remote_state.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/remote_state.h"
 
 #include <utility>
 
diff --git a/chromeos/services/cros_healthd/testing/bindings/remote_state.h b/chromeos/ash/services/cros_healthd/testing/bindings/remote_state.h
similarity index 85%
rename from chromeos/services/cros_healthd/testing/bindings/remote_state.h
rename to chromeos/ash/services/cros_healthd/testing/bindings/remote_state.h
index 427248b8..54ce4d0 100644
--- a/chromeos/services/cros_healthd/testing/bindings/remote_state.h
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/remote_state.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_REMOTE_STATE_H_
-#define CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_REMOTE_STATE_H_
+#ifndef CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_REMOTE_STATE_H_
+#define CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_REMOTE_STATE_H_
 
 #include <memory>
 
 #include "base/callback.h"
-#include "chromeos/services/cros_healthd/testing/bindings/mojom/state.mojom.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/mojom/state.mojom.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace chromeos {
@@ -52,4 +52,4 @@
 }  // namespace cros_healthd
 }  // namespace chromeos
 
-#endif  // CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_REMOTE_STATE_H_
+#endif  // CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_REMOTE_STATE_H_
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/connectivity-forward.h.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/connectivity-forward.h.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/connectivity-forward.h.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/connectivity-forward.h.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/connectivity.cc.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/connectivity.cc.j2
similarity index 85%
rename from chromeos/services/cros_healthd/testing/bindings/templates/connectivity.cc.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/connectivity.cc.j2
index dcb039b..5e72dd2 100644
--- a/chromeos/services/cros_healthd/testing/bindings/templates/connectivity.cc.j2
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/templates/connectivity.cc.j2
@@ -20,9 +20,9 @@
 #include <base/check.h>
 #include <base/logging.h>
 
-#include "chromeos/services/cros_healthd/testing/bindings/local_state.h"
-#include "chromeos/services/cros_healthd/testing/bindings/remote_state.h"
-#include "chromeos/services/cros_healthd/testing/bindings/utils.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/local_state.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/remote_state.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/utils.h"
 
 {%- for imp in module.imports %}
 #include "{{imp.path}}-connectivity.h"
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/connectivity.h.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/connectivity.h.j2
similarity index 91%
rename from chromeos/services/cros_healthd/testing/bindings/templates/connectivity.h.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/connectivity.h.j2
index 508f2566..ab9ddb7 100644
--- a/chromeos/services/cros_healthd/testing/bindings/templates/connectivity.h.j2
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/templates/connectivity.h.j2
@@ -27,8 +27,8 @@
 #include <mojo/public/cpp/bindings/receiver_set.h>
 #include <mojo/public/cpp/bindings/remote.h>
 
-#include "chromeos/services/cros_healthd/testing/bindings/context.h"
-#include "chromeos/services/cros_healthd/testing/bindings/data_generator.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/context.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/data_generator.h"
 #include "{{module.path}}.h"
 #include "{{module.path}}-connectivity-forward.h"
 
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/enum-generator.cc.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/enum-generator.cc.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/enum-generator.cc.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/enum-generator.cc.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/enum-generator.h.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/enum-generator.h.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/enum-generator.h.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/enum-generator.h.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/method-macro.cc.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/method-macro.cc.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/method-macro.cc.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/method-macro.cc.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/struct-generator.cc.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/struct-generator.cc.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/struct-generator.cc.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/struct-generator.cc.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/struct-generator.h.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/struct-generator.h.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/struct-generator.h.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/struct-generator.h.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/test-consumer.cc.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/test-consumer.cc.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/test-consumer.cc.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/test-consumer.cc.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/test-consumer.h.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/test-consumer.h.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/test-consumer.h.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/test-consumer.h.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/test-provider.cc.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/test-provider.cc.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/test-provider.cc.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/test-provider.cc.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/test-provider.h.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/test-provider.h.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/test-provider.h.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/test-provider.h.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/union-generator.cc.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/union-generator.cc.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/union-generator.cc.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/union-generator.cc.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/templates/union-generator.h.j2 b/chromeos/ash/services/cros_healthd/testing/bindings/templates/union-generator.h.j2
similarity index 100%
rename from chromeos/services/cros_healthd/testing/bindings/templates/union-generator.h.j2
rename to chromeos/ash/services/cros_healthd/testing/bindings/templates/union-generator.h.j2
diff --git a/chromeos/services/cros_healthd/testing/bindings/utils.cc b/chromeos/ash/services/cros_healthd/testing/bindings/utils.cc
similarity index 95%
rename from chromeos/services/cros_healthd/testing/bindings/utils.cc
rename to chromeos/ash/services/cros_healthd/testing/bindings/utils.cc
index 929a9318..6b72a4f 100644
--- a/chromeos/services/cros_healthd/testing/bindings/utils.cc
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/utils.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/services/cros_healthd/testing/bindings/utils.h"
+#include "chromeos/ash/services/cros_healthd/testing/bindings/utils.h"
 
 #include <utility>
 
diff --git a/chromeos/services/cros_healthd/testing/bindings/utils.h b/chromeos/ash/services/cros_healthd/testing/bindings/utils.h
similarity index 86%
rename from chromeos/services/cros_healthd/testing/bindings/utils.h
rename to chromeos/ash/services/cros_healthd/testing/bindings/utils.h
index 4155521..331d34a 100644
--- a/chromeos/services/cros_healthd/testing/bindings/utils.h
+++ b/chromeos/ash/services/cros_healthd/testing/bindings/utils.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_UTILS_H_
-#define CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_UTILS_H_
+#ifndef CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_UTILS_H_
+#define CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_UTILS_H_
 
 #include "base/callback.h"
 
@@ -41,4 +41,4 @@
 }  // namespace cros_healthd
 }  // namespace chromeos
 
-#endif  // CHROMEOS_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_UTILS_H_
+#endif  // CHROMEOS_ASH_SERVICES_CROS_HEALTHD_TESTING_BINDINGS_UTILS_H_
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 886bad6..d42898e 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -2418,6 +2418,9 @@
       <message name="IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT4" desc="Text for search result item which, when clicked, navigates the user to the personalization app page where they can change their device account image (visible on log-in screen). Alternate phrase for: 'Change device account image', 'Sign-in image', 'Login image', 'Profile picture'">
         Profile image
       </message>
+      <message name="IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT5" desc="Text for search result item which, when clicked, navigates the user to the personalization app page where they can change their device account image (visible on log-in screen). Alternative phrase for: 'Change device account image'">
+        Avatar image
+      </message>
       <message name="IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_WALLPAPER" desc="Text for search result item which, when clicked, navigates the user to wallpaper settings. Alternate phrase for: 'Background', 'Desktop'">
         Change wallpaper
       </message>
@@ -3425,6 +3428,9 @@
       <message name="IDS_FEEDBACK_TOOL_SEND_BUTTON_LABEL" desc="label for the send button to send feedback.">
         Send
       </message>
+      <message name="IDS_FEEDBACK_TOOL_ANONYMOUS_EMAIL_OPTION" desc="Option in the drop down menu to let the user send the feedback report without attaching their email.">
+        Don't include email address
+      </message>
       <message name="IDS_FEEDBACK_TOOL_SHARE_DIAGNOSTIC_DATA_LABEL" desc="Label showing the share diagnostic data.">
         Share diagnostic data
       </message>
@@ -3438,12 +3444,27 @@
       <message name="IDS_FEEDBACK_TOOL_PAGE_TITLE_AFTER_SENT" desc="Label showing a thank you message as the title of the confirmation page after a report has been sent.">
         Thanks for your feedback
       </message>
+      <message name="IDS_FEEDBACK_TOOL_THANK_YOU_NOTE_OFFLINE" desc="Thank you note when feedback tool is offline">
+        Thanks for the feedback. Your feedback helps improve Chrome OS and will be reviewed by the Chrome OS team. Because of the number of reports submitted, you won’t receive a direct reply.
+      </message>
       <message name="IDS_FEEDBACK_TOOL_RESOURCES_EXPLORE_APP_DESCRIPTION" desc="Description of the explore app that links to some resourses like help articals and new features of Chromebook.">
         Find help articles and answers to common Chromebook questions
       </message>
+      <message name="IDS_FEEDBACK_TOOL_RESOURCES_EXPLORE_APP_LABEL" desc="Label of the explore app">
+        Explore app
+      </message>
       <message name="IDS_FEEDBACK_TOOL_RESOURCES_DIAGNOSTICS_APP_LABEL" desc="Label of the diagnostics app">
         Diagnostics app
       </message>
+      <message name="IDS_FEEDBACK_TOOL_RESOURCES_DIAGNOSTICS_APP_DESCRIPTION" desc="Description of the diagnostics app resource indicating that they can debug and run hardware tests in the Diagnostics app.">
+        Run tests and troubleshooting for hardware issues
+      </message>
+      <message name="IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_LABEL" desc="Label of the ask community that opens an external link to the Chromebook community.">
+        Chromebook community
+      </message>
+      <message name="IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_DESCRIPTION" desc="Description of the ask community link">
+        Ask the experts in the Chromebook help forum
+      </message>
       <!-- End of Feedback Tool -->
     </messages>
   </release>
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_ANONYMOUS_EMAIL_OPTION.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_ANONYMOUS_EMAIL_OPTION.png.sha1
new file mode 100644
index 0000000..3e69bae9
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_ANONYMOUS_EMAIL_OPTION.png.sha1
@@ -0,0 +1 @@
+69a6a7a003a50f636091fdce1be12ab934bf15af
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_DESCRIPTION.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..4f607c0
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+1a29394e35efa33c04ab03a3e42de689305d0ef2
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_LABEL.png.sha1
new file mode 100644
index 0000000..4f607c0
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_ASK_COMMUNITY_LABEL.png.sha1
@@ -0,0 +1 @@
+1a29394e35efa33c04ab03a3e42de689305d0ef2
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_DIAGNOSTICS_APP_DESCRIPTION.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_DIAGNOSTICS_APP_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..4f607c0
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_DIAGNOSTICS_APP_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+1a29394e35efa33c04ab03a3e42de689305d0ef2
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_EXPLORE_APP_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_EXPLORE_APP_LABEL.png.sha1
new file mode 100644
index 0000000..d3278ef1
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_RESOURCES_EXPLORE_APP_LABEL.png.sha1
@@ -0,0 +1 @@
+75d105b9a764c40f7d5fc6e14af81f2addad3270
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_THANK_YOU_NOTE_OFFLINE.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_THANK_YOU_NOTE_OFFLINE.png.sha1
new file mode 100644
index 0000000..bfb0f7c3
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_THANK_YOU_NOTE_OFFLINE.png.sha1
@@ -0,0 +1 @@
+69de666d0e03cce140106e79f15085b0ec1a3c6e
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT5.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT5.png.sha1
new file mode 100644
index 0000000..6b30cd4
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_SEARCH_RESULT_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT5.png.sha1
@@ -0,0 +1 @@
+877e966cae67611ad7939ce79b5b21711df0c4e4
\ No newline at end of file
diff --git a/chromeos/components/local_search_service/linear_map_search.cc b/chromeos/components/local_search_service/linear_map_search.cc
index d9b90ec..753e9a6 100644
--- a/chromeos/components/local_search_service/linear_map_search.cc
+++ b/chromeos/components/local_search_service/linear_map_search.cc
@@ -53,7 +53,6 @@
   for (const auto& tag : search_tags) {
     FuzzyTokenizedStringMatch match;
     if (match.IsRelevant(query, *(tag.second), relevance_threshold,
-                         false /* use_prefix_only */,
                          true /* use_weighted_ratio */,
                          false /* use_edit_distance */,
                          0.9 /* partial_match_penalty_rate */, 0.1)) {
diff --git a/chromeos/components/string_matching/fuzzy_tokenized_string_match.cc b/chromeos/components/string_matching/fuzzy_tokenized_string_match.cc
index f8d4da3..5e87b3e 100644
--- a/chromeos/components/string_matching/fuzzy_tokenized_string_match.cc
+++ b/chromeos/components/string_matching/fuzzy_tokenized_string_match.cc
@@ -56,7 +56,8 @@
   std::vector<std::u16string> query_diff_text;
   std::vector<std::u16string> text_diff_query;
 
-  // Find the intersection and the differences between two set of tokens.
+  // Find the set intersection and the set differences between two sets of
+  // tokens.
   std::set_intersection(query_token.begin(), query_token.end(),
                         text_token.begin(), text_token.end(),
                         std::back_inserter(intersection));
@@ -183,11 +184,21 @@
     double partial_match_penalty_rate,
     bool use_edit_distance,
     double num_matching_blocks_penalty) {
+  // All token based comparisons are scaled by 0.95 (on top of any partial
+  // scalars), as per original implementation:
+  // https://github.com/seatgeek/fuzzywuzzy/blob/af443f918eebbccff840b86fa606ac150563f466/fuzzywuzzy/fuzz.py#L245
   const double unbase_scale = 0.95;
+
   // Since query.text() and text.text() is not normalized, we use query.tokens()
   // and text.tokens() instead.
   const std::u16string query_normalized(base::JoinString(query.tokens(), u" "));
   const std::u16string text_normalized(base::JoinString(text.tokens(), u" "));
+
+  // TODO(crbug.com/1336160): Refactor the calculation flow in this method to
+  // make it easier to understand. For example, there is a long chain of
+  // std::max calls which is difficult to read. And it is confusing to have a
+  // conditional called |use_partial| but to also see |partial_scale| seemingly
+  // unconditionally applied.
   double weighted_ratio =
       SequenceMatcher(query_normalized, text_normalized, use_edit_distance,
                       num_matching_blocks_penalty)
@@ -202,6 +213,9 @@
   double partial_scale = 1;
 
   if (use_partial) {
+    // TODO(crbug.com/1336160): Consider scaling |partial_scale| smoothly with
+    // |length_ratio|, instead of using a step function.
+    //
     // If one string is much much shorter than the other, set |partial_scale| to
     // be 0.6, otherwise set it to be 0.9.
     partial_scale = length_ratio > 8 ? 0.6 : 0.9;
@@ -212,12 +226,11 @@
                               num_matching_blocks_penalty) *
                      partial_scale);
   }
-  weighted_ratio =
-      std::max(weighted_ratio,
-               TokenSortRatio(query, text, use_partial /*partial*/,
-                              partial_match_penalty_rate, use_edit_distance,
-                              num_matching_blocks_penalty) *
-                   unbase_scale * partial_scale);
+  weighted_ratio = std::max(
+      weighted_ratio,
+      TokenSortRatio(query, text, use_partial, partial_match_penalty_rate,
+                     use_edit_distance, num_matching_blocks_penalty) *
+          unbase_scale * partial_scale);
 
   // Do not use partial match for token set because the match between the
   // intersection string and query/text rewrites will always return an extremely
@@ -240,7 +253,6 @@
 bool FuzzyTokenizedStringMatch::IsRelevant(const TokenizedString& query,
                                            const TokenizedString& text,
                                            double relevance_threshold,
-                                           bool use_prefix_only,
                                            bool use_weighted_ratio,
                                            bool use_edit_distance,
                                            double partial_match_penalty_rate,
@@ -276,13 +288,6 @@
 
   const double prefix_score = PrefixMatcher(query, text);
 
-  if (use_prefix_only && prefix_score >= relevance_threshold) {
-    // If the prefix score is already higher than |relevance_threshold|, use
-    // prefix score as final score.
-    relevance_ = prefix_score;
-    return true;
-  }
-
   if (use_weighted_ratio) {
     // If WeightedRatio is used, |relevance_| is the average of WeightedRatio
     // and PrefixMatcher scores.
diff --git a/chromeos/components/string_matching/fuzzy_tokenized_string_match.h b/chromeos/components/string_matching/fuzzy_tokenized_string_match.h
index a772bb22..1e0f4c7 100644
--- a/chromeos/components/string_matching/fuzzy_tokenized_string_match.h
+++ b/chromeos/components/string_matching/fuzzy_tokenized_string_match.h
@@ -15,11 +15,17 @@
 // FuzzyTokenizedStringMatch takes two tokenized strings: one as the text and
 // the other one as the query. It matches the query against the text,
 // calculates a relevance score between [0, 1] and marks the matched portions
-// of text. A relevance of zero means the two are completely different to each
+// of text ("hits").
+//
+// A relevance of zero means the two strings are completely different to each
 // other. The higher the relevance score, the better the two strings are
 // matched. Matched portions of text are stored as index ranges.
+//
 // TODO(crbug.com/1018613): each of these functions have too many input params,
 // we should revise the structure and remove unnecessary ones.
+//
+// TODO(crbug.com/1336160): Terminology (for example: relevance vs. ratio) is
+// confusing and could be clarified.
 class FuzzyTokenizedStringMatch {
  public:
   typedef std::vector<gfx::Range> Hits;
@@ -32,11 +38,16 @@
 
   ~FuzzyTokenizedStringMatch();
 
+  // TODO(crbug.com/1336160): The Ratio() methods are called in sequence under
+  // certain conditions, and trigger much computation. These could potentially
+  // be streamlined or compressed.
+
   // TokenSetRatio takes two sets of tokens, finds their intersection and
   // differences. From the intersection and differences, it rewrites the |query|
   // and |text| and find the similarity ratio between them. This function
   // assumes that TokenizedString is already normalized (converted to lower
-  // case). Duplicates tokens will be removed for ratio computation.
+  // case). Duplicate tokens will be removed for ratio computation. The return
+  // score is in range [0, 1].
   static double TokenSetRatio(const TokenizedString& query,
                               const TokenizedString& text,
                               bool partial,
@@ -46,7 +57,8 @@
 
   // TokenSortRatio takes two set of tokens, sorts them and find the similarity
   // between two sorted strings. This function assumes that TokenizedString is
-  // already normalized (converted to lower case)
+  // already normalized (converted to lower case). The return score is in range
+  // [0, 1].
   static double TokenSortRatio(const TokenizedString& query,
                                const TokenizedString& text,
                                bool partial,
@@ -71,6 +83,9 @@
                               double partial_match_penalty_rate,
                               bool use_edit_distance,
                               double num_matching_blocks_penalty);
+  // TODO(crbug.com/1336160): Should prefix match always be favored over other
+  // matches? Reconsider this principle.
+  //
   // Since prefix match should always be favored over other matches, this
   // function is dedicated to calculate a prefix match score in range of [0, 1]
   // using PrefixMatcher class.
@@ -79,12 +94,18 @@
   static double PrefixMatcher(const TokenizedString& query,
                               const TokenizedString& text);
 
-  // Calculates the relevance of two strings. Returns true if two strings are
-  // somewhat matched, i.e. relevance score is greater than a threshold.
+  // TODO(crbug.com/1336160): Consider refactoring this method to directly
+  // return the relevance score, instead of a bool. This would remove the need
+  // to subsequently call relevance().
+  //
+  // Calculates the relevance score of |query| relative to |text|.
+  //
+  // Returns true if two strings are somewhat matched, i.e. relevance score is
+  // greater than |relevance_threshold|. The actual relevance score may
+  // subsequently be retrieved by calling relevance().
   bool IsRelevant(const TokenizedString& query,
                   const TokenizedString& text,
                   double relevance_threshold,
-                  bool use_prefix_only,
                   bool use_weighted_ratio,
                   bool use_edit_distance,
                   double partial_match_penalty_rate,
diff --git a/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc b/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
index b29be9b..4a67a9b 100644
--- a/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
+++ b/chromeos/components/string_matching/fuzzy_tokenized_string_match_unittest.cc
@@ -227,22 +227,22 @@
     std::u16string query(u"anonymous");
     std::u16string text(u"famous");
     EXPECT_FALSE(match.IsRelevant(TokenizedString(query), TokenizedString(text),
-                                  0.4, false, true, false,
-                                  kPartialMatchPenaltyRate, 0.0));
+                                  0.4, true, false, kPartialMatchPenaltyRate,
+                                  0.0));
   }
   {
     std::u16string query(u"CC");
     std::u16string text(u"Clash Of Clan");
     EXPECT_FALSE(match.IsRelevant(TokenizedString(query), TokenizedString(text),
-                                  0.25, false, true, false,
-                                  kPartialMatchPenaltyRate, 0.0));
+                                  0.25, true, false, kPartialMatchPenaltyRate,
+                                  0.0));
   }
   {
     std::u16string query(u"Clash.of.clan");
     std::u16string text(u"ClashOfTitan");
     EXPECT_TRUE(match.IsRelevant(TokenizedString(query), TokenizedString(text),
-                                 0.4, false, true, false,
-                                 kPartialMatchPenaltyRate, 0.0));
+                                 0.4, true, false, kPartialMatchPenaltyRate,
+                                 0.0));
   }
 }
 
@@ -252,22 +252,21 @@
     std::u16string query(u"anonymous");
     std::u16string text(u"famous");
     EXPECT_FALSE(match.IsRelevant(TokenizedString(query), TokenizedString(text),
-                                  0.5, false, true, false,
-                                  kPartialMatchPenaltyRate, 0.0));
+                                  0.5, true, false, kPartialMatchPenaltyRate,
+                                  0.0));
   }
   {
     std::u16string query(u"CC");
     std::u16string text(u"Clash Of Clan");
     EXPECT_FALSE(match.IsRelevant(TokenizedString(query), TokenizedString(text),
-                                  0.25, false, true, false,
-                                  kPartialMatchPenaltyRate));
+                                  0.25, true, false, kPartialMatchPenaltyRate));
   }
   {
     std::u16string query(u"Clash.of.clan");
     std::u16string text(u"ClashOfTitan");
     EXPECT_FALSE(match.IsRelevant(TokenizedString(query), TokenizedString(text),
-                                  0.5, false, true, false,
-                                  kPartialMatchPenaltyRate, 0.0));
+                                  0.5, true, false, kPartialMatchPenaltyRate,
+                                  0.0));
   }
 }
 
@@ -276,8 +275,8 @@
   std::u16string query(u"anonymous");
   std::u16string text(u"famous");
   EXPECT_FALSE(match.IsRelevant(TokenizedString(query), TokenizedString(text),
-                                0.35, false, false, true,
-                                kPartialMatchPenaltyRate, 0.0));
+                                0.35, false, true, kPartialMatchPenaltyRate,
+                                0.0));
   EXPECT_NEAR(match.relevance(), 0.33 / 2, 0.01);
 }
 
@@ -286,8 +285,8 @@
   std::u16string query(u"yat");
   std::u16string text(u"YaT");
   EXPECT_TRUE(match.IsRelevant(TokenizedString(query), TokenizedString(text),
-                               0.35, false, false, true,
-                               kPartialMatchPenaltyRate, 0.0));
+                               0.35, false, true, kPartialMatchPenaltyRate,
+                               0.0));
   EXPECT_DOUBLE_EQ(match.relevance(), 1.0);
   EXPECT_EQ(match.hits().size(), 1u);
   EXPECT_EQ(match.hits()[0].start(), 0u);
diff --git a/chromeos/components/string_matching/sequence_matcher.cc b/chromeos/components/string_matching/sequence_matcher.cc
index 48f5f24..f21d41de 100644
--- a/chromeos/components/string_matching/sequence_matcher.cc
+++ b/chromeos/components/string_matching/sequence_matcher.cc
@@ -50,22 +50,38 @@
   use_edit_distance_ = use_edit_distance;
 }
 
+// Compute the longest common substring, with optimisations for:
+//
+// 1) Time: By pre-computing some letter positions (stored in
+// `char_to_positions_`.
+//
+// 2) Memory: Store only the latest row of the DP table (in
+// `dp_common_string_`).
+//
+// 3) Time: Fast-update `dp_common_string_`.
 Match SequenceMatcher::FindLongestMatch(int first_start,
                                         int first_end,
                                         int second_start,
                                         int second_end) {
   Match match(first_start, second_start, 0);
 
-  // These two vectors are used to do "fast update".
-  // |dp_values_to_erase| contains the values should be erased from
-  // |dp_common_string_|.
-  // |dp_values_to_affect| contains the values should be updated from
-  // |dp_common_string_|.
+  // These two vectors are used for fast updating of `dp_common_string_`.
+  // Only erase or update values which are known to have been changed.
+  //
+  //   `dp_values_to_erase` contains the values which should be erased from
+  //     `dp_common_string_`.
+  //   `dp_values_to_affect` contains the values which should be updated in
+  //     `dp_common_string_`.
   std::vector<std::pair<int, int>> dp_values_to_erase;
   std::vector<std::pair<int, int>> dp_values_to_affect;
 
+  // Outer loop: Iterate through the characters of `first_string`.
+  // Keep up-to-date `dp_common_string_` (the latest row of the DP table).
   for (int i = first_start; i < first_end; i++) {
     dp_values_to_affect.clear();
+
+    // Inner loop: Iterate through characters of `second_string`, where those
+    // characters are equal to first_string_[i], and within range.
     for (auto j : char_to_positions_[first_string_[i]]) {
       if (j < second_start) {
         continue;
@@ -73,17 +89,19 @@
       if (j >= second_end) {
         break;
       }
-      // dp_commong_string_[j + 1] is length of longest common substring
-      // ends at first_string_[i] and second_string_[j + 1]
+      // dp_common_string_[j + 1] is the length of the longest common substring
+      // ending at first_string_[i] and second_string_[j].
       const int length = dp_common_string_[j] + 1;
       dp_values_to_affect.emplace_back(j + 1, length);
+
+      // Store newly-found longer matches.
       if (length > match.length) {
         match.pos_first_string = i - length + 1;
         match.pos_second_string = j - length + 1;
         match.length = length;
       }
     }
-    // Updates dp_common_string_
+    // Update `dp_common_string_`.
     for (auto const& element : dp_values_to_erase) {
       dp_common_string_[element.first] = 0;
     }
@@ -92,7 +110,7 @@
     }
     std::swap(dp_values_to_erase, dp_values_to_affect);
   }
-  // Erases all updated value for the next call.
+  // Erase temporary values in preparation for future calls.
   std::fill(dp_common_string_.begin(), dp_common_string_.end(), 0);
 
   return match;
@@ -109,29 +127,39 @@
   std::queue<std::tuple<int, int, int, int>> queue_block;
   queue_block.emplace(0, first_string_.size(), 0, second_string_.size());
 
-  // Find all matching blocks recursively.
+  // Find all matching blocks recursively. Prioritize longer blocks: Find the
+  // longest matching block first, then recurse to the left and right into the
+  // remaining as-yet unmatched sections of the two strings.
   while (!queue_block.empty()) {
     int first_start, first_end, second_start, second_end;
     std::tie(first_start, first_end, second_start, second_end) =
         queue_block.front();
     queue_block.pop();
+
     const Match match =
         FindLongestMatch(first_start, first_end, second_start, second_end);
+
     if (match.length > 0) {
+      matching_blocks_.push_back(match);
+
+      // Recurse left.
       if (first_start < match.pos_first_string &&
           second_start < match.pos_second_string) {
         queue_block.emplace(first_start, match.pos_first_string, second_start,
                             match.pos_second_string);
       }
+      // Recurse right.
       if (match.pos_first_string + match.length < first_end &&
           match.pos_second_string + match.length < second_end) {
         queue_block.emplace(match.pos_first_string + match.length, first_end,
                             match.pos_second_string + match.length, second_end);
       }
-      matching_blocks_.push_back(match);
     }
   }
 
+  // Always store a final matching block. In case no matching blocks
+  // were discovered above, this final matching block serves
+  // the purpose of indicating that block matching has taken place.
   matching_blocks_.push_back(
       Match(first_string_.size(), second_string_.size(), 0));
   sort(matching_blocks_.begin(), matching_blocks_.end(), CompareMatches);
@@ -139,7 +167,7 @@
 }
 
 int SequenceMatcher::EditDistance() {
-  // If edit distance is already calculated
+  // If edit distance is already calculated, don't recompute.
   if (edit_distance_ >= 0) {
     return edit_distance_;
   }
@@ -151,12 +179,12 @@
     return edit_distance_;
   }
 
-  // Memory for the dynamic programming:
-  // dp[i + 1][j + 1] is the edit distane of first |i| characters of
-  // |first_string_| and first |j| characters of |second_string_|
+  // DP table: dp[i + 1][j + 1] is the edit distance between the first `i`
+  // characters of `first_string_` and the first `j` characters of
+  // `second_string_`.
   int dp[len_first + 1][len_second + 1];
 
-  // Initialize memory
+  // Initialize memory.
   for (int i = 0; i < len_first + 1; i++) {
     dp[i][0] = i;
   }
@@ -164,15 +192,16 @@
     dp[0][j] = j;
   }
 
-  // Calculate the edit distance
+  // Calculate the edit distance.
   for (int i = 1; i < len_first + 1; i++) {
     for (int j = 1; j < len_second + 1; j++) {
       const int cost = first_string_[i - 1] == second_string_[j - 1] ? 0 : 1;
-      // Insertion and deletion
+      // Insertion and deletion.
       dp[i][j] = std::min(dp[i - 1][j], dp[i][j - 1]) + 1;
-      // Substitution
+      // When cost == 0: Alignment.
+      // When cost == 1: Substitution.
       dp[i][j] = std::min(dp[i][j], dp[i - 1][j - 1] + cost);
-      // Transposition
+      // Transposition.
       if (i > 1 && j > 1 && first_string_[i - 2] == second_string_[j - 1] &&
           first_string_[i - 1] == second_string_[j - 2]) {
         dp[i][j] = std::min(dp[i][j], dp[i - 2][j - 2] + 1);
@@ -183,6 +212,9 @@
   return edit_distance_;
 }
 
+// TODO(crbug.com/1336160): This class contains two mutually exclusive
+// pathways (edit distance and block matching), with distinct algorithms
+// and ratio calculations. Consider refactoring.
 double SequenceMatcher::Ratio() {
   if (use_edit_distance_) {
     if (edit_distance_ratio_ < 0) {
@@ -203,8 +235,12 @@
     for (const auto& match : GetMatchingBlocks()) {
       sum_match += match.length;
     }
-    // Subtract two because the last one is always an "empty block". Hence
-    // actual number of matching blocks is |num_blocks - 1|.
+    // The last block is always a placeholder "empty" block, so subtract one.
+    // And, allow for one "penalty-free" block, so subtract one again. Hence,
+    // apply a penalty by using |num_blocks - 2|. Example:
+    //
+    // If num_blocks = 5, the actual number of matching blocks is 4. This
+    // means there are 3 blocks in excess of 1.
     block_matching_ratio_ =
         2.0 * sum_match / sum_length *
         exp(-(num_blocks - 2) * num_matching_blocks_penalty_);
diff --git a/chromeos/components/string_matching/sequence_matcher.h b/chromeos/components/string_matching/sequence_matcher.h
index 5618565..5e3285d5 100644
--- a/chromeos/components/string_matching/sequence_matcher.h
+++ b/chromeos/components/string_matching/sequence_matcher.h
@@ -17,24 +17,24 @@
 // (https://docs.python.org/2/library/difflib.html#difflib.SequenceMatcher)
 class SequenceMatcher {
  public:
-  // Representing a common substring between |first_string_| and
-  // |second_string_|.
+  // Representing a common substring between `first_string_` and
+  // `second_string_`.
   struct Match {
     Match();
     Match(int pos_first, int pos_second, int len);
-    // Starting position of the common substring in |first_string_|.
+    // Starting position of the common substring in `first_string_`.
     int pos_first_string;
-    // Starting position of the common substring in |second_string_|.
+    // Starting position of the common substring in `second_string_`.
     int pos_second_string;
     // Length of the common substring.
     int length;
   };
 
-  // |num_matching_blocks_penalty| is used to penalize too many small matching
+  // `num_matching_blocks_penalty` is used to penalize too many small matching
   // blocks. For the same number of matching characters, we prefer fewer
   // matching blocks. Value equal to 0 means no penalty. Values greater than 0
   // means heavier penalty will be applied to larger number of blocks. This is
-  // only appled if |use_edit_distance| is false.
+  // only appled if `use_edit_distance` is false.
   SequenceMatcher(const std::u16string& first_string,
                   const std::u16string& second_string,
                   bool use_edit_distance,
@@ -45,24 +45,37 @@
 
   ~SequenceMatcher() = default;
 
-  // Calculates similarity ratio of |first_string_| and |second_string_|.
+  // Calculates similarity ratio of `first_string_` and `second_string_`.
   double Ratio();
-  // Calculates the Damerau–Levenshtein distance between |first_string_| and
-  // |second_string_|.
-  // See https://en.wikipedia.org/wiki/Damerau–Levenshtein_distance for more
+  // Calculates the Damerau–Levenshtein restricted edit distance between
+  // `first_string_` and `second_string_`. Also known as the "optimal string
+  // alignment distance".
+  //
+  // The algorithm considers the following edit operations: insertion, deletion,
+  // substitution, and two-character transposition. It does not consider
+  // multiple adjacent transpositions. See
+  // https://en.wikipedia.org/wiki/Damerau–Levenshtein_distance for more
   // details.
   int EditDistance();
   // Finds the longest common substring between
-  // |first_string_[first_start:first_end]| and
-  // |second_string_[second_start:second_end]|.
+  // `first_string_[first_start:first_end]` and
+  // `second_string_[second_start:second_end]`. Used by
+  // GetMatchingBlocks().
   Match FindLongestMatch(int first_start,
                          int first_end,
                          int second_start,
                          int second_end);
-  // Get all matching blocks of |first_string_| and |second_string_|.
-  // All blocks will be sorted by starting position of them in the
-  // |first_string_|. The last matching block will always be
-  // Match(first_string_.size(), second_string_.size(), 0).
+  // Get all matching blocks of `first_string_` and `second_string_`.
+  // All blocks will be sorted by their starting position within
+  // `first_string_`.
+  //
+  // The last matching block will always be:
+  //
+  //   Match(first_string_.size(), second_string_.size(), 0).
+  //
+  // This is to cover the case where two strings have no matching blocks,
+  // so that we have something to store in `matching_blocks_` to indicate
+  // that matching has taken place.
   std::vector<Match> GetMatchingBlocks();
 
  private:
@@ -76,9 +89,9 @@
   // Controls whether to use edit distance to calculate ratio.
   bool use_edit_distance_;
   int edit_distance_ = -1;
-  // For each character |c| in |second_string_|, this variable
-  // |char_to_positions_| stores all positions where |c| occurs in
-  // |second_string_|.
+  // For each character `c` in `second_string_`, this variable
+  // `char_to_positions_` stores all positions where `c` occurs in
+  // `second_string_`.
   std::unordered_map<char, std::vector<int>> char_to_positions_;
   // Memory for dynamic programming algorithm used in FindLongestMatch().
   std::vector<int> dp_common_string_;
diff --git a/chromeos/components/string_matching/tokenized_string_match.h b/chromeos/components/string_matching/tokenized_string_match.h
index f956485..da2c052 100644
--- a/chromeos/components/string_matching/tokenized_string_match.h
+++ b/chromeos/components/string_matching/tokenized_string_match.h
@@ -17,8 +17,10 @@
 
 // TokenizedStringMatch takes two tokenized strings: one as the text and
 // the other one as the query. It matches the query against the text,
-// calculates a relevance score between [0, 1] and marks the matched portions
-// of text. A relevance of zero means the two are completely different to each
+// calculates a relevance score between [0, 1] and records the matched portions
+// of text ("hits").
+//
+// A relevance score of zero means the two are completely different to each
 // other. The higher the relevance score, the better the two strings are
 // matched. Matched portions of text are stored as index ranges.
 class TokenizedStringMatch {
@@ -32,8 +34,12 @@
 
   ~TokenizedStringMatch();
 
+  // TODO(crbug.com/1336160): Consider refactoring this method to directly
+  // return the relevance score, instead of a bool. This would remove the need
+  // to subsequently call relevance().
+  //
   // Calculates the relevance and hits. Returns true if the two strings are
-  // somewhat matched, i.e. relevance score is not zero.
+  // somewhat matched, i.e. relevance score is greater than zero.
   bool Calculate(const TokenizedString& query, const TokenizedString& text);
 
   // Convenience wrapper to calculate match from raw string input.
diff --git a/chromeos/components/sync_wifi/BUILD.gn b/chromeos/components/sync_wifi/BUILD.gn
index f665f11..ae8f1cd 100644
--- a/chromeos/components/sync_wifi/BUILD.gn
+++ b/chromeos/components/sync_wifi/BUILD.gn
@@ -35,6 +35,7 @@
     "//base",
     "//chromeos/dbus/shill",
     "//chromeos/network",
+    "//chromeos/services/network_config/public/cpp",
     "//chromeos/services/network_config/public/mojom",
     "//components/device_event_log",
     "//components/keyed_service/core",
@@ -76,8 +77,8 @@
   deps = [
     ":sync_wifi",
     "//base/test:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/login/login_state",
-    "//chromeos/network:test_support",
     "//chromeos/services/network_config:in_process_instance",
     "//chromeos/services/network_config:network_config",
     "//chromeos/services/network_config/public/cpp:test_support",
@@ -105,10 +106,10 @@
     "//ash/constants",
     "//ash/public/cpp",
     "//base/test:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus/shill:test_support",
     "//chromeos/login/login_state",
     "//chromeos/login/login_state:test_support",
-    "//chromeos/network:test_support",
     "//chromeos/services/network_config",
     "//chromeos/services/network_config:in_process_instance",
     "//chromeos/services/network_config/public/cpp:test_support",
diff --git a/chromeos/components/sync_wifi/local_network_collector_impl.h b/chromeos/components/sync_wifi/local_network_collector_impl.h
index 47130fc..1b817a40 100644
--- a/chromeos/components/sync_wifi/local_network_collector_impl.h
+++ b/chromeos/components/sync_wifi/local_network_collector_impl.h
@@ -15,7 +15,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chromeos/components/sync_wifi/local_network_collector.h"
 #include "chromeos/components/sync_wifi/synced_network_metrics_logger.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -35,7 +35,7 @@
 // ShillServiceClient.
 class LocalNetworkCollectorImpl
     : public LocalNetworkCollector,
-      public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+      public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   // LocalNetworkCollector:
 
@@ -68,17 +68,6 @@
 
   // CrosNetworkConfigObserver:
   void OnNetworkStateListChanged() override;
-  void OnActiveNetworksChanged(
-      std::vector<
-          network_config::mojom::NetworkStatePropertiesPtr> /* networks */)
-      override {}
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr /* network */)
-      override {}
-  void OnDeviceStateListChanged() override {}
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
  private:
   std::string InitializeRequest();
diff --git a/chromeos/components/sync_wifi/network_test_helper.cc b/chromeos/components/sync_wifi/network_test_helper.cc
index 4f86a291..56961da 100644
--- a/chromeos/components/sync_wifi/network_test_helper.cc
+++ b/chromeos/components/sync_wifi/network_test_helper.cc
@@ -8,9 +8,9 @@
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "chromeos/ash/components/network/cellular_metrics_logger.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/components/sync_wifi/network_type_conversions.h"
 #include "chromeos/login/login_state/login_state.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_metadata_store.h"
 #include "chromeos/services/network_config/in_process_instance.h"
 #include "components/account_id/account_id.h"
diff --git a/chromeos/components/sync_wifi/network_test_helper.h b/chromeos/components/sync_wifi/network_test_helper.h
index 8dc224e..32fc224 100644
--- a/chromeos/components/sync_wifi/network_test_helper.h
+++ b/chromeos/components/sync_wifi/network_test_helper.h
@@ -5,6 +5,7 @@
 #ifndef CHROMEOS_COMPONENTS_SYNC_WIFI_NETWORK_TEST_HELPER_H_
 #define CHROMEOS_COMPONENTS_SYNC_WIFI_NETWORK_TEST_HELPER_H_
 
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/ash/components/network/proxy/ui_proxy_config_service.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
@@ -12,7 +13,6 @@
 #include "chromeos/network/network_device_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/services/network_config/cros_network_config.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
diff --git a/chromeos/components/sync_wifi/synced_network_metrics_logger_unittest.cc b/chromeos/components/sync_wifi/synced_network_metrics_logger_unittest.cc
index e64f7ab..66bc69d 100644
--- a/chromeos/components/sync_wifi/synced_network_metrics_logger_unittest.cc
+++ b/chromeos/components/sync_wifi/synced_network_metrics_logger_unittest.cc
@@ -9,11 +9,11 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/components/sync_wifi/network_test_helper.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_metadata_store.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/components/sync_wifi/synced_network_updater_impl.h b/chromeos/components/sync_wifi/synced_network_updater_impl.h
index a30645ea..6105c98 100644
--- a/chromeos/components/sync_wifi/synced_network_updater_impl.h
+++ b/chromeos/components/sync_wifi/synced_network_updater_impl.h
@@ -12,7 +12,7 @@
 #include "chromeos/components/sync_wifi/pending_network_configuration_tracker.h"
 #include "chromeos/components/sync_wifi/synced_network_metrics_logger.h"
 #include "chromeos/components/sync_wifi/synced_network_updater.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "components/sync/protocol/model_type_state.pb.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 
@@ -27,7 +27,7 @@
 // using mojom::CrosNetworkConfig.
 class SyncedNetworkUpdaterImpl
     : public SyncedNetworkUpdater,
-      public chromeos::network_config::mojom::CrosNetworkConfigObserver {
+      public chromeos::network_config::CrosNetworkConfigObserver {
  public:
   // |cros_network_config| must outlive this class.
   SyncedNetworkUpdaterImpl(
@@ -46,17 +46,6 @@
 
   // CrosNetworkConfigObserver:
   void OnNetworkStateListChanged() override;
-  void OnActiveNetworksChanged(
-      std::vector<
-          network_config::mojom::NetworkStatePropertiesPtr> /* networks */)
-      override {}
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr /* network */)
-      override {}
-  void OnDeviceStateListChanged() override {}
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
  private:
   void StartAddOrUpdateOperation(
diff --git a/chromeos/crosapi/mojom/video_capture.mojom b/chromeos/crosapi/mojom/video_capture.mojom
index bd09b33e..a642903 100644
--- a/chromeos/crosapi/mojom/video_capture.mojom
+++ b/chromeos/crosapi/mojom/video_capture.mojom
@@ -133,7 +133,7 @@
 
 // Similar to |video_capture.mojom.VideoFrameHandler| but depends on simplified
 // structures.
-// Next min method ID: 10
+// Next min method ID: 11
 [Stable, Uuid="590ab36a-9162-4c9d-8429-1753108825ea"]
 interface VideoFrameHandler {
   OnNewBuffer@0(int32 buffer_id, VideoBufferHandle buffer_handle);
@@ -147,6 +147,9 @@
 
   OnFrameDropped@4(media.mojom.VideoCaptureFrameDropReason reason);
 
+  [MinVersion=2]
+  OnNewCropVersion@10(uint32 crop_version);
+
   [MinVersion=1]
   OnFrameWithEmptyRegionCapture@9();
 
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn
index 74fb14b8..90f9b6ae 100644
--- a/chromeos/dbus/BUILD.gn
+++ b/chromeos/dbus/BUILD.gn
@@ -110,8 +110,6 @@
     "//chromeos/dbus/u2f",
     "//chromeos/dbus/u2f:u2f_proto",
     "//chromeos/dbus/update_engine:unit_tests",
-    "//chromeos/dbus/userdataauth",
-    "//chromeos/dbus/userdataauth:userdataauth_proto",
     "//chromeos/dbus/util:unit_tests",
     "//dbus",
     "//dbus:test_support",
@@ -126,11 +124,6 @@
     "native_timer_unittest.cc",
     "pipe_reader_unittest.cc",
     "tpm_manager/tpm_manager_client_unittest.cc",
-    "userdataauth/arc_quota_client_unittest.cc",
-    "userdataauth/cryptohome_misc_client_unittest.cc",
-    "userdataauth/cryptohome_pkcs11_client_unittest.cc",
-    "userdataauth/install_attributes_client_unittest.cc",
-    "userdataauth/userdataauth_client_unittest.cc",
   ]
 }
 
diff --git a/chromeos/dbus/permission_broker/fake_permission_broker_client.cc b/chromeos/dbus/permission_broker/fake_permission_broker_client.cc
index 666f3b1..8f12e4b5 100644
--- a/chromeos/dbus/permission_broker/fake_permission_broker_client.cc
+++ b/chromeos/dbus/permission_broker/fake_permission_broker_client.cc
@@ -5,23 +5,29 @@
 #include "chromeos/dbus/permission_broker/fake_permission_broker_client.h"
 
 #include <fcntl.h>
+#include <linux/usbdevice_fs.h>
 #include <stdint.h>
+#include <sys/ioctl.h>
 
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/check_op.h"
+#include "base/containers/contains.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/unguessable_token.h"
 
 namespace chromeos {
 
 namespace {
 
-const char kOpenFailedError[] = "open_failed";
+constexpr char kOpenFailedError[] = "open_failed";
+constexpr char kDupFailedError[] = "dup_failed";
+constexpr char kWatchLifelineFdFailedError[] = "watch_lifeline_fd_failed";
 
 FakePermissionBrokerClient* g_instance = nullptr;
 
@@ -50,6 +56,46 @@
                         base::BindOnce(std::move(callback), std::move(fd)));
 }
 
+bool DisconnectInterface(const std::string& path, uint8_t iface_num) {
+  base::ScopedFD fd(HANDLE_EINTR(open(path.c_str(), O_RDWR)));
+  if (!fd.is_valid()) {
+    PLOG(ERROR) << "Failed to open path " << path;
+    return false;
+  }
+
+  struct usbdevfs_ioctl dio = {};
+  dio.ifno = iface_num;
+  dio.ioctl_code = USBDEVFS_DISCONNECT;
+  dio.data = nullptr;
+  int rc = HANDLE_EINTR(ioctl(fd.get(), USBDEVFS_IOCTL, &dio));
+  if (rc < 0) {
+    PLOG(ERROR) << "Failed to disconnect interface "
+                << static_cast<int>(iface_num) << " on path " << path;
+    return false;
+  }
+  return true;
+}
+
+bool ConnectInterface(const std::string& path, uint8_t iface_num) {
+  base::ScopedFD fd(HANDLE_EINTR(open(path.c_str(), O_RDWR)));
+  if (!fd.is_valid()) {
+    PLOG(ERROR) << "Failed to open path " << path;
+    return false;
+  }
+
+  struct usbdevfs_ioctl dio = {};
+  dio.ifno = iface_num;
+  dio.ioctl_code = USBDEVFS_CONNECT;
+  dio.data = nullptr;
+  int rc = HANDLE_EINTR(ioctl(fd.get(), USBDEVFS_IOCTL, &dio));
+  if (rc < 0) {
+    PLOG(ERROR) << "Failed to connect interface " << static_cast<int>(iface_num)
+                << " on path " << path;
+    return false;
+  }
+  return true;
+}
+
 }  // namespace
 
 FakePermissionBrokerClient::FakePermissionBrokerClient() {
@@ -93,6 +139,85 @@
   OpenPath(path, std::move(callback), std::move(error_callback));
 }
 
+void FakePermissionBrokerClient::OpenPathAndRegisterClient(
+    const std::string& path,
+    uint32_t allowed_interfaces_mask,
+    int lifeline_fd,
+    OpenPathAndRegisterClientCallback callback,
+    ErrorCallback error_callback) {
+  std::string client_id;
+  do {
+    client_id = base::UnguessableToken::Create().ToString();
+  } while (base::Contains(clients, client_id));
+
+  base::ScopedFD dup_lifeline_fd(HANDLE_EINTR(dup(lifeline_fd)));
+  if (!dup_lifeline_fd.is_valid()) {
+    int error_code = logging::GetLastSystemErrorCode();
+    std::move(error_callback)
+        .Run(kDupFailedError,
+             base::StringPrintf(
+                 "Failed to dup lifeline fd %d: %s", lifeline_fd,
+                 logging::SystemErrorCodeToString(error_code).c_str()));
+    return;
+  }
+
+  auto controller = base::FileDescriptorWatcher::WatchReadable(
+      dup_lifeline_fd.get(),
+      base::BindRepeating(&FakePermissionBrokerClient::HandleClosedClient,
+                          weak_factory_.GetWeakPtr(), client_id));
+  if (!controller) {
+    std::move(error_callback)
+        .Run(kWatchLifelineFdFailedError,
+             base::StringPrintf("Failed to watch dup lifeline fd %d",
+                                dup_lifeline_fd.get()));
+    return;
+  }
+  clients.emplace(client_id, UsbInterfaces(path, std::move(controller),
+                                           std::move(dup_lifeline_fd)));
+
+  // No concern of OpenPath failure causing orphan client record here, as the
+  // inserted client's record will still be removed when requester does error
+  // handling and closes the lifeline_fd.
+  OpenPath(path, base::BindOnce(std::move(callback), client_id),
+           std::move(error_callback));
+}
+
+void FakePermissionBrokerClient::DetachInterface(const std::string& client_id,
+                                                 uint8_t iface_num,
+                                                 ResultCallback callback) {
+  auto client_it = clients.find(client_id);
+  if (client_it == clients.end()) {
+    LOG(ERROR) << "Unknown client_id: " << client_id;
+    std::move(callback).Run(false);
+    return;
+  }
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+      base::BindOnce(&chromeos::DisconnectInterface, client_it->second.path,
+                     iface_num),
+      std::move(callback));
+}
+
+void FakePermissionBrokerClient::ReattachInterface(const std::string& client_id,
+                                                   uint8_t iface_num,
+                                                   ResultCallback callback) {
+  auto client_it = clients.find(client_id);
+  if (client_it == clients.end()) {
+    LOG(ERROR) << "Unknown client_id: " << client_id;
+    std::move(callback).Run(false);
+    return;
+  }
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+      base::BindOnce(&chromeos::ConnectInterface, client_it->second.path,
+                     iface_num),
+      std::move(callback));
+}
+
 void FakePermissionBrokerClient::RequestTcpPortAccess(
     uint16_t port,
     const std::string& interface,
@@ -220,4 +345,19 @@
   return true;
 }
 
+FakePermissionBrokerClient::UsbInterfaces::UsbInterfaces(
+    const std::string& path,
+    std::unique_ptr<base::FileDescriptorWatcher::Controller> controller,
+    base::ScopedFD lifeline_fd)
+    : path(std::move(path)),
+      controller(std::move(controller)),
+      lifeline_fd(std::move(lifeline_fd)) {}
+
+FakePermissionBrokerClient::UsbInterfaces::~UsbInterfaces() = default;
+
+FakePermissionBrokerClient::UsbInterfaces::UsbInterfaces(UsbInterfaces&&) =
+    default;
+FakePermissionBrokerClient::UsbInterfaces&
+FakePermissionBrokerClient::UsbInterfaces::operator=(UsbInterfaces&&) = default;
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/permission_broker/fake_permission_broker_client.h b/chromeos/dbus/permission_broker/fake_permission_broker_client.h
index bd477ed..48799c1c 100644
--- a/chromeos/dbus/permission_broker/fake_permission_broker_client.h
+++ b/chromeos/dbus/permission_broker/fake_permission_broker_client.h
@@ -7,11 +7,14 @@
 
 #include <stdint.h>
 
+#include <map>
 #include <set>
 #include <string>
 #include <utility>
 
 #include "base/compiler_specific.h"
+#include "base/files/file_descriptor_watcher_posix.h"
+#include "base/files/scoped_file.h"
 #include "chromeos/dbus/permission_broker/permission_broker_client.h"
 
 namespace chromeos {
@@ -40,6 +43,17 @@
                        int lifeline_fd,
                        OpenPathCallback callback,
                        ErrorCallback error_callback) override;
+  void OpenPathAndRegisterClient(const std::string& path,
+                                 uint32_t allowed_interfaces_mask,
+                                 int lifeline_fd,
+                                 OpenPathAndRegisterClientCallback callback,
+                                 ErrorCallback error_callback) override;
+  void DetachInterface(const std::string& client_id,
+                       uint8_t iface_num,
+                       ResultCallback callback) override;
+  void ReattachInterface(const std::string& client_id,
+                         uint8_t iface_num,
+                         ResultCallback callback) override;
   void RequestTcpPortAccess(uint16_t port,
                             const std::string& interface,
                             int lifeline_fd,
@@ -95,11 +109,32 @@
   using RuleSet =
       std::set<std::pair<uint16_t /* port */, std::string /* interface */>>;
 
+  struct UsbInterfaces {
+    UsbInterfaces(
+        const std::string& path,
+        std::unique_ptr<base::FileDescriptorWatcher::Controller> controller,
+        base::ScopedFD lifeline_fd);
+    ~UsbInterfaces();
+    UsbInterfaces(UsbInterfaces&&);
+    UsbInterfaces& operator=(UsbInterfaces&&);
+
+    UsbInterfaces(const UsbInterfaces&) = delete;
+    UsbInterfaces& operator=(const UsbInterfaces&) = delete;
+
+    std::string path;
+    std::unique_ptr<base::FileDescriptorWatcher::Controller> controller;
+    base::ScopedFD lifeline_fd;
+  };
+
   bool RequestPortImpl(uint16_t port,
                        const std::string& interface,
                        const RuleSet& deny_rule_set,
                        RuleSet* hole_set);
 
+  void HandleClosedClient(const std::string& client_id) {
+    clients.erase(client_id);
+  }
+
   RuleSet tcp_hole_set_;
   RuleSet udp_hole_set_;
 
@@ -108,6 +143,10 @@
 
   RuleSet tcp_deny_rule_set_;
   RuleSet udp_deny_rule_set_;
+
+  std::map<std::string, UsbInterfaces> clients;
+
+  base::WeakPtrFactory<FakePermissionBrokerClient> weak_factory_{this};
 };
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/permission_broker/permission_broker_client.cc b/chromeos/dbus/permission_broker/permission_broker_client.cc
index 432432c..65f6587 100644
--- a/chromeos/dbus/permission_broker/permission_broker_client.cc
+++ b/chromeos/dbus/permission_broker/permission_broker_client.cc
@@ -18,10 +18,13 @@
 
 using permission_broker::kCheckPathAccess;
 using permission_broker::kClaimDevicePath;
+using permission_broker::kDetachInterface;
 using permission_broker::kOpenPath;
+using permission_broker::kOpenPathAndRegisterClient;
 using permission_broker::kPermissionBrokerInterface;
 using permission_broker::kPermissionBrokerServiceName;
 using permission_broker::kPermissionBrokerServicePath;
+using permission_broker::kReattachInterface;
 using permission_broker::kReleaseTcpPort;
 using permission_broker::kReleaseTcpPortForward;
 using permission_broker::kReleaseUdpPort;
@@ -96,6 +99,54 @@
                        std::move(error_callback)));
   }
 
+  void OpenPathAndRegisterClient(const std::string& path,
+                                 uint32_t allowed_interfaces_mask,
+                                 int lifeline_fd,
+                                 OpenPathAndRegisterClientCallback callback,
+                                 ErrorCallback error_callback) override {
+    dbus::MethodCall method_call(kPermissionBrokerInterface,
+                                 kOpenPathAndRegisterClient);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendString(path);
+    writer.AppendUint32(allowed_interfaces_mask);
+    writer.AppendFileDescriptor(lifeline_fd);
+    proxy_->CallMethodWithErrorCallback(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(
+            &PermissionBrokerClientImpl::OpenPathAndRegisterClientResponse,
+            weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
+        base::BindOnce(&PermissionBrokerClientImpl::OnError,
+                       weak_ptr_factory_.GetWeakPtr(),
+                       std::move(error_callback)));
+  }
+
+  void DetachInterface(const std::string& client_id,
+                       uint8_t iface_num,
+                       ResultCallback callback) override {
+    dbus::MethodCall method_call(kPermissionBrokerInterface, kDetachInterface);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendString(client_id);
+    writer.AppendByte(iface_num);
+    proxy_->CallMethod(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  void ReattachInterface(const std::string& client_id,
+                         uint8_t iface_num,
+                         ResultCallback callback) override {
+    dbus::MethodCall method_call(kPermissionBrokerInterface,
+                                 kReattachInterface);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendString(client_id);
+    writer.AppendByte(iface_num);
+    proxy_->CallMethod(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&PermissionBrokerClientImpl::OnResponse,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
   void RequestTcpPortAccess(uint16_t port,
                             const std::string& interface,
                             int lifeline_fd,
@@ -253,6 +304,23 @@
     std::move(callback).Run(std::move(fd));
   }
 
+  void OpenPathAndRegisterClientResponse(
+      OpenPathAndRegisterClientCallback callback,
+      dbus::Response* response) {
+    base::ScopedFD fd;
+    std::string client_id;
+    dbus::MessageReader reader(response);
+    if (!reader.PopFileDescriptor(&fd)) {
+      LOG(WARNING) << "Could not parse response for fd: "
+                   << response->ToString();
+    }
+    if (!reader.PopString(&client_id)) {
+      LOG(WARNING) << "Could not parse response for client_id: "
+                   << response->ToString();
+    }
+    std::move(callback).Run(client_id, std::move(fd));
+  }
+
   void OnError(ErrorCallback callback, dbus::ErrorResponse* response) {
     std::string error_name;
     std::string error_message;
diff --git a/chromeos/dbus/permission_broker/permission_broker_client.h b/chromeos/dbus/permission_broker/permission_broker_client.h
index 4f40e7e..f0a0027 100644
--- a/chromeos/dbus/permission_broker/permission_broker_client.h
+++ b/chromeos/dbus/permission_broker/permission_broker_client.h
@@ -35,6 +35,11 @@
   // An OpenPathCallback callback is run when an OpenPath request is completed.
   using OpenPathCallback = base::OnceCallback<void(base::ScopedFD)>;
 
+  // An OpenPathAndRegisterClientCallback callback is run when an
+  // OpenPathAndRegisterClient request is completed.
+  using OpenPathAndRegisterClientCallback =
+      base::OnceCallback<void(const std::string& client_id, base::ScopedFD)>;
+
   // An ErrorCallback callback is run when an error is returned by the
   // permission broker.
   using ErrorCallback = base::OnceCallback<void(const std::string& error_name,
@@ -85,6 +90,38 @@
                                OpenPathCallback callback,
                                ErrorCallback error_callback) = 0;
 
+  // This API is for a client to register with the Permission Broker to
+  // make requests to detach/reattach USB device interfaces in the future.
+  // The |drop_privileges_mask| is a bit mask indicating which interface
+  // numbers of a USB device are allowed. The interface number 0 corresponds
+  // to the LSB of the mask. A device which has an ADB interface and other
+  // interfaces for Camera or Storage may be opened purely as an ADB device
+  // using a mask that zeros out the Camera and Storage interface number
+  // bit positions.
+  // The |path| is the USB device path the client wants to access.
+  // The |lifeline_fd| is a file descriptor for monitoring the client's
+  // lifetime and reattaching detached interfaces when the client terminates.
+  // The method returns |fd| which is a file descriptor opened at |path|,
+  // and |client_id| which is an unique id for a registered client.
+  virtual void OpenPathAndRegisterClient(
+      const std::string& path,
+      uint32_t allowed_interfaces_mask,
+      int lifeline_fd,
+      OpenPathAndRegisterClientCallback callback,
+      ErrorCallback error_callback) = 0;
+
+  // This API is for the client with |client_id| to detach the interface
+  // |iface_num| at the USB device associated with it.
+  virtual void DetachInterface(const std::string& client_id,
+                               uint8_t iface_num,
+                               ResultCallback callback) = 0;
+
+  // This API is for the client with |client_id| to reattach the interface
+  // |iface_num| at the USB device associated with it.
+  virtual void ReattachInterface(const std::string& client_id,
+                                 uint8_t iface_num,
+                                 ResultCallback callback) = 0;
+
   // Requests the |port| be opened on the firewall for incoming TCP/IP
   // connections received on |interface| (an empty string indicates all
   // interfaces). One end of an open pipe must be passed as |lifeline_fd| so
diff --git a/chromeos/network/BUILD.gn b/chromeos/network/BUILD.gn
index 0fe9242..514f48e5 100644
--- a/chromeos/network/BUILD.gn
+++ b/chromeos/network/BUILD.gn
@@ -153,66 +153,16 @@
   ]
 }
 
-source_set("test_support") {
-  testonly = true
-  public_deps = [
-    ":network",
-    "//chromeos/components/onc",
-    "//chromeos/dbus/hermes",
-    "//dbus",
-  ]
-  deps = [
-    "//base",
-    "//chromeos:test_utils",
-    "//chromeos/components/onc:test_support",
-    "//chromeos/dbus:test_support",
-    "//chromeos/services/network_config/public/cpp",
-    "//chromeos/services/network_config/public/mojom",
-    "//components/onc",
-    "//components/sync_preferences:test_support",
-    "//dbus",
-    "//net:test_support",
-    "//testing/gmock",
-    "//testing/gtest",
-  ]
-  sources = [
-    "fake_network_activation_handler.cc",
-    "fake_network_activation_handler.h",
-    "fake_network_connection_handler.cc",
-    "fake_network_connection_handler.h",
-    "fake_network_device_handler.cc",
-    "fake_network_device_handler.h",
-    "fake_stub_cellular_networks_provider.cc",
-    "fake_stub_cellular_networks_provider.h",
-    "mock_managed_network_configuration_handler.cc",
-    "mock_managed_network_configuration_handler.h",
-    "mock_network_device_handler.cc",
-    "mock_network_device_handler.h",
-    "mock_network_state_handler.cc",
-    "mock_network_state_handler.h",
-    "network_handler_test_helper.cc",
-    "network_handler_test_helper.h",
-    "network_state_test_helper.cc",
-    "network_state_test_helper.h",
-    "network_test_helper_base.cc",
-    "network_test_helper_base.h",
-    "system_token_cert_db_storage_test_util.cc",
-    "system_token_cert_db_storage_test_util.h",
-    "test_cellular_esim_profile_handler.cc",
-    "test_cellular_esim_profile_handler.h",
-  ]
-}
-
 source_set("unit_tests") {
   testonly = true
   deps = [
     ":network",
-    ":test_support",
     "//ash/constants",
     "//base",
     "//base:i18n",
     "//base/test:test_support",
     "//chromeos:test_utils",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/ash/components/network:unit_tests",
     "//chromeos/ash/components/network/metrics:unit_tests",
     "//chromeos/ash/components/network/onc:unit_tests",
diff --git a/chromeos/network/device_state_unittest.cc b/chromeos/network/device_state_unittest.cc
index 5e8608f..d062d220 100644
--- a/chromeos/network/device_state_unittest.cc
+++ b/chromeos/network/device_state_unittest.cc
@@ -5,8 +5,8 @@
 #include "chromeos/network/device_state.h"
 
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
 
diff --git a/chromeos/network/fast_transition_observer_unittest.cc b/chromeos/network/fast_transition_observer_unittest.cc
index 6426a809..7bd1741f 100644
--- a/chromeos/network/fast_transition_observer_unittest.cc
+++ b/chromeos/network/fast_transition_observer_unittest.cc
@@ -6,9 +6,9 @@
 
 #include "ash/constants/ash_pref_names.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/fast_transition_observer.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/network/managed_cellular_pref_handler_unittest.cc b/chromeos/network/managed_cellular_pref_handler_unittest.cc
index be9d3e9..60ad08f2 100644
--- a/chromeos/network/managed_cellular_pref_handler_unittest.cc
+++ b/chromeos/network/managed_cellular_pref_handler_unittest.cc
@@ -5,7 +5,7 @@
 #include "chromeos/network/managed_cellular_pref_handler.h"
 
 #include "base/test/task_environment.h"
-#include "chromeos/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc
index 0cfe88f..a1b9bb1 100644
--- a/chromeos/network/managed_network_configuration_handler_unittest.cc
+++ b/chromeos/network/managed_network_configuration_handler_unittest.cc
@@ -19,7 +19,10 @@
 #include "chromeos/ash/components/network/cellular_esim_installer.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
 #include "chromeos/ash/components/network/cellular_policy_handler.h"
+#include "chromeos/ash/components/network/fake_network_connection_handler.h"
+#include "chromeos/ash/components/network/mock_network_state_handler.h"
 #include "chromeos/ash/components/network/proxy/ui_proxy_config_service.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/components/onc/onc_signature.h"
 #include "chromeos/components/onc/onc_test_utils.h"
 #include "chromeos/components/onc/onc_utils.h"
@@ -29,17 +32,14 @@
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
-#include "chromeos/network/fake_network_connection_handler.h"
 #include "chromeos/network/managed_cellular_pref_handler.h"
 #include "chromeos/network/managed_network_configuration_handler_impl.h"
-#include "chromeos/network/mock_network_state_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_device_handler.h"
 #include "chromeos/network/network_policy_observer.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "components/onc/onc_pref_names.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
diff --git a/chromeos/network/network_connect_unittest.cc b/chromeos/network/network_connect_unittest.cc
index 5ae7d27..da520578 100644
--- a/chromeos/network/network_connect_unittest.cc
+++ b/chromeos/network/network_connect_unittest.cc
@@ -10,13 +10,13 @@
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chromeos/network/network_connection_handler_impl_unittest.cc b/chromeos/network/network_connection_handler_impl_unittest.cc
index 30c546ab..a756cbf3 100644
--- a/chromeos/network/network_connection_handler_impl_unittest.cc
+++ b/chromeos/network/network_connection_handler_impl_unittest.cc
@@ -17,7 +17,9 @@
 #include "chromeos/ash/components/network/cellular_connection_handler.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
 #include "chromeos/ash/components/network/cellular_utils.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/ash/components/network/onc/network_onc_utils.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/network/managed_network_configuration_handler_impl.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_configuration_handler.h"
@@ -26,11 +28,9 @@
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/prohibited_technologies_handler.h"
 #include "chromeos/network/stub_cellular_networks_provider.h"
 #include "chromeos/network/system_token_cert_db_storage.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "components/onc/onc_constants.h"
 #include "crypto/scoped_nss_types.h"
 #include "crypto/scoped_test_nss_db.h"
diff --git a/chromeos/network/network_event_log_unittest.cc b/chromeos/network/network_event_log_unittest.cc
index 08b47dce..eb166ba 100644
--- a/chromeos/network/network_event_log_unittest.cc
+++ b/chromeos/network/network_event_log_unittest.cc
@@ -5,10 +5,10 @@
 #include "chromeos/network/network_event_log.h"
 
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/network/network_metadata_store_unittest.cc b/chromeos/network/network_metadata_store_unittest.cc
index 6e9ea832..5f5b301 100644
--- a/chromeos/network/network_metadata_store_unittest.cc
+++ b/chromeos/network/network_metadata_store_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/callback_helpers.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/network_configuration_handler.h"
@@ -15,7 +16,6 @@
 #include "chromeos/network/network_metadata_observer.h"
 #include "chromeos/network/network_metadata_store.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "components/account_id/account_id.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chromeos/network/network_name_util_unittest.cc b/chromeos/network/network_name_util_unittest.cc
index b85e8fb..e037016 100644
--- a/chromeos/network/network_name_util_unittest.cc
+++ b/chromeos/network/network_name_util_unittest.cc
@@ -11,11 +11,11 @@
 
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "net/base/net_errors.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc
index d69c2bc..2490672e 100644
--- a/chromeos/network/network_state_handler_unittest.cc
+++ b/chromeos/network/network_state_handler_unittest.cc
@@ -23,6 +23,7 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "chromeos/ash/components/network/cellular_utils.h"
+#include "chromeos/ash/components/network/fake_stub_cellular_networks_provider.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_ipconfig_client.h"
@@ -30,7 +31,6 @@
 #include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/device_state.h"
-#include "chromeos/network/fake_stub_cellular_networks_provider.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "chromeos/network/network_type_pattern.h"
diff --git a/chromeos/network/network_state_unittest.cc b/chromeos/network/network_state_unittest.cc
index 9b19ec9..ff54134 100644
--- a/chromeos/network/network_state_unittest.cc
+++ b/chromeos/network/network_state_unittest.cc
@@ -13,8 +13,8 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/network/tether_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chromeos/network/prohibited_technologies_handler_unittest.cc b/chromeos/network/prohibited_technologies_handler_unittest.cc
index 42287c7..365eb126 100644
--- a/chromeos/network/prohibited_technologies_handler_unittest.cc
+++ b/chromeos/network/prohibited_technologies_handler_unittest.cc
@@ -14,12 +14,12 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/ash/components/network/onc/network_onc_utils.h"
 #include "chromeos/network/managed_network_configuration_handler_impl.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
diff --git a/chromeos/network/stub_cellular_networks_provider_unittest.cc b/chromeos/network/stub_cellular_networks_provider_unittest.cc
index 9c4387468..a0a5c9406 100644
--- a/chromeos/network/stub_cellular_networks_provider_unittest.cc
+++ b/chromeos/network/stub_cellular_networks_provider_unittest.cc
@@ -11,9 +11,9 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "chromeos/ash/components/network/cellular_utils.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
+#include "chromeos/ash/components/network/test_cellular_esim_profile_handler.h"
 #include "chromeos/network/managed_cellular_pref_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
-#include "chromeos/network/test_cellular_esim_profile_handler.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
diff --git a/chromeos/network/system_token_cert_db_storage_unittest.cc b/chromeos/network/system_token_cert_db_storage_unittest.cc
index fceaa87..e25991c 100644
--- a/chromeos/network/system_token_cert_db_storage_unittest.cc
+++ b/chromeos/network/system_token_cert_db_storage_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chromeos/network/system_token_cert_db_storage_test_util.h"
+#include "chromeos/ash/components/network/system_token_cert_db_storage_test_util.h"
 #include "crypto/scoped_test_nss_db.h"
 #include "crypto/scoped_test_system_nss_key_slot.h"
 #include "net/cert/nss_cert_database.h"
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index 56900ad..7969255 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-104-5112.9-1655719671-benchmark-104.0.5112.18-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-104-5112.9-1655719671-benchmark-104.0.5112.20-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index e5c731ee..aab6539 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-104-5087.0-1655718466-benchmark-104.0.5112.18-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-104-5087.0-1655718466-benchmark-104.0.5112.20-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index 0174881..ed55467 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-104-5060.22-1654508750-benchmark-104.0.5112.7-r1.orderfile.xz
+chromeos-chrome-orderfile-field-104-5112.9-1655719671-benchmark-104.0.5112.18-r1.orderfile.xz
diff --git a/chromeos/services/BUILD.gn b/chromeos/services/BUILD.gn
index 6826d08..ca5e251 100644
--- a/chromeos/services/BUILD.gn
+++ b/chromeos/services/BUILD.gn
@@ -21,8 +21,6 @@
     "//chromeos/ash/services/assistant:tests",
     "//chromeos/ash/services/federated/public/cpp:unit_tests",
     "//chromeos/services/bluetooth_config:unit_tests",
-    "//chromeos/services/cros_healthd/private/cpp:unit_tests",
-    "//chromeos/services/cros_healthd/public/cpp:unit_tests",
     "//chromeos/services/machine_learning/public/cpp:unit_tests",
     "//chromeos/services/network_config:unit_tests",
     "//chromeos/services/tts:services_unittests",
diff --git a/chromeos/services/cros_healthd/DEPS b/chromeos/services/cros_healthd/DEPS
deleted file mode 100644
index fb9ea0f8..0000000
--- a/chromeos/services/cros_healthd/DEPS
+++ /dev/null
@@ -1,5 +0,0 @@
-include_rules = [
-  "+chromeos/dbus",
-  "+chromeos/services/network_health/public/mojom",
-  "+mojo/public",
-]
diff --git a/chromeos/services/libassistant/BUILD.gn b/chromeos/services/libassistant/BUILD.gn
index 6ef176e..8fb0888c 100644
--- a/chromeos/services/libassistant/BUILD.gn
+++ b/chromeos/services/libassistant/BUILD.gn
@@ -139,6 +139,7 @@
     "//chromeos/dbus/util:util",
     "//chromeos/services/assistant/public/proto",
     "//chromeos/services/libassistant/public/mojom",
+    "//chromeos/services/network_config/public/cpp",
     "//chromeos/strings:strings_grit",
     "//services/network/public/cpp",
     "//services/network/public/mojom",
diff --git a/chromeos/services/libassistant/network_provider_impl.h b/chromeos/services/libassistant/network_provider_impl.h
index dd3e9e0..d5ea044 100644
--- a/chromeos/services/libassistant/network_provider_impl.h
+++ b/chromeos/services/libassistant/network_provider_impl.h
@@ -9,7 +9,7 @@
 
 #include "chromeos/assistant/internal/libassistant/shared_headers.h"
 #include "chromeos/services/libassistant/public/mojom/platform_delegate.mojom-forward.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
@@ -18,7 +18,7 @@
 
 class COMPONENT_EXPORT(ASSISTANT_SERVICE) NetworkProviderImpl
     : public assistant_client::NetworkProvider,
-      public network_config::mojom::CrosNetworkConfigObserver {
+      public network_config::CrosNetworkConfigObserver {
  public:
   NetworkProviderImpl();
 
@@ -33,18 +33,10 @@
   ConnectionStatus GetConnectionStatus() override;
   assistant_client::MdnsResponder* GetMdnsResponder() override;
 
-  // network_config::mojom::CrosNetworkConfigObserver:
+  // network_config::CrosNetworkConfigObserver:
   void OnActiveNetworksChanged(
       std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks)
       override;
-  void OnNetworkStateChanged(
-      chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
-      override {}
-  void OnNetworkStateListChanged() override {}
-  void OnDeviceStateListChanged() override {}
-  void OnVpnProvidersChanged() override {}
-  void OnNetworkCertificatesChanged() override {}
-  void OnPoliciesApplied(const std::string& userhash) override {}
 
  private:
   ConnectionStatus connection_status_;
diff --git a/chromeos/services/network_config/BUILD.gn b/chromeos/services/network_config/BUILD.gn
index ae883a8..ec0ef7d1 100644
--- a/chromeos/services/network_config/BUILD.gn
+++ b/chromeos/services/network_config/BUILD.gn
@@ -60,9 +60,9 @@
     "//ash/constants:constants",
     "//base",
     "//base/test:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/dbus/shill:test_support",
     "//chromeos/login/login_state",
-    "//chromeos/network:test_support",
     "//chromeos/services/network_config/public/cpp:test_support",
     "//components/onc",
     "//components/prefs:test_support",
diff --git a/chromeos/services/network_config/cros_network_config_unittest.cc b/chromeos/services/network_config/cros_network_config_unittest.cc
index df2e5c4..d99ecd1 100644
--- a/chromeos/services/network_config/cros_network_config_unittest.cc
+++ b/chromeos/services/network_config/cros_network_config_unittest.cc
@@ -17,18 +17,18 @@
 #include "base/test/task_environment.h"
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
 #include "chromeos/ash/components/network/cellular_metrics_logger.h"
+#include "chromeos/ash/components/network/fake_stub_cellular_networks_provider.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/ash/components/network/proxy/ui_proxy_config_service.h"
 #include "chromeos/components/onc/onc_utils.h"
 #include "chromeos/dbus/shill/fake_shill_device_client.h"
 #include "chromeos/login/login_state/login_state.h"
-#include "chromeos/network/fake_stub_cellular_networks_provider.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_certificate_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_device_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_metadata_store.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chromeos/services/network_config/public/cpp/BUILD.gn b/chromeos/services/network_config/public/cpp/BUILD.gn
index 0934860..3ec7b0b 100644
--- a/chromeos/services/network_config/public/cpp/BUILD.gn
+++ b/chromeos/services/network_config/public/cpp/BUILD.gn
@@ -6,6 +6,8 @@
 
 source_set("cpp") {
   sources = [
+    "cros_network_config_observer.cc",
+    "cros_network_config_observer.h",
     "cros_network_config_util.cc",
     "cros_network_config_util.h",
   ]
@@ -28,7 +30,7 @@
 
   public_deps = [
     "//base",
-    "//chromeos/network:test_support",
+    "//chromeos/ash/components/network:test_support",
     "//chromeos/services/network_config/public/mojom",
     "//mojo/public/cpp/bindings",
   ]
diff --git a/chromeos/services/network_config/public/cpp/cros_network_config_observer.cc b/chromeos/services/network_config/public/cpp/cros_network_config_observer.cc
new file mode 100644
index 0000000..d00f923a
--- /dev/null
+++ b/chromeos/services/network_config/public/cpp/cros_network_config_observer.cc
@@ -0,0 +1,26 @@
+// 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 "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
+
+namespace chromeos::network_config {
+
+void CrosNetworkConfigObserver::OnActiveNetworksChanged(
+    std::vector<mojom::NetworkStatePropertiesPtr> networks) {}
+
+void CrosNetworkConfigObserver::OnNetworkStateChanged(
+    mojom::NetworkStatePropertiesPtr network) {}
+
+void CrosNetworkConfigObserver::OnNetworkStateListChanged() {}
+
+void CrosNetworkConfigObserver::OnDeviceStateListChanged() {}
+
+void CrosNetworkConfigObserver::OnVpnProvidersChanged() {}
+
+void CrosNetworkConfigObserver::OnNetworkCertificatesChanged() {}
+
+void CrosNetworkConfigObserver::OnPoliciesApplied(const std::string& userhash) {
+}
+
+}  // namespace chromeos::network_config
diff --git a/chromeos/services/network_config/public/cpp/cros_network_config_observer.h b/chromeos/services/network_config/public/cpp/cros_network_config_observer.h
new file mode 100644
index 0000000..af97fa5
--- /dev/null
+++ b/chromeos/services/network_config/public/cpp/cros_network_config_observer.h
@@ -0,0 +1,30 @@
+// 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 CHROMEOS_SERVICES_NETWORK_CONFIG_PUBLIC_CPP_CROS_NETWORK_CONFIG_OBSERVER_H_
+#define CHROMEOS_SERVICES_NETWORK_CONFIG_PUBLIC_CPP_CROS_NETWORK_CONFIG_OBSERVER_H_
+
+#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+
+namespace chromeos::network_config {
+
+// This class allows derived observers to override only the methods that they
+// need.
+class CrosNetworkConfigObserver : public mojom::CrosNetworkConfigObserver {
+ public:
+  ~CrosNetworkConfigObserver() override = default;
+
+  void OnActiveNetworksChanged(
+      std::vector<mojom::NetworkStatePropertiesPtr> networks) override;
+  void OnNetworkStateChanged(mojom::NetworkStatePropertiesPtr network) override;
+  void OnNetworkStateListChanged() override;
+  void OnDeviceStateListChanged() override;
+  void OnVpnProvidersChanged() override;
+  void OnNetworkCertificatesChanged() override;
+  void OnPoliciesApplied(const std::string& userhash) override;
+};
+
+}  // namespace chromeos::network_config
+
+#endif  // CHROMEOS_SERVICES_NETWORK_CONFIG_PUBLIC_CPP_CROS_NETWORK_CONFIG_OBSERVER_H_
diff --git a/chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h b/chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h
index 4cffda7..212a107 100644
--- a/chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h
+++ b/chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h
@@ -8,8 +8,8 @@
 #include <memory>
 
 #include "chromeos/ash/components/network/cellular_inhibitor.h"
+#include "chromeos/ash/components/network/network_state_test_helper.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
-#include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h"
 #include "chromeos/services/network_config/public/mojom/network_types.mojom-forward.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/chromeos/strings/chromeos_strings_am.xtb b/chromeos/strings/chromeos_strings_am.xtb
index c585fea..0e02d91 100644
--- a/chromeos/strings/chromeos_strings_am.xtb
+++ b/chromeos/strings/chromeos_strings_am.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">ተጠቃሚ</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">ለውጫዊ መሣሪያዎች መስኮት ፊርምዌርን ማዘመን ክፍት ነው። <ph name="NUM_UPDATES" /> ዝማኔዎች ይገኛሉ።</translation>
+<translation id="1145516343487477149">ለተለመዱ የChromebook ጥያቄዎች የእገዛ ጽሑፎችን እና መልሶችን ያግኙ</translation>
 <translation id="1165039591588034296">ስህተት</translation>
 <translation id="1175697296044146566">ይህ <ph name="DEVICE_TYPE" /> በ<ph name="MANAGER" /> የሚተዳደር ነው።</translation>
 <translation id="1175951029573070619">መካከለኛ (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">ጠቆር ያለ ገጽታን አጥፋ</translation>
 <translation id="1874612839560830905">ኤምቲዩ</translation>
 <translation id="188114911237521550">የጨለማ ሁነታን አጥፋ</translation>
+<translation id="1881188606372070653">በሕጋዊ ምክንያቶች የይዘት ለውጦችን ለመጠየቅ ወደ <ph name="BEGIN_LINK1" />የሕግ እገዛ ገጽ<ph name="END_LINK1" /> ይሂዱ። የተወሰነ የመለያ እና የስርዓት መረጃ ለGoogle ሊላክ ይችላል። በእኛ <ph name="BEGIN_LINK2" />የግላዊነት መመሪያ<ph name="END_LINK2" /> እና <ph name="BEGIN_LINK3" />የአገልግሎት ውል<ph name="END_LINK3" /> መሠረት ቴክኒካዊ ችግሮችን ለመፍታትና አገልግሎቶቻችንን ለማሻሻል እንዲያግዝ እርስዎ የሚሰጡንን መረጃ እንጠቀምበታለን።</translation>
 <translation id="1887850431809612466">የሃርድዌር ክለሳ</translation>
 <translation id="1905710495812624430">የሚፈቀደው ከፍተኛ የሙከራዎች ብዛት ታልፏል።</translation>
 <translation id="1908234395526491708">የ UDP ጥያቄ አለመሳካቶች</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">መነካት የሚችል ማያ</translation>
 <translation id="6381741036071372448">የቁልፍ ሰሌዳዎን ይሞክሩ</translation>
 <translation id="6388847657025262518">የቃኚው ሰነድ መጋቢ ተቀርቅሯል። መጋቢውን ይፈትሹ እና እንደገና ይሞክሩ።</translation>
+<translation id="6394634179843537518">ፋይል አክል</translation>
 <translation id="6410257289063177456">የምስል ፋይሎች</translation>
 <translation id="641081527798843608">የርዕሰ ጉዳይ ተዛማጅ</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_ar.xtb b/chromeos/strings/chromeos_strings_ar.xtb
index 44a6383..6ba71bb 100644
--- a/chromeos/strings/chromeos_strings_ar.xtb
+++ b/chromeos/strings/chromeos_strings_ar.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">المستخدم</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">نافذة تحديث البرامج الثابتة للأجهزة الخارجية مفتوحة. عدد التحديثات المتاحة: <ph name="NUM_UPDATES" />.</translation>
+<translation id="1145516343487477149">‏البحث عن مقالات مساعدة وإجابات عن الأسئلة الشائعة حول أجهزة Chromebook</translation>
 <translation id="1165039591588034296">خطأ</translation>
 <translation id="1175697296044146566">تتم إدارة جهاز <ph name="DEVICE_TYPE" /> هذا من خلال <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">إشارة متوسطة (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">إيقاف تشغيل المظهر الداكن</translation>
 <translation id="1874612839560830905">‏وحدة النقل العظمى (MTU)</translation>
 <translation id="188114911237521550">إيقاف تشغيل الوضع المُعتِم</translation>
+<translation id="1881188606372070653">‏يُرجى الانتقال إلى <ph name="BEGIN_LINK1" />صفحة المساعدة القانونية<ph name="END_LINK1" /> لطلب تغيير المحتوى لأسباب قانونية. قد يتم إرسال بعض المعلومات عن الحساب والنظام إلى Google. وسنستعين بالمعلومات التي تصلنا منك لحل المشاكل التقنية وتحسين خدماتنا وفقًا <ph name="BEGIN_LINK2" />لسياسة الخصوصية<ph name="END_LINK2" /> و<ph name="BEGIN_LINK3" />بنود الخدمة<ph name="END_LINK3" /> لدينا.</translation>
 <translation id="1887850431809612466">مراجعة الأجهزة</translation>
 <translation id="1905710495812624430">تم تجاوز الحد الأقصى لعدد المحاولات المسموح بها.</translation>
 <translation id="1908234395526491708">‏تعذَّر طلب بروتوكول UDP.</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">الشاشة التي تعمل باللمس</translation>
 <translation id="6381741036071372448">اختبار لوحة المفاتيح</translation>
 <translation id="6388847657025262518">وحدة تغذية المستندات في الماسح الضوئي مليئة بالأوراق. يُرجى إزالة بعض الأوراق وإعادة المحاولة.</translation>
+<translation id="6394634179843537518">إضافة ملف</translation>
 <translation id="6410257289063177456">ملفات الصور</translation>
 <translation id="641081527798843608">مطابقة الموضوع</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_eu.xtb b/chromeos/strings/chromeos_strings_eu.xtb
index 5cdc6ec1b..675420d9 100644
--- a/chromeos/strings/chromeos_strings_eu.xtb
+++ b/chromeos/strings/chromeos_strings_eu.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Erabiltzailea</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Kanpoko gailuen firmwarea eguneratzeko leihoa irekita dago. <ph name="NUM_UPDATES" /> eguneratze daude.</translation>
+<translation id="1145516343487477149">Bilatu laguntza-artikuluak eta Chromebook-ei buruz egin ohi diren galderen erantzunak</translation>
 <translation id="1165039591588034296">Errorea</translation>
 <translation id="1175697296044146566"><ph name="MANAGER" /> domeinuak kudeatzen du <ph name="DEVICE_TYPE" /> gailua.</translation>
 <translation id="1175951029573070619">Normala (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Desaktibatu gai iluna</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Desaktibatu modu iluna</translation>
+<translation id="1881188606372070653">Legezko arrazoiak direla-eta edukian aldaketak eskatzeko, joan <ph name="BEGIN_LINK1" />legezko laguntzari buruzko orrira<ph name="END_LINK1" />. Baliteke kontuari eta sistemari buruzko zenbait datu bidaltzea Google-ri. Arazo teknikoak konpontzeko eta gure zerbitzuak hobetzeko erabiliko dugu ematen diguzun informazioa, gure <ph name="BEGIN_LINK2" />Pribatutasun-gidalerroei<ph name="END_LINK2" /> eta <ph name="BEGIN_LINK3" />Zerbitzu-baldintzei<ph name="END_LINK3" /> jarraikiz.</translation>
 <translation id="1887850431809612466">Hardwarearen berrikuspena</translation>
 <translation id="1905710495812624430">Saiakera-muga gainditu da.</translation>
 <translation id="1908234395526491708">UDP bidezko eskaeren hutsegiteak</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Ukipen-pantaila</translation>
 <translation id="6381741036071372448">Probatu teklatua</translation>
 <translation id="6388847657025262518">Eskanerraren dokumentu-elikatzailea trabatuta dago. Egiazta ezazu eta saiatu berriro.</translation>
+<translation id="6394634179843537518">Gehitu fitxategi bat</translation>
 <translation id="6410257289063177456">Irudi-fitxategiak</translation>
 <translation id="641081527798843608">Gaiaren bat-etortzea</translation>
 <translation id="6423239382391657905">VPN irekia</translation>
diff --git a/chromeos/strings/chromeos_strings_fi.xtb b/chromeos/strings/chromeos_strings_fi.xtb
index ac40ef8a..225f9a4 100644
--- a/chromeos/strings/chromeos_strings_fi.xtb
+++ b/chromeos/strings/chromeos_strings_fi.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Käyttäjä</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Ulkoisten laitteiden laiteohjelmistojen päivityksiä koskeva ikkuna on auki. <ph name="NUM_UPDATES" /> päivitystä saatavilla.</translation>
+<translation id="1145516343487477149">Etsi ohjeartikkeleita ja vastauksia yleisiin Chromebook-kysymyksiin</translation>
 <translation id="1165039591588034296">Virhe</translation>
 <translation id="1175697296044146566">Laitetta (<ph name="DEVICE_TYPE" />) ylläpitää <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">Keskitasoa (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Laita tumma teema pois päältä</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Laita tumma tila pois päältä</translation>
+<translation id="1881188606372070653">Voit pyytää juridisiin syihin perustuvia sisältömuutoksia <ph name="BEGIN_LINK1" />Oikeudellinen apu ‑sivulla<ph name="END_LINK1" />. Joitakin tili- ja järjestelmätietoja voidaan lähettää Googlelle. Käytämme ilmoittamiasi tietoja teknisten ongelmien ratkaisemiseen ja palvelujemme kehittämiseen <ph name="BEGIN_LINK2" />tietosuojakäytäntömme<ph name="END_LINK2" /> ja <ph name="BEGIN_LINK3" />käyttöehtojemme<ph name="END_LINK3" /> mukaisesti.</translation>
 <translation id="1887850431809612466">Laitteistoversio</translation>
 <translation id="1905710495812624430">Yritysten enimmäismäärä ylitettiin.</translation>
 <translation id="1908234395526491708">Epäonnistuneita UDP-pyyntöjä</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Kosketusnäyttö</translation>
 <translation id="6381741036071372448">Testaa näppäimistöä</translation>
 <translation id="6388847657025262518">Skannerin syöttölaite on tukossa. Tarkista syöttölaite ja yritä uudelleen.</translation>
+<translation id="6394634179843537518">Lisää tiedosto</translation>
 <translation id="6410257289063177456">Kuvatiedostot </translation>
 <translation id="641081527798843608">Aiheen vastaavuus</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_fr.xtb b/chromeos/strings/chromeos_strings_fr.xtb
index f69c623..1fd523e 100644
--- a/chromeos/strings/chromeos_strings_fr.xtb
+++ b/chromeos/strings/chromeos_strings_fr.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Utilisateur</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">La fenêtre de mise à jour du micrologiciel pour les appareils externes est ouverte. <ph name="NUM_UPDATES" /> mises à jour disponibles.</translation>
+<translation id="1145516343487477149">Trouvez des articles d'aide et des réponses aux questions fréquentes sur les Chromebooks</translation>
 <translation id="1165039591588034296">Erreur</translation>
 <translation id="1175697296044146566">Votre <ph name="DEVICE_TYPE" /> est géré par <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">Moyenne (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Annuler le thème sombre</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Annuler le mode sombre</translation>
+<translation id="1881188606372070653">Accédez à la <ph name="BEGIN_LINK1" />page d'aide des demandes légales<ph name="END_LINK1" /> pour demander des modifications de contenu pour des raisons juridiques. Certaines informations concernant votre compte et votre système pourront être envoyées à Google. Nous utiliserons les données fournies pour résoudre des problèmes techniques et pour améliorer nos services, conformément à nos <ph name="BEGIN_LINK2" />Règles de confidentialité<ph name="END_LINK2" /> et à nos <ph name="BEGIN_LINK3" />Conditions d'utilisation<ph name="END_LINK3" />.</translation>
 <translation id="1887850431809612466">Version du matériel</translation>
 <translation id="1905710495812624430">Vous avez atteint le nombre maximal autorisé de tentatives.</translation>
 <translation id="1908234395526491708">Échec de la requête UDP</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Écran tactile</translation>
 <translation id="6381741036071372448">Testez le clavier</translation>
 <translation id="6388847657025262518">Le chargeur de document du scanner est bloqué. Vérifiez le chargeur, puis réessayez.</translation>
+<translation id="6394634179843537518">Ajouter un fichier</translation>
 <translation id="6410257289063177456">Fichiers image</translation>
 <translation id="641081527798843608">Correspondance d'objet</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_gl.xtb b/chromeos/strings/chromeos_strings_gl.xtb
index b98fa0e..6a29c56c 100644
--- a/chromeos/strings/chromeos_strings_gl.xtb
+++ b/chromeos/strings/chromeos_strings_gl.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Usuario</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">A ventá de actualización do firmware dos dispositivos externos está aberta. Hai <ph name="NUM_UPDATES" /> actualizacións dispoñibles.</translation>
+<translation id="1145516343487477149">Atopa artigos de axuda e respostas a preguntas frecuentes en relación co Chromebook</translation>
 <translation id="1165039591588034296">Erro</translation>
 <translation id="1175697296044146566">Este dispositivo (<ph name="DEVICE_TYPE" />) está xestionado por <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">Intermedia (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Quitar tema escuro</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Quitar modo escuro</translation>
+<translation id="1881188606372070653">Accede á <ph name="BEGIN_LINK1" />páxina Axuda legal<ph name="END_LINK1" /> para solicitar cambios de contido por razóns legais. Pódese enviar parte da información da conta e do sistema a Google. Utilizaremos os datos que nos indiques para solucionar problemas técnicos e mellorar os nosos servizos segundo o estipulado na <ph name="BEGIN_LINK2" />Política de privacidade<ph name="END_LINK2" /> e nas <ph name="BEGIN_LINK3" />Condicións de servizo<ph name="END_LINK3" />.</translation>
 <translation id="1887850431809612466">Revisión do hardware</translation>
 <translation id="1905710495812624430">Superouse o número máximo de intentos.</translation>
 <translation id="1908234395526491708">Erros nas solicitudes de UDP</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Pantalla táctil</translation>
 <translation id="6381741036071372448">Probar o teclado</translation>
 <translation id="6388847657025262518">O alimentador de documentos do escáner está atascado. Revísao e téntao de novo.</translation>
+<translation id="6394634179843537518">Engadir ficheiro</translation>
 <translation id="6410257289063177456">Ficheiros de imaxe</translation>
 <translation id="641081527798843608">Coincidencia do asunto</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_gu.xtb b/chromeos/strings/chromeos_strings_gu.xtb
index 4e9f0e1..ff2d47a 100644
--- a/chromeos/strings/chromeos_strings_gu.xtb
+++ b/chromeos/strings/chromeos_strings_gu.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">વપરાશકર્તા</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">બાહ્ય ડિવાઇસનું ફર્મવેયર અપડેટ કરવા માટેની વિન્ડો ખુલ્લી છે. <ph name="NUM_UPDATES" /> અપડેટ ઉપલબ્ધ છે.</translation>
+<translation id="1145516343487477149">સહાય લેખ અને Chromebook વિશેના સામાન્ય પ્રશ્નોના જવાબો શોધો</translation>
 <translation id="1165039591588034296">ભૂલ</translation>
 <translation id="1175697296044146566"><ph name="MANAGER" /> દ્વારા <ph name="DEVICE_TYPE" />ને મેનેજ કરવામાં આવે છે.</translation>
 <translation id="1175951029573070619">સરેરાશ (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">ઘેરી થીમ બંધ કરો</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">ઘેરો મોડ બંધ કરો</translation>
+<translation id="1881188606372070653">કાનૂની કારણોસર કન્ટેન્ટમાં ફેરફારની વિનંતી કરવા માટે <ph name="BEGIN_LINK1" />કાનૂની સહાય પેજ<ph name="END_LINK1" /> પર જાઓ. એકાઉન્ટ અને સિસ્ટમની અમુક માહિતી Googleને મોકલવામાં આવી શકે છે. તમે અમને જે માહિતી આપશો, તેનો ઉપયોગ અમે અમારી <ph name="BEGIN_LINK2" />પ્રાઇવસી પૉલિસી<ph name="END_LINK2" /> અને <ph name="BEGIN_LINK3" />સેવાની શરતો<ph name="END_LINK3" />ને આધીન રહીને ટેક્નિકલ સમસ્યાઓના નિવારણ માટે અને અમારી સેવાઓને બહેતર બનાવવા માટે કરીશું.</translation>
 <translation id="1887850431809612466">હાર્ડવેર પુનરાવર્તન</translation>
 <translation id="1905710495812624430">મહત્તમ મંજૂર પ્રયત્નોની સંખ્યા ઓળંગાઈ.</translation>
 <translation id="1908234395526491708">UDP વિનંતી નિષ્ફળ થઈ</translation>
@@ -622,6 +624,7 @@
 <translation id="6379086450106841622">ટચસ્ક્રીન</translation>
 <translation id="6381741036071372448">તમારા કીબોર્ડનું પરીક્ષણ કરો</translation>
 <translation id="6388847657025262518">સ્કૅનરનું દસ્તાવેજ ફીડર જામ થઈ ગયું છે. ફીડર ચેક કરો અને ફરી પ્રયાસ કરો.</translation>
+<translation id="6394634179843537518">ફાઇલ ઉમેરો</translation>
 <translation id="6410257289063177456">છબી ફાઇલો</translation>
 <translation id="641081527798843608">વિષય મેળ</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_hr.xtb b/chromeos/strings/chromeos_strings_hr.xtb
index 979173ce..fe046bcbc 100644
--- a/chromeos/strings/chromeos_strings_hr.xtb
+++ b/chromeos/strings/chromeos_strings_hr.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Korisnik</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Otvoren je prozor za ažuriranje opreme za vanjske uređaje. Dostupna ažuriranja: <ph name="NUM_UPDATES" />.</translation>
+<translation id="1145516343487477149">Pronađite članke pomoći i odgovore na česta pitanja o Chromebooku</translation>
 <translation id="1165039591588034296">Pogreška</translation>
 <translation id="1175697296044146566">Ovim uređajem <ph name="DEVICE_TYPE" /> upravlja <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">Prosječan (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Isključivanje tamne teme</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Isključivanje tamnog načina</translation>
+<translation id="1881188606372070653">Idite na <ph name="BEGIN_LINK1" />stranicu za pravnu pomoć<ph name="END_LINK1" /> da biste zatražili izmjenu sadržaja zbog pravnih razloga. Neki podaci o računu i sustavu možda će se poslati Googleu. Podatke koje nam dostavite upotrijebit ćemo za rješavanje tehničkih problema i poboljšanje naših usluga, u skladu s našim <ph name="BEGIN_LINK2" />pravilima o privatnosti<ph name="END_LINK2" /> i <ph name="BEGIN_LINK3" />uvjetima pružanja usluge<ph name="END_LINK3" />.</translation>
 <translation id="1887850431809612466">Hardverska revizija</translation>
 <translation id="1905710495812624430">Premašen je maksimalan dopušteni broj pokušaja.</translation>
 <translation id="1908234395526491708">Neuspješni UDP zahtjevi</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Dodirni zaslon</translation>
 <translation id="6381741036071372448">Testirajte tipkovnicu</translation>
 <translation id="6388847657025262518">Ulagač dokumenata u skener je zaglavljen. Provjerite ulagač i pokušajte ponovo.</translation>
+<translation id="6394634179843537518">Dodaj datoteku</translation>
 <translation id="6410257289063177456">Slikovne datoteke</translation>
 <translation id="641081527798843608">Podudaranje predmeta</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_hy.xtb b/chromeos/strings/chromeos_strings_hy.xtb
index 5c63e68..bc5c4c3 100644
--- a/chromeos/strings/chromeos_strings_hy.xtb
+++ b/chromeos/strings/chromeos_strings_hy.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Օգտատեր</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Բացված է արտաքին սարքերի համար ներկառուցված ծրագրաշարի թարմացման պատուհանը։ Հասանելի է <ph name="NUM_UPDATES" /> թարմացում։</translation>
+<translation id="1145516343487477149">Գտեք օգնության հոդվածներ և Chromebook-ի վերաբերյալ հաճախ տրվող հարցերի պատասխաններ</translation>
 <translation id="1165039591588034296">Սխալ</translation>
 <translation id="1175697296044146566">Այս <ph name="DEVICE_TYPE" /> սարքը կառավարվում է <ph name="MANAGER" /> տիրույթի կողմից։</translation>
 <translation id="1175951029573070619">Միջին (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Անջատել մուգ թեման</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Անջատել մուգ ռեժիմը</translation>
+<translation id="1881188606372070653">Իրավական հիմքերով բովանդակության փոփոխություն պահանջելու համար անցեք <ph name="BEGIN_LINK1" />Իրավական հարցերով օգնության էջ<ph name="END_LINK1" />։ Հաշվի և համակարգի որոշ տվյալներ կարող են ուղարկվել Google-ին։ Ձեր տրամադրած տեղեկությունները կօգտագործվեն տեխնիկական խնդիրները լուծելու և մեր ծառայությունների որակը բարելավելու նպատակով՝ մեր <ph name="BEGIN_LINK2" />Գաղտնիության քաղաքականության<ph name="END_LINK2" /> և <ph name="BEGIN_LINK3" />Օգտագործման պայմանների<ph name="END_LINK3" /> համաձայն։</translation>
 <translation id="1887850431809612466">Սարքի տարբերակը</translation>
 <translation id="1905710495812624430">Փորձերի առավելագույն թույլատրելի քանակը սպառվել է:</translation>
 <translation id="1908234395526491708">Ձախողված UDP հարցումներ</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">հպէկրան</translation>
 <translation id="6381741036071372448">Փորձարկեք ձեր ստեղնաշարը</translation>
 <translation id="6388847657025262518">Սկաների փաստաթղթերի մատակարարը լռվել է։ Ստուգեք մատակարարը և նորից փորձեք։</translation>
+<translation id="6394634179843537518">Ավելացնել ֆայլ</translation>
 <translation id="6410257289063177456">Պատկերների ֆայլեր</translation>
 <translation id="641081527798843608">Թեմաների համընկնում</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_id.xtb b/chromeos/strings/chromeos_strings_id.xtb
index 4d2967b..99e42eeb 100644
--- a/chromeos/strings/chromeos_strings_id.xtb
+++ b/chromeos/strings/chromeos_strings_id.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Pengguna</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Jendela update firmware untuk perangkat eksternal terbuka. <ph name="NUM_UPDATES" /> update tersedia.</translation>
+<translation id="1145516343487477149">Temukan artikel bantuan dan jawaban atas pertanyaan umum tentang Chromebook</translation>
 <translation id="1165039591588034296">Kesalahan</translation>
 <translation id="1175697296044146566"><ph name="DEVICE_TYPE" /> ini dikelola oleh <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">Standar (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Nonaktifkan tema gelap</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Nonaktifkan mode gelap</translation>
+<translation id="1881188606372070653">Buka <ph name="BEGIN_LINK1" />halaman Bantuan Hukum<ph name="END_LINK1" /> untuk meminta perubahan konten atas alasan hukum. Beberapa informasi akun dan sistem dapat dikirimkan ke Google. Kami akan menggunakan informasi yang Anda berikan untuk membantu mengatasi masalah teknis dan meningkatkan layanan kami, sesuai dengan <ph name="BEGIN_LINK2" />Kebijakan Privasi<ph name="END_LINK2" /> dan <ph name="BEGIN_LINK3" />Persyaratan Layanan<ph name="END_LINK3" /> kami.</translation>
 <translation id="1887850431809612466">Revisi hardware</translation>
 <translation id="1905710495812624430">Melebihi batas percobaan maksimum yang diizinkan.</translation>
 <translation id="1908234395526491708">Kegagalan permintaan UDP</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Layar sentuh</translation>
 <translation id="6381741036071372448">Uji keyboard Anda</translation>
 <translation id="6388847657025262518">Pengumpan dokumen pemindai macet. Periksa pengumpan, lalu coba lagi.</translation>
+<translation id="6394634179843537518">Tambahkan file</translation>
 <translation id="6410257289063177456">File Gambar</translation>
 <translation id="641081527798843608">Kecocokan subjek</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_iw.xtb b/chromeos/strings/chromeos_strings_iw.xtb
index 534a2a4..25b54fd 100644
--- a/chromeos/strings/chromeos_strings_iw.xtb
+++ b/chromeos/strings/chromeos_strings_iw.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">משתמש</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">החלון של עדכון הקושחה למכשירים חיצוניים פתוח. יש <ph name="NUM_UPDATES" /> עדכונים זמינים.</translation>
+<translation id="1145516343487477149">‏חיפוש של מאמרי עזרה ותשובות לשאלות נפוצות בנושא Chromebook</translation>
 <translation id="1165039591588034296">שגיאה</translation>
 <translation id="1175697296044146566"><ph name="DEVICE_TYPE" /> זה מנוהל על-ידי <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">ממוצע (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">השבתת העיצוב הכהה</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">השבתת המצב הכהה</translation>
+<translation id="1881188606372070653">‏אפשר לעבור אל <ph name="BEGIN_LINK1" />דף העזרה המשפטית<ph name="END_LINK1" /> כדי לבקש שינויים בתוכן מסיבות משפטיות. פרטים מסוימים על החשבון והמערכת עשויים להישלח ל-Google. אנחנו נשתמש במידע שיתקבל ממך כדי לטפל בבעיות טכניות ולשפר את השירותים שלנו, בכפוף ל<ph name="BEGIN_LINK2" />מדיניות הפרטיות<ph name="END_LINK2" /> ו<ph name="BEGIN_LINK3" />לתנאים ולהגבלות<ph name="END_LINK3" /> שלנו.</translation>
 <translation id="1887850431809612466">שכתוב חומרה</translation>
 <translation id="1905710495812624430">חריגה ממספר הניסיונות המרבי המותר.</translation>
 <translation id="1908234395526491708">‏בקשות UDP נכשלו</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">מסך מגע</translation>
 <translation id="6381741036071372448">בדיקת המקלדת</translation>
 <translation id="6388847657025262518">מזין המסמכים של הסורק תקוע. יש לבדוק אותו ולנסות שוב.</translation>
+<translation id="6394634179843537518">הוספה של קובץ</translation>
 <translation id="6410257289063177456">קובצי תמונה</translation>
 <translation id="641081527798843608">התאמת נושא</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_ja.xtb b/chromeos/strings/chromeos_strings_ja.xtb
index 2aeb145..83e49f9 100644
--- a/chromeos/strings/chromeos_strings_ja.xtb
+++ b/chromeos/strings/chromeos_strings_ja.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">ユーザー</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">外部デバイスのファームウェアを更新するためのウィンドウが開いています。<ph name="NUM_UPDATES" /> 件のアップデートがあります。</translation>
+<translation id="1145516343487477149">ヘルプ記事と Chromebook に関するよくある質問の回答を確認できます</translation>
 <translation id="1165039591588034296">エラー</translation>
 <translation id="1175697296044146566">この <ph name="DEVICE_TYPE" /> は <ph name="MANAGER" /> によって管理されています。</translation>
 <translation id="1175951029573070619">普通(<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">ダークモードをオフにする</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">ダークモードをオフにする</translation>
+<translation id="1881188606372070653">法的理由によりコンテンツの変更をリクエストするには、<ph name="BEGIN_LINK1" />法的な問題に関するヘルプページ<ph name="END_LINK1" />をご覧ください。アカウント情報とシステム情報の一部が Google に送信されます。ご提供いただいた情報は、Google で技術的な問題の解決やサービスの改善を図るため、<ph name="BEGIN_LINK2" />プライバシー ポリシー<ph name="END_LINK2" />と<ph name="BEGIN_LINK3" />利用規約<ph name="END_LINK3" />に沿って使用されます。</translation>
 <translation id="1887850431809612466">ハードウェア リビジョン</translation>
 <translation id="1905710495812624430">最大試行回数を超えました。</translation>
 <translation id="1908234395526491708">UDP リクエストに失敗しました</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">タッチスクリーン</translation>
 <translation id="6381741036071372448">キーボードをテストする</translation>
 <translation id="6388847657025262518">スキャナの給紙トレイが詰まっています。トレイを確認してから、もう一度お試しください。</translation>
+<translation id="6394634179843537518">ファイルを追加</translation>
 <translation id="6410257289063177456">画像ファイル</translation>
 <translation id="641081527798843608">件名の一致</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_ko.xtb b/chromeos/strings/chromeos_strings_ko.xtb
index 1c67ab2..595eef0 100644
--- a/chromeos/strings/chromeos_strings_ko.xtb
+++ b/chromeos/strings/chromeos_strings_ko.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">사용자</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">외부 기기용 펌웨어 업데이트 창이 열려 있습니다. 업데이트가 <ph name="NUM_UPDATES" />개 있습니다.</translation>
+<translation id="1145516343487477149">Chromebook과 관련된 일반적인 질문에 관한 도움말 및 답변 찾기</translation>
 <translation id="1165039591588034296">오류</translation>
 <translation id="1175697296044146566">이 <ph name="DEVICE_TYPE" /> 기기는 <ph name="MANAGER" />에서 관리합니다.</translation>
 <translation id="1175951029573070619">평균(<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">어두운 테마 사용 중지</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">어두운 모드 사용 중지</translation>
+<translation id="1881188606372070653">법적인 이유로 콘텐츠 변경을 요청하려면 <ph name="BEGIN_LINK1" />법률 도움말 페이지<ph name="END_LINK1" />로 이동하세요. 일부 계정 및 시스템 정보가 Google로 전송될 수 있습니다. 제공하신 정보는 기술적인 문제를 해결하고 서비스를 개선하는 데 사용되며, <ph name="BEGIN_LINK2" />개인정보처리방침<ph name="END_LINK2" /> 및 <ph name="BEGIN_LINK3" />서비스 약관<ph name="END_LINK3" />이 적용됩니다.</translation>
 <translation id="1887850431809612466">하드웨어 버전</translation>
 <translation id="1905710495812624430">허용되는 최대 시도 횟수를 초과했습니다.</translation>
 <translation id="1908234395526491708">UDP 요청 실패</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">터치스크린</translation>
 <translation id="6381741036071372448">키보드 테스트</translation>
 <translation id="6388847657025262518">스캐너의 급지대에 용지가 걸렸습니다. 급지대를 확인한 후 다시 시도해 보세요.</translation>
+<translation id="6394634179843537518">파일 추가</translation>
 <translation id="6410257289063177456">이미지 파일</translation>
 <translation id="641081527798843608">주제 일치</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_ky.xtb b/chromeos/strings/chromeos_strings_ky.xtb
index 07848ce..e9dea79 100644
--- a/chromeos/strings/chromeos_strings_ky.xtb
+++ b/chromeos/strings/chromeos_strings_ky.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Колдонуучу</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Тышкы түзмөктөрдө орнотулган программаны жаңыртуу терезеси ачык. <ph name="NUM_UPDATES" /> жаңыртуу бар.</translation>
+<translation id="1145516343487477149">Chromebook тууралуу көп берилүүчү суроолорго жоопторду жана макалаларды табасыз</translation>
 <translation id="1165039591588034296">Ката</translation>
 <translation id="1175697296044146566"><ph name="DEVICE_TYPE" /> түзмөгүн <ph name="MANAGER" /> башкарат.</translation>
 <translation id="1175951029573070619">Орточо (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Караңгы теманы өчүрүү</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Караңгы теманы өчүрүү</translation>
+<translation id="1881188606372070653">Эгер кандайдыр бир мыйзам бузулуп жатса, <ph name="BEGIN_LINK1" />Юридикалык жардам бетине<ph name="END_LINK1" /> өтүңүз. Аккаунт жана тутум жөнүндө айрым маалымат Google'га жөнөтүлүшү мүмкүн. Сиз берген маалыматты <ph name="BEGIN_LINK2" />Купуялык саясаты<ph name="END_LINK2" /> менен <ph name="BEGIN_LINK3" />Тейлөө шарттарына<ph name="END_LINK3" /> ылайык техникалык маселелерди чечүү жана кызматтарыбызды жакшыртуу үчүн пайдаланабыз.</translation>
 <translation id="1887850431809612466">Жабдыкты оңдоо</translation>
 <translation id="1905710495812624430">Аракеттер уруксат берилген чегинен ашты.</translation>
 <translation id="1908234395526491708">Ишке ашпай калган UDP сурамдары</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Сенсордук экран</translation>
 <translation id="6381741036071372448">Баскычтопту колдонуп көрүңүз</translation>
 <translation id="6388847657025262518">Сканердин документ түрмөгү такалып калды. Түрмөктү текшерип, кайра аракет кылыңыз.</translation>
+<translation id="6394634179843537518">Файл кошуу</translation>
 <translation id="6410257289063177456">Сүрөт файлдары</translation>
 <translation id="641081527798843608">Темасы дал келди</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_ml.xtb b/chromeos/strings/chromeos_strings_ml.xtb
index 2bf56fcd..3e20b03 100644
--- a/chromeos/strings/chromeos_strings_ml.xtb
+++ b/chromeos/strings/chromeos_strings_ml.xtb
@@ -581,7 +581,7 @@
 <translation id="6037291330010597344">സ്‌കാനറിന്റെ ഡോക്യുമെന്റ് ഫീഡർ ശൂന്യമാണ്. ഡോക്യുമെന്റുകൾ ചേർത്ത് വീണ്ടും ശ്രമിക്കുക.</translation>
 <translation id="6040143037577758943">അടയ്ക്കുക</translation>
 <translation id="6040852767465482106">അജ്ഞാത ഐഡന്‍റിറ്റി</translation>
-<translation id="604124094241169006">സ്വപ്രേരിതം</translation>
+<translation id="604124094241169006">സ്വയമേവ</translation>
 <translation id="6048107060512778456">പ്രിന്റ് ചെയ്യാനായില്ല - പേപ്പർ ജാമായിരിക്കുന്നു</translation>
 <translation id="6050189528197190982">ഗ്രേസ്‌കെയിൽ</translation>
 <translation id="6058625436358447366">പൂർത്തിയാക്കാൻ നിങ്ങളുടെ പഴയ പാസ്‌വേഡും പുതിയ പാസ്‌വേഡും നൽകുക</translation>
diff --git a/chromeos/strings/chromeos_strings_or.xtb b/chromeos/strings/chromeos_strings_or.xtb
index c9d41f3..2b99ae35 100644
--- a/chromeos/strings/chromeos_strings_or.xtb
+++ b/chromeos/strings/chromeos_strings_or.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">ଉପଯୋଗକର୍ତ୍ତା</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">ଏକ୍ସଟର୍ନଲ ଡିଭାଇସଗୁଡ଼ିକ ପାଇଁ ଫାର୍ମୱେର ଅପଡେଟ ୱିଣ୍ଡୋ ଖୋଲା ଅଛି। <ph name="NUM_UPDATES" />ଟି ଅପଡେଟ ଉପଲବ୍ଧ ଅଛି।</translation>
+<translation id="1145516343487477149">ସହାୟତା ଆର୍ଟିକିଲ ଏବଂ ସାଧାରଣ Chromebook ପ୍ରଶ୍ନଗୁଡ଼ିକର ଉତ୍ତର ପାଆନ୍ତୁ</translation>
 <translation id="1165039591588034296">ତ୍ରୁଟି</translation>
 <translation id="1175697296044146566">ଏହି <ph name="DEVICE_TYPE" />, <ph name="MANAGER" /> ଦ୍ୱାରା ପରିଚାଳିତ ହେଉଛି।</translation>
 <translation id="1175951029573070619">ସାଧାରଣ (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">ଗାଢ଼ା ଥିମ୍ ବନ୍ଦ କରନ୍ତୁ</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">ଡାର୍କ ମୋଡ୍ ବନ୍ଦ କରନ୍ତୁ</translation>
+<translation id="1881188606372070653">ଆଇନଗତ କାରଣଗୁଡ଼ିକ ପାଇଁ ବିଷୟବସ୍ତୁ ପରିବର୍ତ୍ତନର ଅନୁରୋଧ କରିବାକୁ <ph name="BEGIN_LINK1" />ଆଇନଗତ ସହାୟତା ପୃଷ୍ଠା<ph name="END_LINK1" />କୁ ଯାଆନ୍ତୁ। କିଛି ଆକାଉଣ୍ଟ ଏବଂ ସିଷ୍ଟମ ସୂଚନା Googleକୁ ପଠାଯାଇପାରେ। ଆମର <ph name="BEGIN_LINK2" />ଗୋପନୀୟତା ନୀତି<ph name="END_LINK2" /> ଏବଂ <ph name="BEGIN_LINK3" />ସେବାର ସର୍ତ୍ତାବଳୀ<ph name="END_LINK3" /> ଅନୁସାରେ, ଟେକନିକାଲ ସମସ୍ୟାର ସମାଧାନ କରିବା ଏବଂ ଆମର ସେବାଗୁଡ଼ିକୁ ଉନ୍ନତ କରିବା ପାଇଁ ଆପଣ ଆମକୁ ଦେଇଥିବା ସୂଚନାକୁ ଆମେ ବ୍ୟବହାର କରିବୁ।</translation>
 <translation id="1887850431809612466">ହାର୍ଡୱେୟାର୍ ପୁନରାବୃତ୍ତି</translation>
 <translation id="1905710495812624430">ସର୍ବାଧିକ ଅନୁମୋଦିତ ପ୍ରଚେଷ୍ଟା ସୀମା ଅତିକ୍ରମ କଲା।</translation>
 <translation id="1908234395526491708">UDP ଅନୁରୋଧ ବିଫଳ</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">ଟଚସ୍କ୍ରିନ୍</translation>
 <translation id="6381741036071372448">ଆପଣଙ୍କ କୀବୋର୍ଡକୁ ପରୀକ୍ଷା କରନ୍ତୁ</translation>
 <translation id="6388847657025262518">ସ୍କାନରର ଡକ୍ୟୁମେଣ୍ଟ ଫିଡର୍ ଜାମ୍ ହୋଇଯାଇଛି। ଫିଡରକୁ ଯାଞ୍ଚ କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation>
+<translation id="6394634179843537518">ଫାଇଲ ଯୋଗ କରନ୍ତୁ</translation>
 <translation id="6410257289063177456">ଛବି ଫାଇଲ୍‌ଗୁଡ଼ିକ</translation>
 <translation id="641081527798843608">ବିଷୟ ମେଳ</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_pa.xtb b/chromeos/strings/chromeos_strings_pa.xtb
index 321ce8b..8ee785e 100644
--- a/chromeos/strings/chromeos_strings_pa.xtb
+++ b/chromeos/strings/chromeos_strings_pa.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">ਵਰਤੋਂਕਾਰ</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">ਬਾਹਰੀ ਡੀਵਾਈਸਾਂ ਲਈ ਅੱਪਡੇਟ ਫ਼ਰਮਵੇਅਰ ਵਿੰਡੋ ਖੁੱਲ੍ਹੀ ਹੈ। <ph name="NUM_UPDATES" /> ਅੱਪਡੇਟ ਉਪਲਬਧ ਹਨ।</translation>
+<translation id="1145516343487477149">ਮਦਦ ਲੇਖ ਅਤੇ Chromebook ਸੰਬੰਧੀ ਆਮ ਸਵਾਲਾਂ ਦੇ ਜਵਾਬ ਲੱਭੋ</translation>
 <translation id="1165039591588034296">ਗੜਬੜ</translation>
 <translation id="1175697296044146566"><ph name="MANAGER" /> ਵੱਲੋਂ ਇਸ <ph name="DEVICE_TYPE" /> ਦਾ ਪ੍ਰਬੰਧਨ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।</translation>
 <translation id="1175951029573070619">ਔਸਤ (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">ਗੂੜ੍ਹਾ ਥੀਮ ਬੰਦ ਕਰੋ</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">ਗੂੜ੍ਹਾ ਮੋਡ ਬੰਦ ਕਰੋ</translation>
+<translation id="1881188606372070653">ਕਨੂੰਨੀ ਕਾਰਨਾਂ ਕਰਕੇ ਸਮੱਗਰੀ ਵਿੱਚ ਤਬਦੀਲੀਆਂ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕਰਨ ਲਈ <ph name="BEGIN_LINK1" />ਕਨੂੰਨੀ ਮਦਦ ਪੰਨੇ<ph name="END_LINK1" /> 'ਤੇ ਜਾਓ। ਖਾਤੇ ਅਤੇ ਸਿਸਟਮ ਦੀ ਕੁਝ ਜਾਣਕਾਰੀ Google ਨੂੰ ਭੇਜੀ ਜਾ ਸਕਦੀ ਹੈ। ਅਸੀਂ ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਾਨੂੰ ਦਿੱਤੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਾਡੀ <ph name="BEGIN_LINK2" />ਪਰਦੇਦਾਰੀ ਨੀਤੀ<ph name="END_LINK2" /> ਅਤੇ <ph name="BEGIN_LINK3" />ਸੇਵਾ ਦੇ ਨਿਯਮਾਂ<ph name="END_LINK3" /> ਦੇ ਅਧੀਨ, ਤਕਨੀਕੀ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਹੱਲ ਕਰਨ ਅਤੇ ਸਾਡੀਆਂ ਸੇਵਾਵਾਂ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ ਵਰਤਾਂਗੇ।</translation>
 <translation id="1887850431809612466">ਹਾਰਡਵੇਅਰ ਸੰਸ਼ੋਧਨ</translation>
 <translation id="1905710495812624430">ਅਧਿਕਤਮ ਮਨਜ਼ੂਰ ਕੀਤੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ ਵਧੀਆਂ।</translation>
 <translation id="1908234395526491708">UDP ਬੇਨਤੀ ਦੀਆਂ ਅਸਫਲਤਾਵਾਂ</translation>
@@ -622,6 +624,7 @@
 <translation id="6379086450106841622">ਟੱਚਸਕ੍ਰੀਨ</translation>
 <translation id="6381741036071372448">ਆਪਣੇ ਕੀ-ਬੋਰਡ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਦੇਖੋ</translation>
 <translation id="6388847657025262518">ਸਕੈਨਰ ਦਾ ਦਸਤਾਵੇਜ਼ ਫ਼ੀਡਰ ਜਾਮ ਹੋ ਗਿਆ ਹੈ। ਫ਼ੀਡਰ ਦੀ ਜਾਂਚ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
+<translation id="6394634179843537518">ਫ਼ਾਈਲ ਸ਼ਾਮਲ ਕਰੋ</translation>
 <translation id="6410257289063177456">ਚਿੱਤਰ ਫਾਈਲਾਂ</translation>
 <translation id="641081527798843608">ਵਿਸ਼ਾ ਮਿਲਾਨ</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_ru.xtb b/chromeos/strings/chromeos_strings_ru.xtb
index 6a9bcb5..d0dde15 100644
--- a/chromeos/strings/chromeos_strings_ru.xtb
+++ b/chromeos/strings/chromeos_strings_ru.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Пользователь</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Открыто окно со сведениями о доступных обновлениях (<ph name="NUM_UPDATES" />) встроенного ПО для внешних устройств.</translation>
+<translation id="1145516343487477149">Находите нужные справочные статьи и ответы на частые вопросы об устройствах Chromebook.</translation>
 <translation id="1165039591588034296">Ошибка</translation>
 <translation id="1175697296044146566">Этим устройством <ph name="DEVICE_TYPE" /> управляет <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">Средний (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Выключить тёмную тему</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Выключить тёмную тему</translation>
+<translation id="1881188606372070653">Если контент нарушает закон, <ph name="BEGIN_LINK1" />отправьте запрос на исправление<ph name="END_LINK1" />. Некоторые сведения об аккаунте и системе могут быть отправлены в Google. Это помогает нам устранять технические неполадки и улучшать наши сервисы. Ваши данные будут обрабатываться в соответствии с <ph name="BEGIN_LINK2" />Политикой конфиденциальности<ph name="END_LINK2" /> и <ph name="BEGIN_LINK3" />Условиями использования<ph name="END_LINK3" />.</translation>
 <translation id="1887850431809612466">Версия оборудования</translation>
 <translation id="1905710495812624430">Превышено максимально допустимое число попыток.</translation>
 <translation id="1908234395526491708">Невыполненные запросы UDP.</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Сенсорный экран</translation>
 <translation id="6381741036071372448">Проверьте свою клавиатуру</translation>
 <translation id="6388847657025262518">Автоподатчик документов заклинило. Устраните проблему и повторите попытку.</translation>
+<translation id="6394634179843537518">Добавить файл</translation>
 <translation id="6410257289063177456">Файлы изображений</translation>
 <translation id="641081527798843608">Совпадение тем</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_sk.xtb b/chromeos/strings/chromeos_strings_sk.xtb
index 9bebd33d5..13fb8c3 100644
--- a/chromeos/strings/chromeos_strings_sk.xtb
+++ b/chromeos/strings/chromeos_strings_sk.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Používateľ</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Okno aktualizácie firmvéru externých zariadení je otvorené. K dispozícii je tento počet aktualizácií: <ph name="NUM_UPDATES" />.</translation>
+<translation id="1145516343487477149">Vyhľadajte články pomocníka a odpovede na bežné otázky o Chromebooku</translation>
 <translation id="1165039591588034296">Chyba</translation>
 <translation id="1175697296044146566">Toto zariadenie <ph name="DEVICE_TYPE" /> spravuje <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">Priemerné (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Vypnúť tmavý motív</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Vypnúť tmavý režim</translation>
+<translation id="1881188606372070653">Ak chcete požiadať o zmenu obsahu z právnych dôvodov, prejdite na stránku <ph name="BEGIN_LINK1" />právnej pomoci<ph name="END_LINK1" />. Niektoré informácie o účte a systéme môžu byť odoslané Googlu. Pomocou informácií, ktoré nám poskytnete, odstránime technické problémy a zlepšíme svoje služby v súlade s <ph name="BEGIN_LINK2" />pravidlami ochrany súkromia<ph name="END_LINK2" /> a <ph name="BEGIN_LINK3" />zmluvnými podmienkami<ph name="END_LINK3" />.</translation>
 <translation id="1887850431809612466">Revízia hardvéru</translation>
 <translation id="1905710495812624430">Maximálny počet povolených pokusov bol prekročený.</translation>
 <translation id="1908234395526491708">Neúspešné žiadosti UDP</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Dotyková obrazovka</translation>
 <translation id="6381741036071372448">Test klávesnice</translation>
 <translation id="6388847657025262518">Podávač dokumentov skenera je zaseknutý. Skontrolujte ho a skúste to znova.</translation>
+<translation id="6394634179843537518">Pridajte súbor</translation>
 <translation id="6410257289063177456">Súbory obrázkov</translation>
 <translation id="641081527798843608">Zhoda predmetu</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_sl.xtb b/chromeos/strings/chromeos_strings_sl.xtb
index 86271937..d737898 100644
--- a/chromeos/strings/chromeos_strings_sl.xtb
+++ b/chromeos/strings/chromeos_strings_sl.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Uporabnik</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Okno za posodobitev vdelane programske opreme za zunanje naprave je odprto. Na voljo je toliko posodobitev: <ph name="NUM_UPDATES" />.</translation>
+<translation id="1145516343487477149">Poiščite članke s pomočjo in odgovore na pogosta vprašanja o Chromebookih.</translation>
 <translation id="1165039591588034296">Napaka</translation>
 <translation id="1175697296044146566">To napravo <ph name="DEVICE_TYPE" /> upravlja <ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">Povprečna (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Izklop temne teme</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Izklop temnega načina</translation>
+<translation id="1881188606372070653">Če želite zahtevati spremembe vsebine zaradi pravnih razlogov, obiščite <ph name="BEGIN_LINK1" />stran s pravno pomočjo<ph name="END_LINK1" />. Nekateri podatki o računu in sistemu bodo morda poslani Googlu. Informacije, ki nam jih pošljete, bomo v skladu z našim <ph name="BEGIN_LINK2" />pravilnikom o zasebnosti<ph name="END_LINK2" /> in <ph name="BEGIN_LINK3" />pogoji storitve<ph name="END_LINK3" /> uporabljali za odpravljanje tehničnih težav in izboljševanje naših storitev.</translation>
 <translation id="1887850431809612466">Različica strojne opreme</translation>
 <translation id="1905710495812624430">Preseženo je največje dovoljeno število dovoljenih poskusov.</translation>
 <translation id="1908234395526491708">Neuspele zahteve UDP</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Zaslon na dotik</translation>
 <translation id="6381741036071372448">Preizkusite tipkovnico</translation>
 <translation id="6388847657025262518">V podajalniku papirja optičnega bralnika se je zagozdil papir. Preverite podajalnik in poskusite znova.</translation>
+<translation id="6394634179843537518">Dodaj datoteko</translation>
 <translation id="6410257289063177456">Slikovne datoteke</translation>
 <translation id="641081527798843608">Ujemanje zadeve</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_ta.xtb b/chromeos/strings/chromeos_strings_ta.xtb
index 3e198e0..27e9b08 100644
--- a/chromeos/strings/chromeos_strings_ta.xtb
+++ b/chromeos/strings/chromeos_strings_ta.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">பயனர்</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">வெளிப்புறச் சாதனங்களுக்கான நிலைபொருள் புதுப்பிப்புச் சாளரம் திறந்துள்ளது. <ph name="NUM_UPDATES" /> புதுப்பிப்புகள் உள்ளன.</translation>
+<translation id="1145516343487477149">உதவிக் கட்டுரைகளையும் Chromebook குறித்த பொதுவான கேள்விகளுக்கான பதில்களையும் கண்டறியலாம்</translation>
 <translation id="1165039591588034296">பிழை</translation>
 <translation id="1175697296044146566">இந்த <ph name="DEVICE_TYPE" /> சாதனத்தை <ph name="MANAGER" /> நிர்வகிக்கிறது.</translation>
 <translation id="1175951029573070619">சுமாராக உள்ளது (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">டார்க் தீமினை முடக்குதல்</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">டார்க் பயன்முறையை முடக்குதல்</translation>
+<translation id="1881188606372070653">சட்டப்பூர்வக் காரணங்களுக்காக உள்ளடக்க மாற்றங்களைக் கோர, <ph name="BEGIN_LINK1" />சட்டப்பூர்வ உதவிப் பக்கத்திற்குச்<ph name="END_LINK1" /> செல்லவும். சில கணக்கு மற்றும் சிஸ்டம் தகவல்கள் Googleளுக்கு அனுப்பப்படக்கூடும். தொழில்நுட்பச் சிக்கல்களைச் சரிசெய்யவும் எங்கள் சேவைகளை மேம்படுத்தவும் நீங்கள் அளிக்கும் தகவல்களை எங்கள் <ph name="BEGIN_LINK2" />தனியுரிமைக் கொள்கை<ph name="END_LINK2" />, <ph name="BEGIN_LINK3" />சேவை விதிமுறைகள்<ph name="END_LINK3" /> ஆகியவற்றுக்கு உட்பட்டுப் பயன்படுத்துவோம்.</translation>
 <translation id="1887850431809612466">வன்பொருள் பதிப்பு</translation>
 <translation id="1905710495812624430">அனுமதிக்கப்பட்ட அதிகபட்ச முயற்சிகளைக் கடந்துவிட்டீர்கள்.</translation>
 <translation id="1908234395526491708">UDP கோரிக்கையை அனுப்ப முடியவில்லை</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">டச்ஸ்கிரீன்</translation>
 <translation id="6381741036071372448">கீபோர்டைச் சோதனை செய்தல்</translation>
 <translation id="6388847657025262518">ஸ்கேனரின் டாக்குமெண்ட் ஃபீடரில் தாள் சிக்கிக் கொண்டது. ஃபீடரைச் சரிசெய்துவிட்டு மீண்டும் முயலவும்.</translation>
+<translation id="6394634179843537518">ஃபைலைச் சேர்</translation>
 <translation id="6410257289063177456">பட ஃபைல்கள்</translation>
 <translation id="641081527798843608">சப்ஜெக்ட் மேட்ச்</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_te.xtb b/chromeos/strings/chromeos_strings_te.xtb
index 4943e4a2..c0a0e12e 100644
--- a/chromeos/strings/chromeos_strings_te.xtb
+++ b/chromeos/strings/chromeos_strings_te.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">వినియోగదారు</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">బాహ్య పరికరాలకు ఫర్మ్‌వేర్‌‌ను అప్‌డేట్ చేసే విండో తెరిచి ఉంది. <ph name="NUM_UPDATES" /> అప్‌డేట్‌లు అందుబాటులో ఉన్నాయి.</translation>
+<translation id="1145516343487477149">సాధారణ Chromebook ప్రశ్నలకు సహాయక ఆర్టికల్స్, సమాధానాలను కనుగొంటుంది</translation>
 <translation id="1165039591588034296">ఎర్రర్</translation>
 <translation id="1175697296044146566"><ph name="MANAGER" /> ద్వారా ఈ <ph name="DEVICE_TYPE" /> మేనేజ్ చేయబడుతోంది.</translation>
 <translation id="1175951029573070619">మోస్తరుగా ఉంది (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">ముదురు రంగు రూపాన్ని ఆఫ్ చేయండి</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">డార్క్ మోడ్‌ను ఆఫ్ చేయండి</translation>
+<translation id="1881188606372070653">చట్టపరమైన కారణాల దృష్ట్యా కంటెంట్‌కు మార్పులను రిక్వెస్ట్ చేయడానికి <ph name="BEGIN_LINK1" />చట్టపరమైన సహాయ పేజీకి<ph name="END_LINK1" /> వెళ్లండి. ఖాతా, సిస్టమ్‌కు సంబంధించిన కొంత సమాచారం Googleకు పంపబడవచ్చు. మీరు మాకు అందించే సమాచారాన్ని మా <ph name="BEGIN_LINK2" />గోప్యతా పాలసీ<ph name="END_LINK2" />, ఇంకా <ph name="BEGIN_LINK3" />సర్వీస్ నియమాలకు<ph name="END_LINK3" /> అనుగుణంగా, టెక్నికల్ సమస్యలను పరిష్కరించడానికి, మా సర్వీస్‌లను మరింత మెరుగుపరచడానికి మేము ఉపయోగిస్తాము.</translation>
 <translation id="1887850431809612466">హార్డ్‌వేర్ పునర్విమర్శ</translation>
 <translation id="1905710495812624430">అనుమతించిన గరిష్ట ప్రయత్నాలు మించిపోయారు.</translation>
 <translation id="1908234395526491708">UDP రిక్వెస్ట్ వైఫల్యాలు</translation>
@@ -350,7 +352,7 @@
 <translation id="4131410914670010031">నలుపు మరియు తెలుపు</translation>
 <translation id="4140251671072434548">RMA సర్వర్‌ను అన్‌లాక్ చేయండి</translation>
 <translation id="4145784616224233563">HTTP ఫైర్‌వాల్</translation>
-<translation id="4147897805161313378">Google ఫోటోలు</translation>
+<translation id="4147897805161313378">Google Photos</translation>
 <translation id="4150201353443180367">డిస్‌ప్లే</translation>
 <translation id="4155551848414053977">స్కానర్ ఆన్ చేయబడి ఉందని, అలాగే నెట్‌వర్క్ లేదా ప్రత్యక్ష కనెక్షన్ ద్వారా అందుబాటులో ఉందని నిర్ధారించుకోండి</translation>
 <translation id="4159784952369912983">వంగపండు రంగు</translation>
@@ -622,6 +624,7 @@
 <translation id="6379086450106841622">టచ్‌స్క్రీన్</translation>
 <translation id="6381741036071372448">మీ కీబోర్డ్‌ను టెస్ట్ చేయండి</translation>
 <translation id="6388847657025262518">స్కానర్ డాక్యుమెంట్ ఫీడర్ ఇరుక్కుపోయింది. ఫీడర్‌ను చెక్ చేసి, మళ్లీ ట్రై చేయండి.</translation>
+<translation id="6394634179843537518">ఫైల్‌ను జోడించండి</translation>
 <translation id="6410257289063177456">చిత్రం ఫైళ్లు</translation>
 <translation id="641081527798843608">విషయ సరిపోలిక</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
@@ -634,7 +637,7 @@
 <translation id="649050271426829538">ఆగిపోయింది - కాగితం జామ్ అయింది</translation>
 <translation id="6494974875566443634">అనుకూలీకరణ</translation>
 <translation id="6500818810472529210">Google Searchలో ఫలితాన్ని చూడండి</translation>
-<translation id="650266656685499220">ఆల్బమ్‌లను క్రియేట్ చేయడానికి, 'Google ఫోటోలు'కు వెళ్లండి</translation>
+<translation id="650266656685499220">ఆల్బమ్‌లను క్రియేట్ చేయడానికి, 'Google Photos'కు వెళ్లండి</translation>
 <translation id="6516990319416533844">బ్యాటరీ ఛార్జ్ అయ్యే రేట్‌ను పరీక్షించడానికి, కొంత వ్యవధి పాటు మీ బ్యాటరీని తగ్గనివ్వండి</translation>
 <translation id="6517239166834772319">అన్వేషణ</translation>
 <translation id="6527081081771465939">తెలియని WiFi భద్రతా ప్రోటోకాల్</translation>
diff --git a/chromeos/strings/chromeos_strings_tr.xtb b/chromeos/strings/chromeos_strings_tr.xtb
index e871d07b..5a1425d 100644
--- a/chromeos/strings/chromeos_strings_tr.xtb
+++ b/chromeos/strings/chromeos_strings_tr.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Kullanıcı</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Harici cihazlar için donanım yazılımını güncelleme penceresi açık. <ph name="NUM_UPDATES" /> güncelleme var.</translation>
+<translation id="1145516343487477149">Sık sorulan Chromebook sorularıyla ilgili yardım makaleleri ve yanıtlar bulun</translation>
 <translation id="1165039591588034296">Hata</translation>
 <translation id="1175697296044146566">Bu <ph name="DEVICE_TYPE" />, <ph name="MANAGER" /> tarafından yönetiliyor.</translation>
 <translation id="1175951029573070619">Ortalama (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Koyu temayı kapat</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Koyu modu kapat</translation>
+<translation id="1881188606372070653">Yasal nedenlerden dolayı içerik değişikliği talebinde bulunmak istiyorsanız <ph name="BEGIN_LINK1" />Yasal Yardım sayfasını<ph name="END_LINK1" /> ziyaret edin. Bazı hesap ve sistem bilgileri Google'a gönderilebilir. Bizimle paylaştığınız bilgileri, <ph name="BEGIN_LINK2" />Gizlilik Politikası<ph name="END_LINK2" /> ve <ph name="BEGIN_LINK3" />Hizmet Şartları<ph name="END_LINK3" />'na uygun şekilde teknik sorunları gidermek ve size daha iyi hizmet sunmak için kullanırız.</translation>
 <translation id="1887850431809612466">Donanım düzeltmesi</translation>
 <translation id="1905710495812624430">İzin verilen maksimum deneme sayısı aşıldı.</translation>
 <translation id="1908234395526491708">UDP istek hataları</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Dokunmatik ekran</translation>
 <translation id="6381741036071372448">Klavyenizi test edin</translation>
 <translation id="6388847657025262518">Tarayıcının doküman besleyicisi sıkıştı. Besleyiciyi kontrol edip tekrar deneyin.</translation>
+<translation id="6394634179843537518">Dosya ekle</translation>
 <translation id="6410257289063177456">Resim Dosyaları</translation>
 <translation id="641081527798843608">Konu eşleştirmesi</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_uz.xtb b/chromeos/strings/chromeos_strings_uz.xtb
index 195b929..2d0182c 100644
--- a/chromeos/strings/chromeos_strings_uz.xtb
+++ b/chromeos/strings/chromeos_strings_uz.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Foydalanuvchi</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Tashqi qurilmalar uchun mikrodasturni yangilash oynasi ochiq. <ph name="NUM_UPDATES" /> ta yangilanish chiqdi.</translation>
+<translation id="1145516343487477149">Yordam maqolalari va umumiy Chromebook savollariga javoblar toping</translation>
 <translation id="1165039591588034296">Xatolik</translation>
 <translation id="1175697296044146566">Bu <ph name="DEVICE_TYPE" /> qurilmasi <ph name="MANAGER" /> domenida boshqariladi.</translation>
 <translation id="1175951029573070619">Oʻrtacha (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Tungi mavzuni faolsizlantirish</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Tungi rejimdan chiqish</translation>
+<translation id="1881188606372070653">Agar bu kontent biror qonunni buzsa, shikoyat yuborish uchun <ph name="BEGIN_LINK1" />Huquqiy yordam sahifasiga<ph name="END_LINK1" /> kiring. Hisob va tizimga oid ayrim axborotlar Google kompaniyasiga yuborilishi mumkin. Bizga taqdim etilgan maʼlumotlardan texnik muammolarni hal qilish va xizmatlarimizni yaxshilashda foydalanamiz. Bunda <ph name="BEGIN_LINK2" />Maxfiylik siyosati<ph name="END_LINK2" /> va <ph name="BEGIN_LINK3" />Xizmat shartlariga<ph name="END_LINK3" /> rioya qilinadi.</translation>
 <translation id="1887850431809612466">Qurilma versiyasi</translation>
 <translation id="1905710495812624430">Urinishlar soni cheklovdan oshib ketdi.</translation>
 <translation id="1908234395526491708">Bajarilmagan UDP soʻrovlari</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Sensorli ekran</translation>
 <translation id="6381741036071372448">Klaviaturangizni sinang</translation>
 <translation id="6388847657025262518">Skanerga joylanadigan qogʻozlar tiqilib qoldi. Hujjat joylash panelini tekshirib, qaytadan urining.</translation>
+<translation id="6394634179843537518">Fayl qoʻshish</translation>
 <translation id="6410257289063177456">Tasvir fayllar</translation>
 <translation id="641081527798843608">Mavzu mosligi</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_vi.xtb b/chromeos/strings/chromeos_strings_vi.xtb
index 3f459eb..3cbfe61 100644
--- a/chromeos/strings/chromeos_strings_vi.xtb
+++ b/chromeos/strings/chromeos_strings_vi.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Người dùng</translation>
 <translation id="1128128132059598906">EAP-TTLS</translation>
 <translation id="1145018782460575098">Đang mở cửa sổ cập nhật chương trình cơ sở cho các thiết bị bên ngoài. Có <ph name="NUM_UPDATES" /> bản cập nhật</translation>
+<translation id="1145516343487477149">Tìm bài viết trợ giúp và câu trả lời cho các câu hỏi phổ biến về Chromebook</translation>
 <translation id="1165039591588034296">Lỗi</translation>
 <translation id="1175697296044146566"><ph name="DEVICE_TYPE" /> này do <ph name="MANAGER" /> quản lý.</translation>
 <translation id="1175951029573070619">Trung bình (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Tắt giao diện tối</translation>
 <translation id="1874612839560830905">MTU</translation>
 <translation id="188114911237521550">Tắt chế độ tối</translation>
+<translation id="1881188606372070653">Nếu bạn muốn yêu cầu thay đổi nội dung vì lý do pháp lý, hãy truy cập <ph name="BEGIN_LINK1" />trang Trợ giúp pháp lý<ph name="END_LINK1" />. Một số thông tin về tài khoản và hệ thống có thể được gửi đến Google. Chúng tôi sẽ dùng thông tin mà bạn cung cấp để giúp khắc phục các vấn đề kỹ thuật, đồng thời cải thiện các dịch vụ theo <ph name="BEGIN_LINK2" />Chính sách quyền riêng tư<ph name="END_LINK2" /> và <ph name="BEGIN_LINK3" />Điều khoản dịch vụ<ph name="END_LINK3" /> của chúng tôi.</translation>
 <translation id="1887850431809612466">Hiệu chỉnh phần cứng</translation>
 <translation id="1905710495812624430">Đã vượt quá số lần thử tối đa được phép.</translation>
 <translation id="1908234395526491708">Không gửi được yêu cầu UDP</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Màn hình cảm ứng</translation>
 <translation id="6381741036071372448">Kiểm tra bàn phím</translation>
 <translation id="6388847657025262518">Khay nạp tài liệu của máy quét bị kẹt. Hãy kiểm tra khay nạp rồi thử lại.</translation>
+<translation id="6394634179843537518">Thêm tệp</translation>
 <translation id="6410257289063177456">Tệp hình ảnh</translation>
 <translation id="641081527798843608">Khớp với chủ đề</translation>
 <translation id="6423239382391657905">OpenVPN</translation>
diff --git a/chromeos/strings/chromeos_strings_zu.xtb b/chromeos/strings/chromeos_strings_zu.xtb
index 27f4edba..6667e2a 100644
--- a/chromeos/strings/chromeos_strings_zu.xtb
+++ b/chromeos/strings/chromeos_strings_zu.xtb
@@ -16,6 +16,7 @@
 <translation id="1124772482545689468">Umsebenzisi</translation>
 <translation id="1128128132059598906">I-EAP-TTLS</translation>
 <translation id="1145018782460575098">Iwindi lesibuyekezo se-firmware samadivayisi wangaphandle livuliwe. izibuyekezo ezitholakalayo <ph name="NUM_UPDATES" /></translation>
+<translation id="1145516343487477149">Thola izindaba ezichaza ngosizo nezimpendulo zemibuzo ye-Chromebook</translation>
 <translation id="1165039591588034296">Iphutha</translation>
 <translation id="1175697296044146566">Le-<ph name="DEVICE_TYPE" /> iphethwe yi-<ph name="MANAGER" />.</translation>
 <translation id="1175951029573070619">Ngokusesilinganisweni (<ph name="SIGNAL_STRENGTH" />)</translation>
@@ -120,6 +121,7 @@
 <translation id="1871569928317311284">Vala itimu emnyama</translation>
 <translation id="1874612839560830905">I-MTU</translation>
 <translation id="188114911237521550">Vala imodi emnyama</translation>
+<translation id="1881188606372070653">Yiya <ph name="BEGIN_LINK1" />ekhasini losizo lwezomthetho<ph name="END_LINK1" /> ukuze ucele izinguquko zokuqukethwe ngezizathu zezomthetho. Olunye ulwazi lwe-akhawunti nolwesistimu lungathunyelwa ku-Google. Sizosebenzisa ulwazi osinika lona ukulungisa izinkinga zobuchwepheshe futhi sithuthukise amasevisi, ngokuvumelana <ph name="BEGIN_LINK2" />Nenqubomgomo yethu Yobumfihlo<ph name="END_LINK2" /> kanye <ph name="BEGIN_LINK3" />Nemigomo Yesevisi<ph name="END_LINK3" />.</translation>
 <translation id="1887850431809612466">Ukubuyekeza kwezingxenyekazi zekhompuyutha</translation>
 <translation id="1905710495812624430">Imizamo emikhulu evunyelwe idluliwe.</translation>
 <translation id="1908234395526491708">Ukwehluleka kwesicelo se-UDP</translation>
@@ -623,6 +625,7 @@
 <translation id="6379086450106841622">Isikrini esithintwayo</translation>
 <translation id="6381741036071372448">Hlola ikhibhodi yakho</translation>
 <translation id="6388847657025262518">Okuphakelayo kweskena sedokhumenti kujemile. Hlola okuphakelayo bese uyazama futhi.</translation>
+<translation id="6394634179843537518">Engeza ifayela</translation>
 <translation id="6410257289063177456">Amafayela wesithombe</translation>
 <translation id="641081527798843608">Ukufana kwesihloko</translation>
 <translation id="6423239382391657905">I-OpenVPN</translation>
diff --git a/components/autofill/content/renderer/form_tracker.cc b/components/autofill/content/renderer/form_tracker.cc
index 1d7bbb3..f7bc4bd9 100644
--- a/components/autofill/content/renderer/form_tracker.cc
+++ b/components/autofill/content/renderer/form_tracker.cc
@@ -162,8 +162,8 @@
     absl::optional<blink::WebNavigationType> navigation_type) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(form_tracker_sequence_checker_);
   blink::WebLocalFrame* navigated_frame = render_frame()->GetWebFrame();
-  // Ony handle main frame.
-  if (navigated_frame->Parent())
+  // Ony handle primary main frame.
+  if (!navigated_frame->IsOutermostMainFrame())
     return;
 
   // Bug fix for crbug.com/368690. isProcessingUserGesture() is false when
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 96724ce..deef095 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -1380,7 +1380,9 @@
   // If a sub frame has been destroyed while the user was entering information
   // into a password form, try to save the data. See https://crbug.com/450806
   // for examples of sites that perform login using this technique.
-  if (render_frame()->GetWebFrame()->Parent() && browser_has_form_to_process_) {
+  // We are treating primary main frame and the root of embedded frames the same
+  // on purpose.
+  if (browser_has_form_to_process_ && render_frame()->GetWebFrame()->Parent()) {
     DCHECK(FrameCanAccessPasswordManager());
     GetPasswordManagerDriver().DynamicFormSubmission(
         SubmissionIndicatorEvent::FRAME_DETACHED);
@@ -1408,12 +1410,12 @@
   }
 
   WebLocalFrame* navigated_frame = render_frame()->GetWebFrame();
-  if (navigated_frame->Parent()) {
-    LogMessage(logger.get(), Logger::STRING_FRAME_NOT_MAIN_FRAME);
-  } else {
+  if (navigated_frame->IsOutermostMainFrame()) {
     // This is a new navigation, so require a new user gesture before filling in
     // passwords.
     gatekeeper_.Reset();
+  } else {
+    LogMessage(logger.get(), Logger::STRING_FRAME_NOT_MAIN_FRAME);
   }
 
   CleanupOnDocumentShutdown();
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc
index e780918..d8b9b49 100644
--- a/components/autofill/content/renderer/password_generation_agent.cc
+++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -233,8 +233,8 @@
 
 void PasswordGenerationAgent::DidCommitProvisionalLoad(
     ui::PageTransition transition) {
-  // Update stats for main frame navigation.
-  if (!render_frame()->GetWebFrame()->Parent()) {
+  // Update stats for primary main frame navigation.
+  if (render_frame()->GetWebFrame()->IsOutermostMainFrame()) {
     if (current_generation_item_) {
       if (current_generation_item_->password_edited_) {
         password_generation::LogPasswordGenerationEvent(
diff --git a/components/autofill/core/browser/field_filler.cc b/components/autofill/core/browser/field_filler.cc
index f7309c0..0a9cf86 100644
--- a/components/autofill/core/browser/field_filler.cc
+++ b/components/autofill/core/browser/field_filler.cc
@@ -268,7 +268,11 @@
       for (const auto& alternative_name : state_entry->alternative_names())
         full_names.push_back(base::UTF8ToUTF16(alternative_name));
     } else {
-      full_names.push_back(value);
+      if (value.size() > 2) {
+        full_names.push_back(value);
+      } else {
+        abbreviations.push_back(value);
+      }
     }
   }
 
@@ -283,6 +287,17 @@
   if (!state_abbreviation.empty())
     abbreviations.push_back(std::move(state_abbreviation));
 
+  // Remove `abbreviations` from the `full_names` as a precautionary measure in
+  // case the `AlternativeStateNameMap` contains bad data.
+  base::ranges::sort(abbreviations);
+  full_names.erase(
+      base::ranges::remove_if(full_names,
+                              [&](const std::u16string& full_name) {
+                                return base::ranges::binary_search(
+                                    abbreviations, full_name);
+                              }),
+      full_names.end());
+
   // Try an exact match of the abbreviation first.
   for (const auto& abbreviation : abbreviations) {
     if (!abbreviation.empty() &&
diff --git a/components/autofill/core/browser/field_filler_unittest.cc b/components/autofill/core/browser/field_filler_unittest.cc
index 195b28a..1d14272 100644
--- a/components/autofill/core/browser/field_filler_unittest.cc
+++ b/components/autofill/core/browser/field_filler_unittest.cc
@@ -2058,6 +2058,31 @@
   EXPECT_EQ(u"BY", field.value);
 }
 
+// Tests that Autofill does not fill the state when abbreviated data is stored
+// in the profile and none of the options match with the abbreviated state.
+TEST_F(AutofillFieldFillerTest,
+       DoNotFillStateFieldWhenAbbrStoredInProfileAndNotInOptionsList) {
+  base::test::ScopedFeatureList feature;
+  feature.InitAndEnableFeature(features::kAutofillUseAlternativeStateNameMap);
+
+  test::ClearAlternativeStateNameMapForTesting();
+  std::vector<const char*> kState = {"Colombia", "Connecticut", "Colifornia"};
+
+  AutofillField field;
+  test::CreateTestSelectField(kState, &field);
+  field.set_heuristic_type(GetActivePatternSource(), ADDRESS_HOME_STATE);
+
+  AutofillProfile address;
+  address.SetRawInfo(ADDRESS_HOME_STATE, u"CO");
+  address.SetRawInfo(ADDRESS_HOME_COUNTRY, u"US");
+
+  FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
+  filler.FillFormField(field, &address, /*forced_fill_values=*/{}, &field,
+                       /*cvc=*/std::u16string(),
+                       mojom::RendererFormDataAction::kFill);
+  EXPECT_EQ(u"", field.value);
+}
+
 TEST_F(AutofillFieldFillerTest, PreviewVirtualMonth) {
   AutofillField field;
   field.form_control_type = "text";
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index c0a220df..2c7a440 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -76,7 +76,6 @@
 
 namespace autofill {
 
-using structured_address::HonorificPrefixEnabled;
 using structured_address::StructuredAddressesEnabled;
 using structured_address::StructuredNamesEnabled;
 
@@ -1668,43 +1667,34 @@
   // Make sure everything is set up correctly.
   EXPECT_EQ(1U, personal_data_->GetProfiles().size());
 
-  personal_data_->GetNonEmptyTypes(&non_empty_types);
+  std::vector<ServerFieldType> expected_types{NAME_FIRST,
+                                              NAME_LAST,
+                                              NAME_FULL,
+                                              EMAIL_ADDRESS,
+                                              ADDRESS_HOME_LINE1,
+                                              ADDRESS_HOME_STREET_ADDRESS,
+                                              ADDRESS_HOME_CITY,
+                                              ADDRESS_HOME_STATE,
+                                              ADDRESS_HOME_ZIP,
+                                              ADDRESS_HOME_COUNTRY,
+                                              PHONE_HOME_NUMBER,
+                                              PHONE_HOME_COUNTRY_CODE,
+                                              PHONE_HOME_CITY_CODE,
+                                              PHONE_HOME_CITY_AND_NUMBER,
+                                              PHONE_HOME_WHOLE_NUMBER};
   // For structured names and addresses, there are more non-empty types.
   // TODO(crbug.com/1103421): Clean once launched.
-  unsigned int non_empty_types_expectation = 15;
   if (StructuredNamesEnabled())
-    non_empty_types_expectation += 1;
-  // TODO(crbug.com/1130194): Clean once launched.
-  if (StructuredAddressesEnabled())
-    non_empty_types_expectation += 2;
-  if (HonorificPrefixEnabled())
-    non_empty_types_expectation += 1;
-
-  EXPECT_EQ(non_empty_types_expectation, non_empty_types.size());
-
-  EXPECT_TRUE(non_empty_types.count(NAME_FIRST));
-  EXPECT_TRUE(non_empty_types.count(NAME_LAST));
-  // TODO(crbug.com/1103421): Clean once launched.
-  if (StructuredNamesEnabled())
-    EXPECT_TRUE(non_empty_types.count(NAME_LAST_SECOND));
-  EXPECT_TRUE(non_empty_types.count(NAME_FULL));
-  EXPECT_TRUE(non_empty_types.count(EMAIL_ADDRESS));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE1));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_ADDRESS));
+    expected_types.push_back(NAME_LAST_SECOND);
   // TODO(crbug.com/1130194): Clean once launched.
   if (StructuredAddressesEnabled()) {
-    EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_NAME));
-    EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_HOUSE_NUMBER));
+    expected_types.insert(expected_types.end(), {ADDRESS_HOME_STREET_NAME,
+                                                 ADDRESS_HOME_HOUSE_NUMBER});
   }
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_CITY));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STATE));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_COUNTRY));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_NUMBER));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_COUNTRY_CODE));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_CODE));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_AND_NUMBER));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_WHOLE_NUMBER));
+
+  personal_data_->GetNonEmptyTypes(&non_empty_types);
+  EXPECT_THAT(non_empty_types,
+              testing::UnorderedElementsAreArray(expected_types));
 
   // Test with multiple profiles stored.
   AutofillProfile profile1(base::GenerateGUID(), test::kEmptyOrigin);
@@ -1722,44 +1712,13 @@
 
   EXPECT_EQ(3U, personal_data_->GetProfiles().size());
 
+  expected_types.insert(
+      expected_types.end(),
+      {NAME_MIDDLE, NAME_MIDDLE_INITIAL, ADDRESS_HOME_LINE2, COMPANY_NAME});
+
   personal_data_->GetNonEmptyTypes(&non_empty_types);
-  non_empty_types_expectation = 19;
-  // For structured names, there is one more non-empty type.
-  // TODO(crbug.com/1103421): Clean once launched.
-  if (StructuredNamesEnabled())
-    non_empty_types_expectation += 1;
-  if (HonorificPrefixEnabled())
-    non_empty_types_expectation += 1;
-  // TODO(crbug.com/1130194): Clean once launched.
-  if (StructuredAddressesEnabled())
-    non_empty_types_expectation += 2;
-  EXPECT_EQ(non_empty_types_expectation, non_empty_types.size());
-  EXPECT_TRUE(non_empty_types.count(NAME_FIRST));
-  EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE));
-  EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE_INITIAL));
-  // TODO(crbug.com/1103421): Clean once launched.
-  if (StructuredNamesEnabled())
-    EXPECT_TRUE(non_empty_types.count(NAME_LAST));
-  EXPECT_TRUE(non_empty_types.count(NAME_FULL));
-  EXPECT_TRUE(non_empty_types.count(EMAIL_ADDRESS));
-  EXPECT_TRUE(non_empty_types.count(COMPANY_NAME));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE1));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE2));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_ADDRESS));
-  // TODO(crbug.com/1130194): Clean once launched.
-  if (StructuredAddressesEnabled()) {
-    EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_NAME));
-    EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_HOUSE_NUMBER));
-  }
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_CITY));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STATE));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_COUNTRY));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_NUMBER));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_CODE));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_COUNTRY_CODE));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_AND_NUMBER));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_WHOLE_NUMBER));
+  EXPECT_THAT(non_empty_types,
+              testing::UnorderedElementsAreArray(expected_types));
 
   // Test with credit card information also stored.
   CreditCard credit_card(base::GenerateGUID(), test::kEmptyOrigin);
@@ -1770,54 +1729,16 @@
   WaitForOnPersonalDataChanged();
   EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
 
+  expected_types.insert(
+      expected_types.end(),
+      {CREDIT_CARD_NAME_FULL, CREDIT_CARD_NAME_FIRST, CREDIT_CARD_NAME_LAST,
+       CREDIT_CARD_NUMBER, CREDIT_CARD_TYPE, CREDIT_CARD_EXP_MONTH,
+       CREDIT_CARD_EXP_2_DIGIT_YEAR, CREDIT_CARD_EXP_4_DIGIT_YEAR,
+       CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR});
+
   personal_data_->GetNonEmptyTypes(&non_empty_types);
-  // For structured names, there is one more non-empty type.
-  // TODO(crbug.com/1103421): Clean once launched.
-  non_empty_types_expectation = 29;
-  if (StructuredNamesEnabled())
-    non_empty_types_expectation += 1;
-  if (HonorificPrefixEnabled())
-    non_empty_types_expectation += 1;
-  // TODO(crbug.com/1130194): Clean once launched.
-  if (StructuredAddressesEnabled())
-    non_empty_types_expectation += 2;
-  EXPECT_EQ(non_empty_types_expectation, non_empty_types.size());
-  EXPECT_TRUE(non_empty_types.count(NAME_FIRST));
-  EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE));
-  EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE_INITIAL));
-  EXPECT_TRUE(non_empty_types.count(NAME_LAST));
-  EXPECT_TRUE(non_empty_types.count(NAME_FULL));
-  if (StructuredNamesEnabled())
-    EXPECT_TRUE(non_empty_types.count(NAME_LAST));
-  EXPECT_TRUE(non_empty_types.count(EMAIL_ADDRESS));
-  EXPECT_TRUE(non_empty_types.count(COMPANY_NAME));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE1));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE2));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_ADDRESS));
-  // TODO(crbug.com/1130194): Clean once launched.
-  if (StructuredAddressesEnabled()) {
-    EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_NAME));
-    EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_HOUSE_NUMBER));
-  }
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_CITY));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STATE));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP));
-  EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_COUNTRY));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_NUMBER));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_CODE));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_COUNTRY_CODE));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_AND_NUMBER));
-  EXPECT_TRUE(non_empty_types.count(PHONE_HOME_WHOLE_NUMBER));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_NAME_FULL));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_NAME_FIRST));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_NAME_LAST));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_NUMBER));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_TYPE));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_MONTH));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_2_DIGIT_YEAR));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_4_DIGIT_YEAR));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR));
-  EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR));
+  EXPECT_THAT(non_empty_types,
+              testing::UnorderedElementsAreArray(expected_types));
 }
 
 TEST_F(PersonalDataManagerTest, IncognitoReadOnly) {
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
index 3366f59..2131f4e 100644
--- a/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -7,11 +7,13 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <initializer_list>
 #include <limits>
 #include <map>
 #include <memory>
 #include <set>
 #include <utility>
+#include <vector>
 
 #include "base/command_line.h"
 #include "base/containers/contains.h"
@@ -21,6 +23,7 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
@@ -57,6 +60,428 @@
 
 namespace {
 
+constexpr base::StringPiece kAutofillTable = "autofill";
+constexpr base::StringPiece kName = "name";
+constexpr base::StringPiece kValue = "value";
+constexpr base::StringPiece kValueLower = "value_lower";
+constexpr base::StringPiece kDateCreated = "date_created";
+constexpr base::StringPiece kDateLastUsed = "date_last_used";
+constexpr base::StringPiece kCount = "count";
+
+constexpr base::StringPiece kAutofillProfilesTable = "autofill_profiles";
+constexpr base::StringPiece kGuid = "guid";
+constexpr base::StringPiece kLabel = "label";
+constexpr base::StringPiece kCompanyName = "company_name";
+constexpr base::StringPiece kStreetAddress = "street_address";
+constexpr base::StringPiece kDependentLocality = "dependent_locality";
+constexpr base::StringPiece kCity = "city";
+constexpr base::StringPiece kState = "state";
+constexpr base::StringPiece kZipcode = "zipcode";
+constexpr base::StringPiece kSortingCode = "sorting_code";
+constexpr base::StringPiece kCountryCode = "country_code";
+constexpr base::StringPiece kUseCount = "use_count";
+constexpr base::StringPiece kUseDate = "use_date";
+constexpr base::StringPiece kDateModified = "date_modified";
+constexpr base::StringPiece kOrigin = "origin";
+constexpr base::StringPiece kLanguageCode = "language_code";
+constexpr base::StringPiece kDisallowSettingsVisibleUpdates =
+    "disallow_settings_visible_updates";
+
+constexpr base::StringPiece kAutofillProfileAddressesTable =
+    "autofill_profile_addresses";
+// kGuid = "guid"
+// kStreetAddress = "street_address"
+constexpr base::StringPiece kStreetName = "street_name";
+constexpr base::StringPiece kDependentStreetName = "dependent_street_name";
+constexpr base::StringPiece kHouseNumber = "house_number";
+constexpr base::StringPiece kSubpremise = "subpremise";
+// kDependentLocality = "dependent_locality"
+// kCity = "city"
+// kState = "state"
+constexpr base::StringPiece kZipCode = "zip_code";
+// kCountryCode = "country_code"
+// kSortingCode = "sorting_code"
+constexpr base::StringPiece kPremiseName = "premise_name";
+constexpr base::StringPiece kApartmentNumber = "apartment_number";
+constexpr base::StringPiece kFloor = "floor";
+constexpr base::StringPiece kStreetAddressStatus = "street_address_status";
+constexpr base::StringPiece kStreetNameStatus = "street_name_status";
+constexpr base::StringPiece kDependentStreetNameStatus =
+    "dependent_street_name_status";
+constexpr base::StringPiece kHouseNumberStatus = "house_number_status";
+constexpr base::StringPiece kSubpremiseStatus = "subpremise_status";
+constexpr base::StringPiece kPremiseNameStatus = "premise_name_status";
+constexpr base::StringPiece kDependentLocalityStatus =
+    "dependent_locality_status";
+constexpr base::StringPiece kCityStatus = "city_status";
+constexpr base::StringPiece kStateStatus = "state_status";
+constexpr base::StringPiece kZipCodeStatus = "zip_code_status";
+constexpr base::StringPiece kCountryCodeStatus = "country_code_status";
+constexpr base::StringPiece kSortingCodeStatus = "sorting_code_status";
+constexpr base::StringPiece kApartmentNumberStatus = "apartment_number_status";
+constexpr base::StringPiece kFloorStatus = "floor_status";
+
+constexpr base::StringPiece kAutofillProfileNamesTable =
+    "autofill_profile_names";
+// kGuid = "guid"
+constexpr base::StringPiece kHonorificPrefix = "honorific_prefix";
+constexpr base::StringPiece kFirstName = "first_name";
+constexpr base::StringPiece kMiddleName = "middle_name";
+constexpr base::StringPiece kLastName = "last_name";
+constexpr base::StringPiece kFirstLastName = "first_last_name";
+constexpr base::StringPiece kConjunctionLastName = "conjunction_last_name";
+constexpr base::StringPiece kSecondLastName = "second_last_name";
+constexpr base::StringPiece kFullName = "full_name";
+constexpr base::StringPiece kFullNameWithHonorificPrefix =
+    "full_name_with_honorific_prefix";
+constexpr base::StringPiece kHonorificPrefixStatus = "honorific_prefix_status";
+constexpr base::StringPiece kFirstNameStatus = "first_name_status";
+constexpr base::StringPiece kMiddleNameStatus = "middle_name_status";
+constexpr base::StringPiece kLastNameStatus = "last_name_status";
+constexpr base::StringPiece kFirstLastNameStatus = "first_last_name_status";
+constexpr base::StringPiece kConjunctionLastNameStatus =
+    "conjunction_last_name_status";
+constexpr base::StringPiece kSecondLastNameStatus = "second_last_name_status";
+constexpr base::StringPiece kFullNameStatus = "full_name_status";
+constexpr base::StringPiece kFullNameWithHonorificPrefixStatus =
+    "full_name_with_honorific_prefix_status";
+
+constexpr base::StringPiece kAutofillProfileEmailsTable =
+    "autofill_profile_emails";
+// kGuid = "guid"
+constexpr base::StringPiece kEmail = "email";
+
+constexpr base::StringPiece kAutofillProfilePhonesTable =
+    "autofill_profile_phones";
+// kGuid = "guid"
+constexpr base::StringPiece kNumber = "number";
+
+constexpr base::StringPiece kAutofillProfileBirthdatesTable =
+    "autofill_profile_birthdates";
+// kGuid = "guid"
+constexpr base::StringPiece kDay = "day";
+constexpr base::StringPiece kMonth = "month";
+constexpr base::StringPiece kYear = "year";
+
+constexpr base::StringPiece kCreditCardsTable = "credit_cards";
+// kGuid = "guid"
+constexpr base::StringPiece kNameOnCard = "name_on_card";
+constexpr base::StringPiece kExpirationMonth = "expiration_month";
+constexpr base::StringPiece kExpirationYear = "expiration_year";
+constexpr base::StringPiece kCardNumberEncrypted = "card_number_encrypted";
+// kUseCount = "use_count"
+// kUseDate = "use_date"
+// kDateModified = "date_modified"
+// kOrigin = "origin"
+constexpr base::StringPiece kBillingAddressId = "billing_address_id";
+constexpr base::StringPiece kNickname = "nickname";
+
+constexpr base::StringPiece kMaskedCreditCardsTable = "masked_credit_cards";
+constexpr base::StringPiece kId = "id";
+constexpr base::StringPiece kStatus = "status";
+// kNameOnCard = "name_on_card"
+constexpr base::StringPiece kNetwork = "network";
+constexpr base::StringPiece kLastFour = "last_four";
+constexpr base::StringPiece kExpMonth = "exp_month";
+constexpr base::StringPiece kExpYear = "exp_year";
+constexpr base::StringPiece kBankName = "bank_name";
+// kNickname = "nickname"
+constexpr base::StringPiece kCardIssuer = "card_issuer";
+constexpr base::StringPiece kInstrumentId = "instrument_id";
+constexpr base::StringPiece kVirtualCardEnrollmentState =
+    "virtual_card_enrollment_state";
+constexpr base::StringPiece kCardArtUrl = "card_art_url";
+constexpr base::StringPiece kProductDescription = "product_description";
+
+constexpr base::StringPiece kUnmaskedCreditCardsTable = "unmasked_credit_cards";
+// kId = "id"
+// kCardNumberEncrypted = "card_number_encrypted"
+constexpr base::StringPiece kUnmaskDate = "unmask_date";
+
+constexpr base::StringPiece kServerCardCloudTokenDataTable =
+    "server_card_cloud_token_data";
+// kId = "id"
+constexpr base::StringPiece kSuffix = "suffix";
+// kExpMonth = "exp_month"
+// kExpYear = "exp_year"
+// kCardArtUrl = "card_art_url"
+constexpr base::StringPiece kInstrumentToken = "instrument_token";
+
+constexpr base::StringPiece kServerCardMetadataTable = "server_card_metadata";
+// kId = "id"
+// kUseCount = "use_count"
+// kUseDate = "use_date"
+// kBillingAddressId = "billing_address_id"
+
+constexpr base::StringPiece kServerAddressesTable = "server_addresses";
+// kId = "id"
+constexpr base::StringPiece kRecipientName = "recipient_name";
+// kCompanyName = "company_name"
+// kStreetAddress = "street_address"
+constexpr base::StringPiece kAddress1 = "address_1";
+constexpr base::StringPiece kAddress2 = "address_2";
+constexpr base::StringPiece kAddress3 = "address_3";
+constexpr base::StringPiece kAddress4 = "address_4";
+constexpr base::StringPiece kPostalCode = "postal_code";
+// kSortingCode = "sorting_code"
+// kCountryCode = "country_code"
+// kLanguageCode = "language_code"
+constexpr base::StringPiece kPhoneNumber = "phone_number";
+
+constexpr base::StringPiece kServerAddressMetadataTable =
+    "server_address_metadata";
+// kId = "id"
+// kUseCount = "use_count"
+// kUseDate = "use_date"
+constexpr base::StringPiece kHasConverted = "has_converted";
+
+constexpr base::StringPiece kAutofillSyncMetadataTable =
+    "autofill_sync_metadata";
+constexpr base::StringPiece kModelType = "model_type";
+constexpr base::StringPiece kStorageKey = "storage_key";
+// kValue = "value"
+
+constexpr base::StringPiece kAutofillModelTypeStateTable =
+    "autofill_model_type_state";
+// kModelType = "model_type"
+// kValue = "value"
+
+constexpr base::StringPiece kPaymentsCustomerDataTable =
+    "payments_customer_data";
+constexpr base::StringPiece kCustomerId = "customer_id";
+
+constexpr base::StringPiece kPaymentsUpiVpaTable = "payments_upi_vpa";
+constexpr base::StringPiece kVpa = "vpa";
+
+constexpr base::StringPiece kOfferDataTable = "offer_data";
+constexpr base::StringPiece kOfferId = "offer_id";
+constexpr base::StringPiece kOfferRewardAmount = "offer_reward_amount";
+constexpr base::StringPiece kExpiry = "expiry";
+constexpr base::StringPiece kOfferDetailsUrl = "offer_details_url";
+constexpr base::StringPiece kPromoCode = "promo_code";
+constexpr base::StringPiece kValuePropText = "value_prop_text";
+constexpr base::StringPiece kSeeDetailsText = "see_details_text";
+constexpr base::StringPiece kUsageInstructionsText = "usage_instructions_text";
+
+constexpr base::StringPiece kOfferEligibleInstrumentTable =
+    "offer_eligible_instrument";
+// kOfferId = "offer_id"
+// kInstrumentId = "instrument_id"
+
+constexpr base::StringPiece kOfferMerchantDomainTable = "offer_merchant_domain";
+// kOfferId = "offer_id"
+constexpr base::StringPiece kMerchantDomain = "merchant_domain";
+
+// Deprecated column names, that are still used in the migration logic.
+constexpr base::StringPiece kType = "type";
+
+// Helper functions to construct SQL statements from string constants.
+// - Functions with names corresponding to SQL keywords execute the statement
+//   directly and return if it was successful.
+// - Builder functions only assign the statement, which enables binding
+//   values to placeholders before running it.
+
+// Executes a CREATE TABLE statement on `db` which the provided `table_name`.
+// The columns are described in `column_names_and_types` as pairs of
+// (name, type), where type can include modifiers such as NOT NULL.
+// By specifying `compositive_primary_key`, a PRIMARY KEY (col1, col2, ..)
+// clause is generated.
+// Returns true if successful.
+bool CreateTable(
+    sql::Database* db,
+    base::StringPiece table_name,
+    std::initializer_list<std::pair<base::StringPiece, base::StringPiece>>
+        column_names_and_types,
+    std::initializer_list<base::StringPiece> composite_primary_key = {}) {
+  DCHECK(composite_primary_key.size() == 0 ||
+         composite_primary_key.size() >= 2);
+
+  std::vector<std::string> combined_names_and_types;
+  combined_names_and_types.reserve(column_names_and_types.size());
+  for (const auto& [name, type] : column_names_and_types)
+    combined_names_and_types.push_back(base::StrCat({name, " ", type}));
+
+  auto primary_key_clause =
+      composite_primary_key.size() == 0
+          ? ""
+          : base::StrCat({", PRIMARY KEY (",
+                          base::JoinString(composite_primary_key, ", "), ")"});
+
+  return db->Execute(
+      base::StrCat({"CREATE TABLE ", table_name, " (",
+                    base::JoinString(combined_names_and_types, ", "),
+                    primary_key_clause, ")"})
+          .c_str());
+}
+
+// Wrapper around `CreateTable()` that condition the creation on the
+// `table_name` not existing.
+// Returns true if the table now exists.
+bool CreateTableIfNotExists(
+    sql::Database* db,
+    base::StringPiece table_name,
+    std::initializer_list<std::pair<base::StringPiece, base::StringPiece>>
+        column_names_and_types,
+    std::initializer_list<base::StringPiece> composite_primary_key = {}) {
+  return db->DoesTableExist(table_name) ||
+         CreateTable(db, table_name, column_names_and_types,
+                     composite_primary_key);
+}
+
+// Creates and index on `table_name` for the provided `columns`.
+// The index is named after the table and columns, separated by '_'.
+// Returns true if successful.
+bool CreateIndex(sql::Database* db,
+                 base::StringPiece table_name,
+                 std::initializer_list<base::StringPiece> columns) {
+  auto index_name =
+      base::StrCat({table_name, "_", base::JoinString(columns, "_")});
+  return db->Execute(
+      base::StrCat({"CREATE INDEX ", index_name, " ON ", table_name, "(",
+                    base::JoinString(columns, ", "), ")"})
+          .c_str());
+}
+
+// Initializes `statement` with INSERT INTO `table_name`, with placeholders for
+// all `column_names`.
+// By setting `or_replace`, INSERT OR REPLACE INTO is used instead.
+void InsertBuilder(sql::Database* db,
+                   sql::Statement& statement,
+                   base::StringPiece table_name,
+                   std::initializer_list<base::StringPiece> column_names,
+                   bool or_replace = false) {
+  auto insert_or_replace =
+      base::StrCat({"INSERT ", or_replace ? "OR REPLACE " : ""});
+  auto placeholders = base::JoinString(
+      std::vector<std::string>(column_names.size(), "?"), ", ");
+  statement.Assign(db->GetUniqueStatement(
+      base::StrCat({insert_or_replace, "INTO ", table_name, " (",
+                    base::JoinString(column_names, ", "), ") VALUES (",
+                    placeholders, ")"})
+          .c_str()));
+}
+
+// Renames the table `from` into `to` and returns true if successful.
+bool RenameTable(sql::Database* db,
+                 base::StringPiece from,
+                 base::StringPiece to) {
+  return db->Execute(
+      base::StrCat({"ALTER TABLE ", from, " RENAME TO ", to}).c_str());
+}
+
+// Wrapper around `sql::Database::DoesColumnExist()`, because that function
+// only accepts const char* parameters.
+bool DoesColumnExist(sql::Database* db,
+                     base::StringPiece table_name,
+                     base::StringPiece column_name) {
+  return db->DoesColumnExist(std::string(table_name).c_str(),
+                             std::string(column_name).c_str());
+}
+
+// Adds a column named `column_name` of `type` to `table_name` and returns true
+// if successful.
+bool AddColumn(sql::Database* db,
+               base::StringPiece table_name,
+               base::StringPiece column_name,
+               base::StringPiece type) {
+  return db->Execute(base::StrCat({"ALTER TABLE ", table_name, " ADD COLUMN ",
+                                   column_name, " ", type})
+                         .c_str());
+}
+
+// Like `AddColumn()`, but conditioned on `column` not existing in `table_name`.
+// Returns true if the column is now part of the table
+bool AddColumnIfNotExists(sql::Database* db,
+                          base::StringPiece table_name,
+                          base::StringPiece column_name,
+                          base::StringPiece type) {
+  return DoesColumnExist(db, table_name, column_name) ||
+         AddColumn(db, table_name, column_name, type);
+}
+
+// Drops `table_name` and returns true if successful.
+bool DropTable(sql::Database* db, base::StringPiece table_name) {
+  return db->Execute(base::StrCat({"DROP TABLE ", table_name}).c_str());
+}
+
+// Initializes `statement` with DELETE FROM `table_name`. A WHERE clause
+// can optionally be specified in `where_clause`.
+void DeleteBuilder(sql::Database* db,
+                   sql::Statement& statement,
+                   base::StringPiece table_name,
+                   base::StringPiece where_clause = "") {
+  auto where =
+      where_clause.empty() ? "" : base::StrCat({" WHERE ", where_clause});
+  statement.Assign(db->GetUniqueStatement(
+      base::StrCat({"DELETE FROM ", table_name, where}).c_str()));
+}
+
+// Like `DeleteBuilder()`, but runs the statement and returns true if it was
+// successful.
+bool Delete(sql::Database* db,
+            base::StringPiece table_name,
+            base::StringPiece where_clause = "") {
+  sql::Statement statement;
+  DeleteBuilder(db, statement, table_name, where_clause);
+  return statement.Run();
+}
+
+// Wrapper around `DeleteBuilder()`, which initializes the where clause as
+// `column` = `value`.
+// Runs the statement and returns true if it was successful.
+bool DeleteWhereColumnEq(sql::Database* db,
+                         base::StringPiece table_name,
+                         base::StringPiece column,
+                         base::StringPiece value) {
+  sql::Statement statement;
+  DeleteBuilder(db, statement, table_name, base::StrCat({column, " = ?"}));
+  statement.BindString(0, value);
+  return statement.Run();
+}
+
+// Initializes `statement` with SELECT `columns` FROM `table_name` and
+// optionally further `modifiers`, such as WHERE, ORDER BY, etc.
+void SelectBuilder(sql::Database* db,
+                   sql::Statement& statement,
+                   base::StringPiece table_name,
+                   std::initializer_list<base::StringPiece> columns,
+                   base::StringPiece modifiers = "") {
+  statement.Assign(db->GetUniqueStatement(
+      base::StrCat({"SELECT ", base::JoinString(columns, ", "), " FROM ",
+                    table_name, " ", modifiers})
+          .c_str()));
+}
+
+// Wrapper around `SelectBuilder()` that restricts the it to the provided `guid`
+// and limits the results to 1. Returns `statement.is_valid() &&
+// statement.Step()`.
+bool SelectByGuid(sql::Database* db,
+                  sql::Statement& statement,
+                  base::StringPiece table_name,
+                  std::initializer_list<base::StringPiece> columns,
+                  base::StringPiece guid) {
+  DCHECK(base::Contains(columns, kGuid));
+  SelectBuilder(db, statement, table_name, columns, "WHERE guid=? LIMIT 1");
+  statement.BindString(0, guid);
+  return statement.is_valid() && statement.Step();
+}
+
+// Wrapper around `SelectBuilder()` that restricts it to the half-open interval
+// [low, high[ of `column_between`.
+void SelectBetween(sql::Database* db,
+                   sql::Statement& statement,
+                   base::StringPiece table_name,
+                   std::initializer_list<base::StringPiece> columns,
+                   base::StringPiece column_between,
+                   int64_t low,
+                   int64_t high) {
+  auto between_selector = base::StrCat(
+      {"WHERE ", column_between, " >= ? AND ", column_between, " < ?"});
+  SelectBuilder(db, statement, table_name, columns, between_selector);
+  statement.BindInt64(0, low);
+  statement.BindInt64(1, high);
+}
+
 // Constant to assign an unset verification status to structured address
 // components stored for legacy profiles.
 constexpr structured_address::VerificationStatus kNoStatus =
@@ -90,14 +515,12 @@
   int index = 0;
   s->BindString(index++, profile.guid());
 
-  s->BindString16(index++, GetInfo(profile, COMPANY_NAME));
-  s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_STREET_ADDRESS));
-  s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_DEPENDENT_LOCALITY));
-  s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_CITY));
-  s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_STATE));
-  s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_ZIP));
-  s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_SORTING_CODE));
-  s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_COUNTRY));
+  for (ServerFieldType type :
+       {COMPANY_NAME, ADDRESS_HOME_STREET_ADDRESS,
+        ADDRESS_HOME_DEPENDENT_LOCALITY, ADDRESS_HOME_CITY, ADDRESS_HOME_STATE,
+        ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, ADDRESS_HOME_COUNTRY}) {
+    s->BindString16(index++, GetInfo(profile, type));
+  }
   s->BindInt64(index++, profile.use_count());
   s->BindInt64(index++, profile.use_date().ToTimeT());
   s->BindInt64(index++, modification_date.ToTimeT());
@@ -110,15 +533,12 @@
 void AddAutofillProfileDetailsFromStatement(sql::Statement& s,
                                             AutofillProfile* profile) {
   int index = 1;  // 0 is for the guid.
-  profile->SetRawInfo(COMPANY_NAME, s.ColumnString16(index++));
-  profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, s.ColumnString16(index++));
-  profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                      s.ColumnString16(index++));
-  profile->SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(index++));
-  profile->SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(index++));
-  profile->SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(index++));
-  profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE, s.ColumnString16(index++));
-  profile->SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(index++));
+  for (ServerFieldType type :
+       {COMPANY_NAME, ADDRESS_HOME_STREET_ADDRESS,
+        ADDRESS_HOME_DEPENDENT_LOCALITY, ADDRESS_HOME_CITY, ADDRESS_HOME_STATE,
+        ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, ADDRESS_HOME_COUNTRY}) {
+    profile->SetRawInfo(type, s.ColumnString16(index++));
+  }
   profile->set_use_count(s.ColumnInt64(index++));
   profile->set_use_date(base::Time::FromTimeT(s.ColumnInt64(index++)));
   profile->set_modification_date(base::Time::FromTimeT(s.ColumnInt64(index++)));
@@ -145,9 +565,10 @@
   int index = 0;
   s->BindString(index++, credit_card.guid());
 
-  s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_NAME_FULL));
-  s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_MONTH));
-  s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_4_DIGIT_YEAR));
+  for (ServerFieldType type : {CREDIT_CARD_NAME_FULL, CREDIT_CARD_EXP_MONTH,
+                               CREDIT_CARD_EXP_4_DIGIT_YEAR}) {
+    s->BindString16(index++, GetInfo(credit_card, type));
+  }
   BindEncryptedCardToColumn(
       s, index++, credit_card.GetRawInfo(CREDIT_CARD_NUMBER), encryptor);
 
@@ -180,10 +601,10 @@
   credit_card->set_guid(s.ColumnString(index++));
   DCHECK(base::IsValidGUID(credit_card->guid()));
 
-  credit_card->SetRawInfo(CREDIT_CARD_NAME_FULL, s.ColumnString16(index++));
-  credit_card->SetRawInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(index++));
-  credit_card->SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR,
-                          s.ColumnString16(index++));
+  for (ServerFieldType type : {CREDIT_CARD_NAME_FULL, CREDIT_CARD_EXP_MONTH,
+                               CREDIT_CARD_EXP_4_DIGIT_YEAR}) {
+    credit_card->SetRawInfo(type, s.ColumnString16(index++));
+  }
   credit_card->SetRawInfo(CREDIT_CARD_NUMBER,
                           UnencryptedCardFromColumn(s, index++, encryptor));
   credit_card->set_use_count(s.ColumnInt64(index++));
@@ -200,53 +621,35 @@
                              sql::Database* db) {
   if (base::FeatureList::IsEnabled(
           features::kAutofillEnableSupportForMoreStructureInNames)) {
-    sql::Statement s(db->GetUniqueStatement(
-        "INSERT INTO autofill_profile_names "
-        "(guid, "
-        "honorific_prefix, honorific_prefix_status, "
-        "first_name, first_name_status, "
-        "middle_name, middle_name_status, "
-        "first_last_name, first_last_name_status, "
-        "conjunction_last_name, conjunction_last_name_status, "
-        "second_last_name, second_last_name_status, "
-        "last_name, last_name_status, "
-        "full_name, full_name_status, "
-        "full_name_with_honorific_prefix, "
-        "full_name_with_honorific_prefix_status) "
-        "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+    sql::Statement s;
+    InsertBuilder(
+        db, s, kAutofillProfileNamesTable,
+        {kGuid, kHonorificPrefix, kHonorificPrefixStatus, kFirstName,
+         kFirstNameStatus, kMiddleName, kMiddleNameStatus, kFirstLastName,
+         kFirstLastNameStatus, kConjunctionLastName, kConjunctionLastNameStatus,
+         kSecondLastName, kSecondLastNameStatus, kLastName, kLastNameStatus,
+         kFullName, kFullNameStatus, kFullNameWithHonorificPrefix,
+         kFullNameWithHonorificPrefixStatus});
     s.BindString(0, profile.guid());
-    s.BindString16(1, profile.GetRawInfo(NAME_HONORIFIC_PREFIX));
-    s.BindInt(2, profile.GetVerificationStatusInt(NAME_HONORIFIC_PREFIX));
-    s.BindString16(3, profile.GetRawInfo(NAME_FIRST));
-    s.BindInt(4, profile.GetVerificationStatusInt(NAME_FIRST));
-    s.BindString16(5, profile.GetRawInfo(NAME_MIDDLE));
-    s.BindInt(6, profile.GetVerificationStatusInt(NAME_MIDDLE));
-    s.BindString16(7, profile.GetRawInfo(NAME_LAST_FIRST));
-    s.BindInt(8, profile.GetVerificationStatusInt(NAME_LAST_FIRST));
-    s.BindString16(9, profile.GetRawInfo(NAME_LAST_CONJUNCTION));
-    s.BindInt(10, profile.GetVerificationStatusInt(NAME_LAST_CONJUNCTION));
-    s.BindString16(11, profile.GetRawInfo(NAME_LAST_SECOND));
-    s.BindInt(12, profile.GetVerificationStatusInt(NAME_LAST_SECOND));
-    s.BindString16(13, profile.GetRawInfo(NAME_LAST));
-    s.BindInt(14, profile.GetVerificationStatusInt(NAME_LAST));
-    s.BindString16(15, profile.GetRawInfo(NAME_FULL));
-    s.BindInt(16, profile.GetVerificationStatusInt(NAME_FULL));
-    s.BindString16(17, profile.GetRawInfo(NAME_FULL_WITH_HONORIFIC_PREFIX));
-    s.BindInt(
-        18, profile.GetVerificationStatusInt(NAME_FULL_WITH_HONORIFIC_PREFIX));
+    int index = 1;
+    for (ServerFieldType type :
+         {NAME_HONORIFIC_PREFIX, NAME_FIRST, NAME_MIDDLE, NAME_LAST_FIRST,
+          NAME_LAST_CONJUNCTION, NAME_LAST_SECOND, NAME_LAST, NAME_FULL,
+          NAME_FULL_WITH_HONORIFIC_PREFIX}) {
+      s.BindString16(index++, profile.GetRawInfo(type));
+      s.BindInt(index++, profile.GetVerificationStatusInt(type));
+    }
     return s.Run();
   }
   // Add the new name.
-  sql::Statement s(
-      db->GetUniqueStatement("INSERT INTO autofill_profile_names"
-                             " (guid, first_name, middle_name, last_name, "
-                             "full_name) "
-                             "VALUES (?,?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db, s, kAutofillProfileNamesTable,
+                {kGuid, kFirstName, kMiddleName, kLastName, kFullName});
   s.BindString(0, profile.guid());
-  s.BindString16(1, profile.GetRawInfo(NAME_FIRST));
-  s.BindString16(2, profile.GetRawInfo(NAME_MIDDLE));
-  s.BindString16(3, profile.GetRawInfo(NAME_LAST));
-  s.BindString16(4, profile.GetRawInfo(NAME_FULL));
+  int index = 1;
+  for (ServerFieldType type : {NAME_FIRST, NAME_MIDDLE, NAME_LAST, NAME_FULL}) {
+    s.BindString16(index++, profile.GetRawInfo(type));
+  }
   return s.Run();
 }
 
@@ -257,57 +660,50 @@
   // votes.
   if (base::FeatureList::IsEnabled(
           features::kAutofillEnableSupportForMoreStructureInAddresses)) {
-    sql::Statement s(db->GetUniqueStatement(
-        "INSERT INTO autofill_profile_addresses "
-        "(guid, "
-        "street_address, street_address_status, "
-        "street_name, street_name_status, "
-        "dependent_street_name, dependent_street_name_status, "
-        "house_number, house_number_status, "
-        "subpremise, subpremise_status, "
-        "premise_name, premise_name_status, "
-        "dependent_locality, dependent_locality_status, "
-        "city, city_status, "
-        "state, state_status, "
-        "zip_code, zip_code_status, "
-        "sorting_code, sorting_code_status, "
-        "country_code, country_code_status, "
-        "apartment_number, apartment_number_status, "
-        "floor, floor_status) "
-        "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+    sql::Statement s;
+    InsertBuilder(db, s, kAutofillProfileAddressesTable,
+                  {kGuid,
+                   kStreetAddress,
+                   kStreetAddressStatus,
+                   kStreetName,
+                   kStreetNameStatus,
+                   kDependentStreetName,
+                   kDependentStreetNameStatus,
+                   kHouseNumber,
+                   kHouseNumberStatus,
+                   kSubpremise,
+                   kSubpremiseStatus,
+                   kPremiseName,
+                   kPremiseNameStatus,
+                   kDependentLocality,
+                   kDependentLocalityStatus,
+                   kCity,
+                   kCityStatus,
+                   kState,
+                   kStateStatus,
+                   kZipCode,
+                   kZipCodeStatus,
+                   kSortingCode,
+                   kSortingCodeStatus,
+                   kCountryCode,
+                   kCountryCodeStatus,
+                   kApartmentNumber,
+                   kApartmentNumberStatus,
+                   kFloor,
+                   kFloorStatus});
 
     s.BindString(0, profile.guid());
-    s.BindString16(1, profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
-    s.BindInt(2, profile.GetVerificationStatusInt(ADDRESS_HOME_STREET_ADDRESS));
-    s.BindString16(3, profile.GetRawInfo(ADDRESS_HOME_STREET_NAME));
-    s.BindInt(4, profile.GetVerificationStatusInt(ADDRESS_HOME_STREET_NAME));
-    s.BindString16(5, profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_STREET_NAME));
-    s.BindInt(6, profile.GetVerificationStatusInt(
-                     ADDRESS_HOME_DEPENDENT_STREET_NAME));
-    s.BindString16(7, profile.GetRawInfo(ADDRESS_HOME_HOUSE_NUMBER));
-    s.BindInt(8, profile.GetVerificationStatusInt(ADDRESS_HOME_HOUSE_NUMBER));
-    s.BindString16(9, profile.GetRawInfo(ADDRESS_HOME_SUBPREMISE));
-    s.BindInt(10, profile.GetVerificationStatusInt(ADDRESS_HOME_SUBPREMISE));
-    s.BindString16(11, profile.GetRawInfo(ADDRESS_HOME_PREMISE_NAME));
-    s.BindInt(12, profile.GetVerificationStatusInt(ADDRESS_HOME_PREMISE_NAME));
-    s.BindString16(13, profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
-    s.BindInt(
-        14, profile.GetVerificationStatusInt(ADDRESS_HOME_DEPENDENT_LOCALITY));
-    s.BindString16(15, profile.GetRawInfo(ADDRESS_HOME_CITY));
-    s.BindInt(16, profile.GetVerificationStatusInt(ADDRESS_HOME_CITY));
-    s.BindString16(17, profile.GetRawInfo(ADDRESS_HOME_STATE));
-    s.BindInt(18, profile.GetVerificationStatusInt(ADDRESS_HOME_STATE));
-    s.BindString16(19, profile.GetRawInfo(ADDRESS_HOME_ZIP));
-    s.BindInt(20, profile.GetVerificationStatusInt(ADDRESS_HOME_ZIP));
-    s.BindString16(21, profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE));
-    s.BindInt(22, profile.GetVerificationStatusInt(ADDRESS_HOME_SORTING_CODE));
-    s.BindString16(23, profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
-    s.BindInt(24, profile.GetVerificationStatusInt(ADDRESS_HOME_COUNTRY));
-    s.BindString16(25, profile.GetRawInfo(ADDRESS_HOME_APT_NUM));
-    s.BindInt(26, profile.GetVerificationStatusInt(ADDRESS_HOME_APT_NUM));
-    s.BindString16(27, profile.GetRawInfo(ADDRESS_HOME_FLOOR));
-    s.BindInt(28, profile.GetVerificationStatusInt(ADDRESS_HOME_FLOOR));
-
+    int index = 1;
+    for (ServerFieldType type :
+         {ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_STREET_NAME,
+          ADDRESS_HOME_DEPENDENT_STREET_NAME, ADDRESS_HOME_HOUSE_NUMBER,
+          ADDRESS_HOME_SUBPREMISE, ADDRESS_HOME_PREMISE_NAME,
+          ADDRESS_HOME_DEPENDENT_LOCALITY, ADDRESS_HOME_CITY,
+          ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE,
+          ADDRESS_HOME_COUNTRY, ADDRESS_HOME_APT_NUM, ADDRESS_HOME_FLOOR}) {
+      s.BindString16(index++, profile.GetRawInfo(type));
+      s.BindInt(index++, profile.GetVerificationStatusInt(type));
+    }
     return s.Run();
   }
   return true;
@@ -315,27 +711,16 @@
 
 bool AddAutofillProfileNamesToProfile(sql::Database* db,
                                       AutofillProfile* profile) {
-  sql::Statement s(db->GetUniqueStatement(
-      "SELECT "
-      "guid, "
-      "honorific_prefix, honorific_prefix_status, "
-      "first_name, first_name_status, "
-      "middle_name, middle_name_status, "
-      "first_last_name, first_last_name_status, "
-      "conjunction_last_name, conjunction_last_name_status, "
-      "second_last_name, second_last_name_status, "
-      "last_name, last_name_status, "
-      "full_name, full_name_status, "
-      "full_name_with_honorific_prefix, full_name_with_honorific_prefix_status "
-      "FROM autofill_profile_names "
-      "WHERE guid=? "
-      "LIMIT 1"));
-  s.BindString(0, profile->guid());
-
-  if (!s.is_valid())
-    return false;
-
-  if (s.Step()) {
+  sql::Statement s;
+  if (SelectByGuid(
+          db, s, kAutofillProfileNamesTable,
+          {kGuid, kHonorificPrefix, kHonorificPrefixStatus, kFirstName,
+           kFirstNameStatus, kMiddleName, kMiddleNameStatus, kFirstLastName,
+           kFirstLastNameStatus, kConjunctionLastName,
+           kConjunctionLastNameStatus, kSecondLastName, kSecondLastNameStatus,
+           kLastName, kLastNameStatus, kFullName, kFullNameStatus,
+           kFullNameWithHonorificPrefix, kFullNameWithHonorificPrefixStatus},
+          profile->guid())) {
     DCHECK_EQ(profile->guid(), s.ColumnString(0));
 
     if (base::FeatureList::IsEnabled(
@@ -343,25 +728,15 @@
       // Whether or not the name has a legacy structure, set all
       // components. The Profile can detect that it must be migrated because
       // all values have the validation status |kNoStatus|.
-      profile->SetRawInfoWithVerificationStatusInt(
-          NAME_HONORIFIC_PREFIX, s.ColumnString16(1), s.ColumnInt(2));
-      profile->SetRawInfoWithVerificationStatusInt(
-          NAME_FIRST, s.ColumnString16(3), s.ColumnInt(4));
-      profile->SetRawInfoWithVerificationStatusInt(
-          NAME_MIDDLE, s.ColumnString16(5), s.ColumnInt(6));
-      profile->SetRawInfoWithVerificationStatusInt(
-          NAME_LAST_FIRST, s.ColumnString16(7), s.ColumnInt(8));
-      profile->SetRawInfoWithVerificationStatusInt(
-          NAME_LAST_CONJUNCTION, s.ColumnString16(9), s.ColumnInt(10));
-      profile->SetRawInfoWithVerificationStatusInt(
-          NAME_LAST_SECOND, s.ColumnString16(11), s.ColumnInt(12));
-      profile->SetRawInfoWithVerificationStatusInt(
-          NAME_LAST, s.ColumnString16(13), s.ColumnInt(14));
-      profile->SetRawInfoWithVerificationStatusInt(
-          NAME_FULL, s.ColumnString16(15), s.ColumnInt(16));
-      profile->SetRawInfoWithVerificationStatusInt(
-          NAME_FULL_WITH_HONORIFIC_PREFIX, s.ColumnString16(17),
-          s.ColumnInt(18));
+      int index = 1;
+      for (ServerFieldType type :
+           {NAME_HONORIFIC_PREFIX, NAME_FIRST, NAME_MIDDLE, NAME_LAST_FIRST,
+            NAME_LAST_CONJUNCTION, NAME_LAST_SECOND, NAME_LAST, NAME_FULL,
+            NAME_FULL_WITH_HONORIFIC_PREFIX}) {
+        profile->SetRawInfoWithVerificationStatusInt(
+            type, s.ColumnString16(index), s.ColumnInt(index + 1));
+        index += 2;
+      }
     } else {
       // If structured components are not enabled, only use the legacy
       // structure.
@@ -380,121 +755,102 @@
 
 bool AddAutofillProfileAddressesToProfile(sql::Database* db,
                                           AutofillProfile* profile) {
-  if (base::FeatureList::IsEnabled(
+  if (!base::FeatureList::IsEnabled(
           features::kAutofillEnableSupportForMoreStructureInAddresses)) {
-    sql::Statement s(db->GetUniqueStatement(
-        "SELECT "
-        "guid, "
-        "street_address, street_address_status, "
-        "street_name, street_name_status, "
-        "dependent_street_name, dependent_street_name_status, "
-        "house_number, house_number_status, "
-        "subpremise, subpremise_status, "
-        "premise_name, premise_name_status, "
-        "dependent_locality, dependent_locality_status, "
-        "city, city_status, "
-        "state, state_status, "
-        "zip_code, zip_code_status, "
-        "sorting_code, sorting_code_status, "
-        "country_code, country_code_status, "
-        "apartment_number, apartment_number_status, "
-        "floor, floor_status "
-        "FROM autofill_profile_addresses "
-        "WHERE guid=? "
-        "LIMIT 1"));
-    s.BindString(0, profile->guid());
-
-    if (!s.is_valid())
-      return false;
-
-    if (s.Step()) {
-      DCHECK_EQ(profile->guid(), s.ColumnString(0));
-      std::u16string street_address = s.ColumnString16(1);
-      std::u16string dependent_locality = s.ColumnString16(13);
-      std::u16string city = s.ColumnString16(15);
-      std::u16string state = s.ColumnString16(17);
-      std::u16string zip_code = s.ColumnString16(19);
-      std::u16string sorting_code = s.ColumnString16(21);
-      std::u16string country = s.ColumnString16(23);
-
-      std::u16string street_address_legacy =
-          profile->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS);
-      std::u16string dependent_locality_legacy =
-          profile->GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY);
-      std::u16string city_legacy = profile->GetRawInfo(ADDRESS_HOME_CITY);
-      std::u16string state_legacy = profile->GetRawInfo(ADDRESS_HOME_STATE);
-      std::u16string zip_code_legacy = profile->GetRawInfo(ADDRESS_HOME_ZIP);
-      std::u16string sorting_code_legacy =
-          profile->GetRawInfo(ADDRESS_HOME_SORTING_CODE);
-      std::u16string country_legacy = profile->GetRawInfo(ADDRESS_HOME_COUNTRY);
-
-      // At this stage, the unstructured address was already written to
-      // the profile. If the address was changed by a legacy client, the
-      // information diverged from the one in this table that is only written by
-      // new clients. In this case remove the corresponding row from this table.
-      // Otherwise, read the new structured tokens and set the verification
-      // statuses for all tokens.
-      if (street_address == street_address_legacy &&
-          dependent_locality == dependent_locality_legacy &&
-          city == city_legacy && state == state_legacy &&
-          zip_code == zip_code_legacy && sorting_code == sorting_code_legacy &&
-          country == country_legacy) {
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_STREET_ADDRESS, street_address, s.ColumnInt(2));
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_STREET_NAME, s.ColumnString16(3), s.ColumnInt(4));
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_DEPENDENT_STREET_NAME, s.ColumnString16(5),
-            s.ColumnInt(6));
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_HOUSE_NUMBER, s.ColumnString16(7), s.ColumnInt(8));
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_SUBPREMISE, s.ColumnString16(9), s.ColumnInt(10));
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_PREMISE_NAME, s.ColumnString16(11), s.ColumnInt(12));
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_DEPENDENT_LOCALITY, dependent_locality,
-            s.ColumnInt(14));
-        profile->SetRawInfoWithVerificationStatusInt(ADDRESS_HOME_CITY, city,
-                                                     s.ColumnInt(16));
-        profile->SetRawInfoWithVerificationStatusInt(ADDRESS_HOME_STATE, state,
-                                                     s.ColumnInt(18));
-        profile->SetRawInfoWithVerificationStatusInt(ADDRESS_HOME_ZIP, zip_code,
-                                                     s.ColumnInt(20));
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_SORTING_CODE, sorting_code, s.ColumnInt(22));
-        profile->SetRawInfoWithVerificationStatusInt(ADDRESS_HOME_COUNTRY,
-                                                     country, s.ColumnInt(24));
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_APT_NUM, s.ColumnString16(25), s.ColumnInt(26));
-        profile->SetRawInfoWithVerificationStatusInt(
-            ADDRESS_HOME_FLOOR, s.ColumnString16(27), s.ColumnInt(28));
-      } else {
-        // Remove the structured information from the table for
-        // eventual deletion consistency.
-        sql::Statement s1(db->GetUniqueStatement(
-            "DELETE FROM autofill_profile_addresses WHERE guid = ?"));
-        s1.BindString(0, profile->guid());
-        s1.Run();
-      }
-    }
-    return s.Succeeded();
+    return true;
   }
-  return true;
+  sql::Statement s;
+  if (SelectByGuid(db, s, kAutofillProfileAddressesTable,
+                   {kGuid,
+                    kStreetAddress,
+                    kStreetAddressStatus,
+                    kStreetName,
+                    kStreetNameStatus,
+                    kDependentStreetName,
+                    kDependentStreetNameStatus,
+                    kHouseNumber,
+                    kHouseNumberStatus,
+                    kSubpremise,
+                    kSubpremiseStatus,
+                    kPremiseName,
+                    kPremiseNameStatus,
+                    kDependentLocality,
+                    kDependentLocalityStatus,
+                    kCity,
+                    kCityStatus,
+                    kState,
+                    kStateStatus,
+                    kZipCode,
+                    kZipCodeStatus,
+                    kSortingCode,
+                    kSortingCodeStatus,
+                    kCountryCode,
+                    kCountryCodeStatus,
+                    kApartmentNumber,
+                    kApartmentNumberStatus,
+                    kFloor,
+                    kFloorStatus},
+                   profile->guid())) {
+    DCHECK_EQ(profile->guid(), s.ColumnString(0));
+    std::u16string street_address = s.ColumnString16(1);
+    std::u16string dependent_locality = s.ColumnString16(13);
+    std::u16string city = s.ColumnString16(15);
+    std::u16string state = s.ColumnString16(17);
+    std::u16string zip_code = s.ColumnString16(19);
+    std::u16string sorting_code = s.ColumnString16(21);
+    std::u16string country = s.ColumnString16(23);
+
+    std::u16string street_address_legacy =
+        profile->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS);
+    std::u16string dependent_locality_legacy =
+        profile->GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY);
+    std::u16string city_legacy = profile->GetRawInfo(ADDRESS_HOME_CITY);
+    std::u16string state_legacy = profile->GetRawInfo(ADDRESS_HOME_STATE);
+    std::u16string zip_code_legacy = profile->GetRawInfo(ADDRESS_HOME_ZIP);
+    std::u16string sorting_code_legacy =
+        profile->GetRawInfo(ADDRESS_HOME_SORTING_CODE);
+    std::u16string country_legacy = profile->GetRawInfo(ADDRESS_HOME_COUNTRY);
+
+    // At this stage, the unstructured address was already written to
+    // the profile. If the address was changed by a legacy client, the
+    // information diverged from the one in this table that is only written by
+    // new clients. In this case remove the corresponding row from this table.
+    // Otherwise, read the new structured tokens and set the verification
+    // statuses for all tokens.
+    if (street_address == street_address_legacy &&
+        dependent_locality == dependent_locality_legacy &&
+        city == city_legacy && state == state_legacy &&
+        zip_code == zip_code_legacy && sorting_code == sorting_code_legacy &&
+        country == country_legacy) {
+      int index = 1;
+      for (ServerFieldType type :
+           {ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_STREET_NAME,
+            ADDRESS_HOME_DEPENDENT_STREET_NAME, ADDRESS_HOME_HOUSE_NUMBER,
+            ADDRESS_HOME_SUBPREMISE, ADDRESS_HOME_PREMISE_NAME,
+            ADDRESS_HOME_DEPENDENT_LOCALITY, ADDRESS_HOME_CITY,
+            ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE,
+            ADDRESS_HOME_COUNTRY, ADDRESS_HOME_APT_NUM, ADDRESS_HOME_FLOOR}) {
+        profile->SetRawInfoWithVerificationStatusInt(
+            type, s.ColumnString16(index), s.ColumnInt(index + 1));
+        index += 2;
+      }
+    } else {
+      // Remove the structured information from the table for
+      // eventual deletion consistency.
+      DeleteWhereColumnEq(db, kAutofillProfileAddressesTable, kGuid,
+                          profile->guid());
+    }
+  }
+  return s.Succeeded();
 }
 
 bool AddAutofillProfileEmailsToProfile(sql::Database* db,
                                        AutofillProfile* profile) {
   // TODO(estade): update schema so that multiple emails are not associated
   // per unique profile guid. Please refer https://crbug.com/497934.
-  sql::Statement s(db->GetUniqueStatement(
-      "SELECT guid, email FROM autofill_profile_emails WHERE guid=? LIMIT 1"));
-  s.BindString(0, profile->guid());
-
-  if (!s.is_valid())
-    return false;
-
-  if (s.Step()) {
+  sql::Statement s;
+  if (SelectByGuid(db, s, kAutofillProfileEmailsTable, {kGuid, kEmail},
+                   profile->guid())) {
     DCHECK_EQ(profile->guid(), s.ColumnString(0));
     profile->SetRawInfo(EMAIL_ADDRESS, s.ColumnString16(1));
   }
@@ -506,14 +862,9 @@
   // TODO(estade): update schema so that multiple phone numbers are not
   // associated per unique profile guid. Please refer
   // https://crbug.com/497934.
-  sql::Statement s(db->GetUniqueStatement(
-      "SELECT guid, number FROM autofill_profile_phones WHERE guid=? LIMIT 1"));
-  s.BindString(0, profile->guid());
-
-  if (!s.is_valid())
-    return false;
-
-  if (s.Step()) {
+  sql::Statement s;
+  if (SelectByGuid(db, s, kAutofillProfilePhonesTable, {kGuid, kNumber},
+                   profile->guid())) {
     DCHECK_EQ(profile->guid(), s.ColumnString(0));
     profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(1));
   }
@@ -527,15 +878,9 @@
     return true;
   }
 
-  sql::Statement s(db->GetUniqueStatement(
-      "SELECT guid, day, month, year FROM autofill_profile_birthdates WHERE "
-      "guid=? LIMIT 1"));
-  s.BindString(0, profile->guid());
-
-  if (!s.is_valid())
-    return false;
-
-  if (s.Step()) {
+  sql::Statement s;
+  if (SelectByGuid(db, s, kAutofillProfileBirthdatesTable,
+                   {kGuid, kDay, kMonth, kYear}, profile->guid())) {
     DCHECK_EQ(profile->guid(), s.ColumnString(0));
     profile->SetRawInfoAsInt(BIRTHDATE_DAY, s.ColumnInt(1));
     profile->SetRawInfoAsInt(BIRTHDATE_MONTH, s.ColumnInt(2));
@@ -547,8 +892,8 @@
 bool AddAutofillProfileEmails(const AutofillProfile& profile,
                               sql::Database* db) {
   // Add the new email.
-  sql::Statement s(db->GetUniqueStatement(
-      "INSERT INTO autofill_profile_emails (guid, email) VALUES (?,?)"));
+  sql::Statement s;
+  InsertBuilder(db, s, kAutofillProfileEmailsTable, {kGuid, kEmail});
   s.BindString(0, profile.guid());
   s.BindString16(1, profile.GetRawInfo(EMAIL_ADDRESS));
 
@@ -558,8 +903,8 @@
 bool AddAutofillProfilePhones(const AutofillProfile& profile,
                               sql::Database* db) {
   // Add the new number.
-  sql::Statement s(db->GetUniqueStatement(
-      "INSERT INTO autofill_profile_phones (guid, number) VALUES (?,?)"));
+  sql::Statement s;
+  InsertBuilder(db, s, kAutofillProfilePhonesTable, {kGuid, kNumber});
   s.BindString(0, profile.guid());
   s.BindString16(1, profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
 
@@ -574,9 +919,9 @@
   }
 
   // Add the new birthdate.
-  sql::Statement s(
-      db->GetUniqueStatement("INSERT INTO autofill_profile_birthdates (guid, "
-                             "day, month, year) VALUES (?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db, s, kAutofillProfileBirthdatesTable,
+                {kGuid, kDay, kMonth, kYear});
   s.BindString(0, profile.guid());
   s.BindInt(1, profile.GetRawInfoAsInt(BIRTHDATE_DAY));
   s.BindInt(2, profile.GetRawInfoAsInt(BIRTHDATE_MONTH));
@@ -587,58 +932,19 @@
 
 bool AddAutofillProfilePieces(const AutofillProfile& profile,
                               sql::Database* db) {
-  if (!AddAutofillProfileNames(profile, db))
-    return false;
-
-  if (!AddAutofillProfileEmails(profile, db))
-    return false;
-
-  if (!AddAutofillProfilePhones(profile, db))
-    return false;
-
-  if (!AddAutofillProfileAddresses(profile, db))
-    return false;
-
-  if (!AddAutofillProfileBirthdate(profile, db))
-    return false;
-
-  return true;
+  return AddAutofillProfileNames(profile, db) &&
+         AddAutofillProfileEmails(profile, db) &&
+         AddAutofillProfilePhones(profile, db) &&
+         AddAutofillProfileAddresses(profile, db) &&
+         AddAutofillProfileBirthdate(profile, db);
 }
 
 bool RemoveAutofillProfilePieces(const std::string& guid, sql::Database* db) {
-  sql::Statement s1(db->GetUniqueStatement(
-      "DELETE FROM autofill_profile_names WHERE guid = ?"));
-  s1.BindString(0, guid);
-
-  if (!s1.Run())
-    return false;
-
-  sql::Statement s2(db->GetUniqueStatement(
-      "DELETE FROM autofill_profile_emails WHERE guid = ?"));
-  s2.BindString(0, guid);
-
-  if (!s2.Run())
-    return false;
-
-  sql::Statement s3(db->GetUniqueStatement(
-      "DELETE FROM autofill_profile_phones WHERE guid = ?"));
-  s3.BindString(0, guid);
-
-  if (!s3.Run())
-    return false;
-
-  sql::Statement s4(db->GetUniqueStatement(
-      "DELETE FROM autofill_profile_addresses WHERE guid = ?"));
-  s4.BindString(0, guid);
-
-  if (!s4.Run())
-    return false;
-
-  sql::Statement s5(db->GetUniqueStatement(
-      "DELETE FROM autofill_profile_birthdates WHERE guid = ?"));
-  s5.BindString(0, guid);
-
-  return s5.Run();
+  return DeleteWhereColumnEq(db, kAutofillProfileNamesTable, kGuid, guid) &&
+         DeleteWhereColumnEq(db, kAutofillProfileEmailsTable, kGuid, guid) &&
+         DeleteWhereColumnEq(db, kAutofillProfilePhonesTable, kGuid, guid) &&
+         DeleteWhereColumnEq(db, kAutofillProfileAddressesTable, kGuid, guid) &&
+         DeleteWhereColumnEq(db, kAutofillProfileBirthdatesTable, kGuid, guid);
 }
 
 WebDatabaseTable::TypeKey GetKey() {
@@ -699,16 +1005,16 @@
 }
 
 bool AutofillTable::CreateTablesIfNecessary() {
-  return (InitMainTable() && InitCreditCardsTable() && InitProfilesTable() &&
-          InitProfileAddressesTable() && InitProfileNamesTable() &&
-          InitProfileEmailsTable() && InitProfilePhonesTable() &&
-          InitProfileBirthdatesTable() && InitMaskedCreditCardsTable() &&
-          InitUnmaskedCreditCardsTable() && InitServerCardMetadataTable() &&
-          InitServerAddressesTable() && InitServerAddressMetadataTable() &&
-          InitAutofillSyncMetadataTable() && InitModelTypeStateTable() &&
-          InitPaymentsCustomerDataTable() && InitPaymentsUPIVPATable() &&
-          InitServerCreditCardCloudTokenDataTable() && InitOfferDataTable() &&
-          InitOfferEligibleInstrumentTable() && InitOfferMerchantDomainTable());
+  return InitMainTable() && InitCreditCardsTable() && InitProfilesTable() &&
+         InitProfileAddressesTable() && InitProfileNamesTable() &&
+         InitProfileEmailsTable() && InitProfilePhonesTable() &&
+         InitProfileBirthdatesTable() && InitMaskedCreditCardsTable() &&
+         InitUnmaskedCreditCardsTable() && InitServerCardMetadataTable() &&
+         InitServerAddressesTable() && InitServerAddressMetadataTable() &&
+         InitAutofillSyncMetadataTable() && InitModelTypeStateTable() &&
+         InitPaymentsCustomerDataTable() && InitPaymentsUPIVPATable() &&
+         InitServerCreditCardCloudTokenDataTable() && InitOfferDataTable() &&
+         InitOfferEligibleInstrumentTable() && InitOfferMerchantDomainTable();
 }
 
 bool AutofillTable::IsSyncable() {
@@ -869,10 +1175,9 @@
 
   if (prefix.empty()) {
     sql::Statement s;
-    s.Assign(db_->GetUniqueStatement(
-        "SELECT name, value, date_created, date_last_used FROM autofill "
-        "WHERE name = ? "
-        "ORDER BY count DESC LIMIT ?"));
+    SelectBuilder(db_, s, kAutofillTable,
+                  {kName, kValue, kDateCreated, kDateLastUsed},
+                  "WHERE name = ? ORDER BY count DESC LIMIT ?");
     s.BindString16(0, name);
     s.BindInt(1, limit);
 
@@ -892,13 +1197,13 @@
     next_prefix.back()++;
 
     sql::Statement s1;
-    s1.Assign(db_->GetUniqueStatement(
-        "SELECT name, value, date_created, date_last_used FROM autofill "
-        "WHERE name = ? AND "
-        "value_lower >= ? AND "
-        "value_lower < ? "
-        "ORDER BY count DESC "
-        "LIMIT ?"));
+    SelectBuilder(db_, s1, kAutofillTable,
+                  {kName, kValue, kDateCreated, kDateLastUsed},
+                  "WHERE name = ? AND "
+                  "value_lower >= ? AND "
+                  "value_lower < ? "
+                  "ORDER BY count DESC "
+                  "LIMIT ?");
     s1.BindString16(0, name);
     s1.BindString16(1, prefix_lower);
     s1.BindString16(2, next_prefix);
@@ -917,17 +1222,17 @@
 
     if (IsFeatureSubstringMatchEnabled()) {
       sql::Statement s2;
-      s2.Assign(db_->GetUniqueStatement(
-          "SELECT name, value, date_created, date_last_used FROM autofill "
-          "WHERE name = ? AND ("
-          " value LIKE '% ' || :prefix || '%' ESCAPE '!' OR "
-          " value LIKE '%.' || :prefix || '%' ESCAPE '!' OR "
-          " value LIKE '%,' || :prefix || '%' ESCAPE '!' OR "
-          " value LIKE '%-' || :prefix || '%' ESCAPE '!' OR "
-          " value LIKE '%@' || :prefix || '%' ESCAPE '!' OR "
-          " value LIKE '%!_' || :prefix || '%' ESCAPE '!' ) "
-          "ORDER BY count DESC "
-          "LIMIT ?"));
+      SelectBuilder(db_, s2, kAutofillTable,
+                    {kName, kValue, kDateCreated, kDateLastUsed},
+                    "WHERE name = ? AND ("
+                    " value LIKE '% ' || :prefix || '%' ESCAPE '!' OR "
+                    " value LIKE '%.' || :prefix || '%' ESCAPE '!' OR "
+                    " value LIKE '%,' || :prefix || '%' ESCAPE '!' OR "
+                    " value LIKE '%-' || :prefix || '%' ESCAPE '!' OR "
+                    " value LIKE '%@' || :prefix || '%' ESCAPE '!' OR "
+                    " value LIKE '%!_' || :prefix || '%' ESCAPE '!' ) "
+                    "ORDER BY count DESC "
+                    "LIMIT ?");
 
       s2.BindString16(0, name);
       // escaper as L'!' -> 0x21.
@@ -957,10 +1262,11 @@
 
   // Query for the name, value, count, and access dates of all form elements
   // that were used between the given times.
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT name, value, count, date_created, date_last_used FROM autofill "
-      "WHERE (date_created >= ? AND date_created < ?) OR "
-      "      (date_last_used >= ? AND date_last_used < ?)"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kAutofillTable,
+                {kName, kValue, kCount, kDateCreated, kDateLastUsed},
+                "WHERE (date_created >= ? AND date_created < ?) OR "
+                "      (date_last_used >= ? AND date_last_used < ?)");
   s.BindInt64(0, delete_begin_time_t);
   s.BindInt64(1, delete_end_time_t);
   s.BindInt64(2, delete_begin_time_t);
@@ -1024,8 +1330,9 @@
     return false;
 
   // As a single transaction, remove or update the elements appropriately.
-  sql::Statement s_delete(db_->GetUniqueStatement(
-      "DELETE FROM autofill WHERE date_created >= ? AND date_last_used < ?"));
+  sql::Statement s_delete;
+  DeleteBuilder(db_, s_delete, kAutofillTable,
+                "date_created >= ? AND date_last_used < ?");
   s_delete.BindInt64(0, delete_begin_time_t);
   s_delete.BindInt64(1, delete_end_time_t);
   sql::Transaction transaction(db_);
@@ -1061,8 +1368,9 @@
 
   // Query for the name and value of all form elements that were last used
   // before the |expiration_time|.
-  sql::Statement select_for_delete(db_->GetUniqueStatement(
-      "SELECT name, value FROM autofill WHERE date_last_used < ?"));
+  sql::Statement select_for_delete;
+  SelectBuilder(db_, select_for_delete, kAutofillTable, {kName, kValue},
+                "WHERE date_last_used < ?");
   select_for_delete.BindInt64(0, expiration_time.ToTimeT());
   std::vector<AutofillChange> tentative_changes;
   while (select_for_delete.Step()) {
@@ -1074,8 +1382,9 @@
   if (!select_for_delete.Succeeded())
     return false;
 
-  sql::Statement delete_data_statement(
-      db_->GetUniqueStatement("DELETE FROM autofill WHERE date_last_used < ?"));
+  sql::Statement delete_data_statement;
+  DeleteBuilder(db_, delete_data_statement, kAutofillTable,
+                "date_last_used < ?");
   delete_data_statement.BindInt64(0, expiration_time.ToTimeT());
   if (!delete_data_statement.Run())
     return false;
@@ -1086,8 +1395,8 @@
 
 bool AutofillTable::RemoveFormElement(const std::u16string& name,
                                       const std::u16string& value) {
-  sql::Statement s(db_->GetUniqueStatement(
-      "DELETE FROM autofill WHERE name = ? AND value= ?"));
+  sql::Statement s;
+  DeleteBuilder(db_, s, kAutofillTable, "name = ? AND value= ?");
   s.BindString16(0, name);
   s.BindString16(1, value);
   return s.Run();
@@ -1116,8 +1425,9 @@
 }
 
 bool AutofillTable::GetAllAutofillEntries(std::vector<AutofillEntry>* entries) {
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT name, value, date_created, date_last_used FROM autofill"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kAutofillTable,
+                {kName, kValue, kDateCreated, kDateLastUsed});
 
   while (s.Step()) {
     std::u16string name = s.ColumnString16(0);
@@ -1135,9 +1445,9 @@
                                           const std::u16string& value,
                                           base::Time* date_created,
                                           base::Time* date_last_used) {
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT date_created, date_last_used FROM autofill "
-      "WHERE name = ? AND value = ?"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kAutofillTable, {kDateCreated, kDateLastUsed},
+                "WHERE name = ? AND value = ?");
   s.BindString16(0, name);
   s.BindString16(1, value);
   if (!s.Step())
@@ -1157,8 +1467,8 @@
 
   // Remove all existing entries.
   for (const auto& entry : entries) {
-    sql::Statement s(db_->GetUniqueStatement(
-        "DELETE FROM autofill WHERE name = ? AND value = ?"));
+    sql::Statement s;
+    DeleteBuilder(db_, s, kAutofillTable, "name = ? AND value = ?");
     s.BindString16(0, entry.key().name());
     s.BindString16(1, entry.key().value());
     if (!s.Run())
@@ -1175,13 +1485,12 @@
 }
 
 bool AutofillTable::AddAutofillProfile(const AutofillProfile& profile) {
-  sql::Statement s(db_->GetUniqueStatement(
-      "INSERT INTO autofill_profiles"
-      "(guid, company_name, street_address, dependent_locality, city, state,"
-      " zipcode, sorting_code, country_code, use_count, use_date, "
-      " date_modified, origin, language_code, "
-      " label, disallow_settings_visible_updates) "
-      "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(
+      db_, s, kAutofillProfilesTable,
+      {kGuid, kCompanyName, kStreetAddress, kDependentLocality, kCity, kState,
+       kZipcode, kSortingCode, kCountryCode, kUseCount, kUseDate, kDateModified,
+       kOrigin, kLanguageCode, kLabel, kDisallowSettingsVisibleUpdates});
   BindAutofillProfileToStatement(profile, AutofillClock::Now(), &s);
 
   if (!s.Run())
@@ -1228,26 +1537,20 @@
 
 bool AutofillTable::RemoveAutofillProfile(const std::string& guid) {
   DCHECK(base::IsValidGUID(guid));
-  sql::Statement s(
-      db_->GetUniqueStatement("DELETE FROM autofill_profiles WHERE guid = ?"));
-  s.BindString(0, guid);
-
-  if (!s.Run())
-    return false;
-
-  return RemoveAutofillProfilePieces(guid, db_);
+  return DeleteWhereColumnEq(db_, kAutofillProfilesTable, kGuid, guid) &&
+         RemoveAutofillProfilePieces(guid, db_);
 }
 
 std::unique_ptr<AutofillProfile> AutofillTable::GetAutofillProfile(
     const std::string& guid) {
   DCHECK(base::IsValidGUID(guid));
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT guid, company_name, street_address, dependent_locality, city,"
-      " state, zipcode, sorting_code, country_code, use_count, use_date,"
-      " date_modified, origin, language_code, label,"
-      " disallow_settings_visible_updates "
-      "FROM autofill_profiles "
-      "WHERE guid=?"));
+  sql::Statement s;
+  SelectBuilder(
+      db_, s, kAutofillProfilesTable,
+      {kGuid, kCompanyName, kStreetAddress, kDependentLocality, kCity, kState,
+       kZipcode, kSortingCode, kCountryCode, kUseCount, kUseDate, kDateModified,
+       kOrigin, kLanguageCode, kLabel, kDisallowSettingsVisibleUpdates},
+      "WHERE guid=?");
   s.BindString(0, guid);
 
   if (!s.Step())
@@ -1290,8 +1593,9 @@
   DCHECK(profiles);
   profiles->clear();
 
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT guid FROM autofill_profiles ORDER BY date_modified DESC, guid"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kAutofillProfilesTable, {kGuid},
+                "ORDER BY date_modified DESC, guid");
 
   while (s.Step()) {
     std::string guid = s.ColumnString(0);
@@ -1308,26 +1612,20 @@
     std::vector<std::unique_ptr<AutofillProfile>>* profiles) const {
   profiles->clear();
 
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT "
-      "id,"
-      "use_count,"
-      "use_date,"
-      "recipient_name,"
-      "company_name,"
-      "street_address,"
-      "address_1,"     // ADDRESS_HOME_STATE
-      "address_2,"     // ADDRESS_HOME_CITY
-      "address_3,"     // ADDRESS_HOME_DEPENDENT_LOCALITY
-      "address_4,"     // Not supported in AutofillProfile yet.
-      "postal_code,"   // ADDRESS_HOME_ZIP
-      "sorting_code,"  // ADDRESS_HOME_SORTING_CODE
-      "country_code,"  // ADDRESS_HOME_COUNTRY
-      "phone_number,"  // PHONE_HOME_WHOLE_NUMBER
-      "language_code, "
-      "has_converted "
-      "FROM server_addresses addresses "
-      "LEFT OUTER JOIN server_address_metadata USING (id)"));
+  sql::Statement s;
+  SelectBuilder(
+      db_, s, kServerAddressesTable,
+      {kId, kUseCount, kUseDate, kRecipientName, kCompanyName, kStreetAddress,
+       kAddress1,     // ADDRESS_HOME_STATE
+       kAddress2,     // ADDRESS_HOME_CITY
+       kAddress3,     // ADDRESS_HOME_DEPENDENT_LOCALITY
+       kAddress4,     // Not supported in AutofillProfile yet.
+       kPostalCode,   // ADDRESS_HOME_ZIP
+       kSortingCode,  // ADDRESS_HOME_SORTING_CODE
+       kCountryCode,  // ADDRESS_HOME_COUNTRY
+       kPhoneNumber,  // PHONE_HOME_WHOLE_NUMBER
+       kLanguageCode, kHasConverted},
+      "LEFT OUTER JOIN server_address_metadata USING (id)");
 
   while (s.Step()) {
     int index = 0;
@@ -1342,16 +1640,16 @@
     profile->set_modification_date(base::Time());
 
     std::u16string recipient_name = s.ColumnString16(index++);
-    profile->SetRawInfo(COMPANY_NAME, s.ColumnString16(index++));
-    profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, s.ColumnString16(index++));
-    profile->SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(index++));
-    profile->SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(index++));
-    profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                        s.ColumnString16(index++));
+    for (ServerFieldType type :
+         {COMPANY_NAME, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_STATE,
+          ADDRESS_HOME_CITY, ADDRESS_HOME_DEPENDENT_LOCALITY}) {
+      profile->SetRawInfo(type, s.ColumnString16(index++));
+    }
     index++;  // Skip address_4 which we haven't added to AutofillProfile yet.
-    profile->SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(index++));
-    profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE, s.ColumnString16(index++));
-    profile->SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(index++));
+    for (ServerFieldType type :
+         {ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, ADDRESS_HOME_COUNTRY}) {
+      profile->SetRawInfo(type, s.ColumnString16(index++));
+    }
     std::u16string phone_number = s.ColumnString16(index++);
     profile->set_language_code(s.ColumnString(index++));
     profile->set_has_converted(s.ColumnBool(index++));
@@ -1372,76 +1670,76 @@
   return s.Succeeded();
 }
 
-void AutofillTable::SetServerProfiles(
-    const std::vector<AutofillProfile>& profiles) {
+void AutofillTable::SetServerProfilesAndMetadata(
+    const std::vector<AutofillProfile>& profiles,
+    bool update_metadata) {
   sql::Transaction transaction(db_);
   if (!transaction.Begin())
     return;
 
   // Delete all old ones first.
-  sql::Statement delete_old(
-      db_->GetUniqueStatement("DELETE FROM server_addresses"));
-  delete_old.Run();
+  Delete(db_, kServerAddressesTable);
 
-  sql::Statement insert(db_->GetUniqueStatement(
-      "INSERT INTO server_addresses("
-      "id,"
-      "recipient_name,"
-      "company_name,"
-      "street_address,"
-      "address_1,"     // ADDRESS_HOME_STATE
-      "address_2,"     // ADDRESS_HOME_CITY
-      "address_3,"     // ADDRESS_HOME_DEPENDENT_LOCALITY
-      "address_4,"     // Not supported in AutofillProfile yet.
-      "postal_code,"   // ADDRESS_HOME_ZIP
-      "sorting_code,"  // ADDRESS_HOME_SORTING_CODE
-      "country_code,"  // ADDRESS_HOME_COUNTRY
-      "phone_number,"  // PHONE_HOME_WHOLE_NUMBER
-      "language_code) "
-      "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+  sql::Statement insert;
+  InsertBuilder(db_, insert, kServerAddressesTable,
+                {kId, kRecipientName, kCompanyName, kStreetAddress,
+                 kAddress1,     // ADDRESS_HOME_STATE
+                 kAddress2,     // ADDRESS_HOME_CITY
+                 kAddress3,     // ADDRESS_HOME_DEPENDENT_LOCALITY
+                 kAddress4,     // Not supported in AutofillProfile yet.
+                 kPostalCode,   // ADDRESS_HOME_ZIP
+                 kSortingCode,  // ADDRESS_HOME_SORTING_CODE
+                 kCountryCode,  // ADDRESS_HOME_COUNTRY
+                 kPhoneNumber,  // PHONE_HOME_WHOLE_NUMBER
+                 kLanguageCode});
   for (const auto& profile : profiles) {
     DCHECK(profile.record_type() == AutofillProfile::SERVER_PROFILE);
 
     int index = 0;
     insert.BindString(index++, profile.server_id());
-    insert.BindString16(index++, profile.GetRawInfo(NAME_FULL));
-    insert.BindString16(index++, profile.GetRawInfo(COMPANY_NAME));
-    insert.BindString16(index++,
-                        profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_STATE));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_CITY));
-    insert.BindString16(index++,
-                        profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
-    index++;  // SKip address_4 which we haven't added to AutofillProfile yet.
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_ZIP));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
-    insert.BindString16(index++, profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
+    for (ServerFieldType type :
+         {NAME_FULL, COMPANY_NAME, ADDRESS_HOME_STREET_ADDRESS,
+          ADDRESS_HOME_STATE, ADDRESS_HOME_CITY,
+          ADDRESS_HOME_DEPENDENT_LOCALITY}) {
+      insert.BindString16(index++, profile.GetRawInfo(type));
+    }
+    index++;  // Skip address_4 which we haven't added to AutofillProfile yet.
+    for (ServerFieldType type :
+         {ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, ADDRESS_HOME_COUNTRY,
+          PHONE_HOME_WHOLE_NUMBER}) {
+      insert.BindString16(index++, profile.GetRawInfo(type));
+    }
     insert.BindString(index++, profile.language_code());
 
     insert.Run();
     insert.Reset(true);
 
-    // Save the use count and use date of the profile.
-    UpdateServerAddressMetadata(profile);
+    if (update_metadata) {
+      // Save the use count and use date of the profile.
+      UpdateServerAddressMetadata(profile);
+    }
   }
 
-  // Delete metadata that's no longer relevant.
-  sql::Statement metadata_delete(db_->GetUniqueStatement(
-      "DELETE FROM server_address_metadata WHERE id NOT IN "
-      "(SELECT id FROM server_addresses)"));
-  metadata_delete.Run();
+  if (update_metadata) {
+    // Delete metadata that's no longer relevant.
+    Delete(db_, kServerAddressMetadataTable,
+           "id NOT IN (SELECT id FROM server_addresses)");
+  }
 
   transaction.Commit();
 }
 
+void AutofillTable::SetServerProfiles(
+    const std::vector<AutofillProfile>& profiles) {
+  SetServerProfilesAndMetadata(profiles, /*update_metadata=*/true);
+}
+
 bool AutofillTable::AddCreditCard(const CreditCard& credit_card) {
-  sql::Statement s(db_->GetUniqueStatement(
-      "INSERT INTO credit_cards"
-      "(guid, name_on_card, expiration_month, expiration_year, "
-      " card_number_encrypted, use_count, use_date, date_modified, origin,"
-      " billing_address_id, nickname)"
-      "VALUES (?,?,?,?,?,?,?,?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kCreditCardsTable,
+                {kGuid, kNameOnCard, kExpirationMonth, kExpirationYear,
+                 kCardNumberEncrypted, kUseCount, kUseDate, kDateModified,
+                 kOrigin, kBillingAddressId, kNickname});
   BindCreditCardToStatement(credit_card, AutofillClock::Now(), &s,
                             *autofill_table_encryptor_);
 
@@ -1481,11 +1779,7 @@
 
 bool AutofillTable::RemoveCreditCard(const std::string& guid) {
   DCHECK(base::IsValidGUID(guid));
-  sql::Statement s(
-      db_->GetUniqueStatement("DELETE FROM credit_cards WHERE guid = ?"));
-  s.BindString(0, guid);
-
-  return s.Run();
+  return DeleteWhereColumnEq(db_, kCreditCardsTable, kGuid, guid);
 }
 
 bool AutofillTable::AddFullServerCreditCard(const CreditCard& credit_card) {
@@ -1518,12 +1812,12 @@
 std::unique_ptr<CreditCard> AutofillTable::GetCreditCard(
     const std::string& guid) {
   DCHECK(base::IsValidGUID(guid));
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT guid, name_on_card, expiration_month, expiration_year, "
-      "card_number_encrypted, use_count, use_date, date_modified, "
-      "origin, billing_address_id, nickname "
-      "FROM credit_cards "
-      "WHERE guid = ?"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kCreditCardsTable,
+                {kGuid, kNameOnCard, kExpirationMonth, kExpirationYear,
+                 kCardNumberEncrypted, kUseCount, kUseDate, kDateModified,
+                 kOrigin, kBillingAddressId, kNickname},
+                "WHERE guid = ?");
   s.BindString(0, guid);
 
   if (!s.Step())
@@ -1537,8 +1831,9 @@
   DCHECK(credit_cards);
   credit_cards->clear();
 
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT guid FROM credit_cards ORDER BY date_modified DESC, guid"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kCreditCardsTable, {kGuid},
+                "ORDER BY date_modified DESC, guid");
 
   while (s.Step()) {
     std::string guid = s.ColumnString(0);
@@ -1555,28 +1850,17 @@
     std::vector<std::unique_ptr<CreditCard>>* credit_cards) const {
   credit_cards->clear();
 
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT "
-      "card_number_encrypted, "          // 0
-      "last_four,"                       // 1
-      "masked.id,"                       // 2
-      "metadata.use_count,"              // 3
-      "metadata.use_date,"               // 4
-      "network,"                         // 5
-      "name_on_card,"                    // 6
-      "exp_month,"                       // 7
-      "exp_year,"                        // 8
-      "metadata.billing_address_id,"     // 9
-      "bank_name,"                       // 10
-      "nickname,"                        // 11
-      "card_issuer,"                     // 12
-      "instrument_id, "                  // 13
-      "virtual_card_enrollment_state, "  // 14
-      "card_art_url, "                   // 15
-      "product_description "             // 16
-      "FROM masked_credit_cards masked "
+  sql::Statement s;
+  SelectBuilder(
+      db_, s, base::StrCat({kMaskedCreditCardsTable, " AS masked"}),
+      {kCardNumberEncrypted, kLastFour, base::StrCat({"masked.", kId}),
+       base::StrCat({"metadata.", kUseCount}),
+       base::StrCat({"metadata.", kUseDate}), kNetwork, kNameOnCard, kExpMonth,
+       kExpYear, base::StrCat({"metadata.", kBillingAddressId}), kBankName,
+       kNickname, kCardIssuer, kInstrumentId, kVirtualCardEnrollmentState,
+       kCardArtUrl, kProductDescription},
       "LEFT OUTER JOIN unmasked_credit_cards USING (id) "
-      "LEFT OUTER JOIN server_card_metadata metadata USING (id)"));
+      "LEFT OUTER JOIN server_card_metadata AS metadata USING (id)");
   while (s.Step()) {
     int index = 0;
 
@@ -1636,22 +1920,16 @@
     return;
 
   // Delete all old values.
-  sql::Statement masked_delete(
-      db_->GetUniqueStatement("DELETE FROM masked_credit_cards"));
-  masked_delete.Run();
+  Delete(db_, kMaskedCreditCardsTable);
 
   AddMaskedCreditCards(credit_cards);
 
   // Delete all items in the unmasked table that aren't in the new set.
-  sql::Statement unmasked_delete(db_->GetUniqueStatement(
-      "DELETE FROM unmasked_credit_cards WHERE id NOT IN "
-      "(SELECT id FROM masked_credit_cards)"));
-  unmasked_delete.Run();
+  Delete(db_, kUnmaskedCreditCardsTable,
+         "id NOT IN (SELECT id FROM masked_credit_cards)");
   // Do the same for metadata.
-  sql::Statement metadata_delete(db_->GetUniqueStatement(
-      "DELETE FROM server_card_metadata WHERE id NOT IN "
-      "(SELECT id FROM masked_credit_cards)"));
-  metadata_delete.Run();
+  Delete(db_, kServerCardMetadataTable,
+         "id NOT IN (SELECT id FROM masked_credit_cards)");
 
   transaction.Commit();
 }
@@ -1684,10 +1962,9 @@
 
 bool AutofillTable::AddServerCardMetadata(
     const AutofillMetadata& card_metadata) {
-  sql::Statement s(
-      db_->GetUniqueStatement("INSERT INTO server_card_metadata(use_count, "
-                              "use_date, billing_address_id, id)"
-                              "VALUES (?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kServerCardMetadataTable,
+                {kUseCount, kUseDate, kBillingAddressId, kId});
   s.BindInt64(0, card_metadata.use_count);
   s.BindInt64(1, card_metadata.use_date.ToInternalValue());
   s.BindString(2, card_metadata.billing_address_id);
@@ -1700,15 +1977,12 @@
 bool AutofillTable::UpdateServerCardMetadata(const CreditCard& credit_card) {
   DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type());
 
-  sql::Statement remove(
-      db_->GetUniqueStatement("DELETE FROM server_card_metadata WHERE id = ?"));
-  remove.BindString(0, credit_card.server_id());
-  remove.Run();
+  DeleteWhereColumnEq(db_, kServerCardMetadataTable, kId,
+                      credit_card.server_id());
 
-  sql::Statement s(
-      db_->GetUniqueStatement("INSERT INTO server_card_metadata(use_count, "
-                              "use_date, billing_address_id, id)"
-                              "VALUES (?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kServerCardMetadataTable,
+                {kUseCount, kUseDate, kBillingAddressId, kId});
   s.BindInt64(0, credit_card.use_count());
   s.BindInt64(1, credit_card.use_date().ToInternalValue());
   s.BindString(2, credit_card.billing_address_id());
@@ -1723,10 +1997,9 @@
   // Do not check if there was a record that got deleted. Inserting a new one is
   // also fine.
   RemoveServerCardMetadata(card_metadata.id);
-  sql::Statement s(
-      db_->GetUniqueStatement("INSERT INTO server_card_metadata(use_count, "
-                              "use_date, billing_address_id, id)"
-                              "VALUES (?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kServerCardMetadataTable,
+                {kUseCount, kUseDate, kBillingAddressId, kId});
   s.BindInt64(0, card_metadata.use_count);
   s.BindInt64(1, card_metadata.use_date.ToInternalValue());
   s.BindString(2, card_metadata.billing_address_id);
@@ -1737,11 +2010,7 @@
 }
 
 bool AutofillTable::RemoveServerCardMetadata(const std::string& id) {
-  sql::Statement remove(
-      db_->GetUniqueStatement("DELETE FROM server_card_metadata WHERE id = ?"));
-  remove.BindString(0, id);
-  remove.Run();
-
+  DeleteWhereColumnEq(db_, kServerCardMetadataTable, kId, id);
   return db_->GetLastChangeCount() > 0;
 }
 
@@ -1749,9 +2018,9 @@
     std::map<std::string, AutofillMetadata>* cards_metadata) const {
   cards_metadata->clear();
 
-  sql::Statement s(
-      db_->GetUniqueStatement("SELECT id, use_count, use_date, "
-                              "billing_address_id FROM server_card_metadata"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kServerCardMetadataTable,
+                {kId, kUseCount, kUseDate, kBillingAddressId});
 
   while (s.Step()) {
     int index = 0;
@@ -1769,10 +2038,9 @@
 
 bool AutofillTable::AddServerAddressMetadata(
     const AutofillMetadata& address_metadata) {
-  sql::Statement s(
-      db_->GetUniqueStatement("INSERT INTO server_address_metadata(use_count, "
-                              "use_date, has_converted, id)"
-                              "VALUES (?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kServerAddressMetadataTable,
+                {kUseCount, kUseDate, kHasConverted, kId});
   s.BindInt64(0, address_metadata.use_count);
   s.BindInt64(1, address_metadata.use_date.ToInternalValue());
   s.BindBool(2, address_metadata.has_converted);
@@ -1792,15 +2060,13 @@
   if (!transaction.Begin())
     return false;
 
-  sql::Statement remove(db_->GetUniqueStatement(
-      "DELETE FROM server_address_metadata WHERE id = ?"));
-  remove.BindString(0, profile.server_id());
-  remove.Run();
+  DeleteWhereColumnEq(db_, kServerAddressMetadataTable, kId,
+                      profile.server_id());
 
-  sql::Statement s(
-      db_->GetUniqueStatement("INSERT INTO server_address_metadata(use_count, "
-                              "use_date, has_converted, id)"
-                              "VALUES (?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kServerAddressMetadataTable,
+                {kUseCount, kUseDate, kHasConverted, kId});
+
   s.BindInt64(0, profile.use_count());
   s.BindInt64(1, profile.use_date().ToInternalValue());
   s.BindBool(2, profile.has_converted());
@@ -1817,10 +2083,9 @@
   // Do not check if there was a record that got deleted. Inserting a new one is
   // also fine.
   RemoveServerAddressMetadata(address_metadata.id);
-  sql::Statement s(
-      db_->GetUniqueStatement("INSERT INTO server_address_metadata(use_count, "
-                              "use_date, has_converted, id)"
-                              "VALUES (?,?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kServerAddressMetadataTable,
+                {kUseCount, kUseDate, kHasConverted, kId});
   s.BindInt64(0, address_metadata.use_count);
   s.BindInt64(1, address_metadata.use_date.ToInternalValue());
   s.BindBool(2, address_metadata.has_converted);
@@ -1831,11 +2096,7 @@
 }
 
 bool AutofillTable::RemoveServerAddressMetadata(const std::string& id) {
-  sql::Statement remove(db_->GetUniqueStatement(
-      "DELETE FROM server_address_metadata WHERE id = ?"));
-  remove.BindString(0, id);
-  remove.Run();
-
+  DeleteWhereColumnEq(db_, kServerAddressMetadataTable, kId, id);
   return db_->GetLastChangeCount() > 0;
 }
 
@@ -1843,9 +2104,9 @@
     std::map<std::string, AutofillMetadata>* addresses_metadata) const {
   addresses_metadata->clear();
 
-  sql::Statement s(
-      db_->GetUniqueStatement("SELECT id, use_count, use_date, has_converted "
-                              "FROM server_address_metadata"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kServerAddressMetadataTable,
+                {kId, kUseCount, kUseDate, kHasConverted});
   while (s.Step()) {
     int index = 0;
 
@@ -1867,27 +2128,16 @@
     return;
 
   // Delete all old values.
-  sql::Statement masked_delete(
-      db_->GetUniqueStatement("DELETE FROM masked_credit_cards"));
-  masked_delete.Run();
+  Delete(db_, kMaskedCreditCardsTable);
 
   // Add all the masked cards.
-  sql::Statement masked_insert(
-      db_->GetUniqueStatement("INSERT INTO masked_credit_cards("
-                              "id,"                             // 0
-                              "network,"                        // 1
-                              "name_on_card,"                   // 2
-                              "last_four,"                      // 3
-                              "exp_month,"                      // 4
-                              "exp_year,"                       // 5
-                              "bank_name,"                      // 6
-                              "nickname,"                       // 7
-                              "card_issuer,"                    // 8
-                              "instrument_id,"                  // 9
-                              "virtual_card_enrollment_state,"  // 10
-                              "card_art_url,"                   // 11
-                              "product_description) "           // 12
-                              "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+  sql::Statement masked_insert;
+  InsertBuilder(
+      db_, masked_insert, kMaskedCreditCardsTable,
+      {kId, kNetwork, kNameOnCard, kLastFour, kExpMonth, kExpYear, kBankName,
+       kNickname, kCardIssuer, kInstrumentId, kVirtualCardEnrollmentState,
+       kCardArtUrl, kProductDescription});
+
   int index;
   for (const CreditCard& card : credit_cards) {
     DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type());
@@ -1912,67 +2162,15 @@
   }
 
   // Delete all items in the unmasked table that aren't in the new set.
-  sql::Statement unmasked_delete(db_->GetUniqueStatement(
-      "DELETE FROM unmasked_credit_cards WHERE id NOT IN "
-      "(SELECT id FROM masked_credit_cards)"));
-  unmasked_delete.Run();
+  Delete(db_, kUnmaskedCreditCardsTable,
+         "id NOT IN (SELECT id FROM masked_credit_cards)");
 
   transaction.Commit();
 }
 
 void AutofillTable::SetServerAddressesData(
     const std::vector<AutofillProfile>& profiles) {
-  sql::Transaction transaction(db_);
-  if (!transaction.Begin())
-    return;
-
-  // Delete existing server addresses.
-  sql::Statement delete_old(
-      db_->GetUniqueStatement("DELETE FROM server_addresses"));
-  delete_old.Run();
-
-  // Add the new server addresses.
-  sql::Statement insert(db_->GetUniqueStatement(
-      "INSERT INTO server_addresses("
-      "id,"
-      "recipient_name,"
-      "company_name,"
-      "street_address,"
-      "address_1,"     // ADDRESS_HOME_STATE
-      "address_2,"     // ADDRESS_HOME_CITY
-      "address_3,"     // ADDRESS_HOME_DEPENDENT_LOCALITY
-      "address_4,"     // Not supported in AutofillProfile yet.
-      "postal_code,"   // ADDRESS_HOME_ZIP
-      "sorting_code,"  // ADDRESS_HOME_SORTING_CODE
-      "country_code,"  // ADDRESS_HOME_COUNTRY
-      "phone_number,"  // PHONE_HOME_WHOLE_NUMBER
-      "language_code) "
-      "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
-  for (const auto& profile : profiles) {
-    DCHECK(profile.record_type() == AutofillProfile::SERVER_PROFILE);
-
-    int index = 0;
-    insert.BindString(index++, profile.server_id());
-    insert.BindString16(index++, profile.GetRawInfo(NAME_FULL));
-    insert.BindString16(index++, profile.GetRawInfo(COMPANY_NAME));
-    insert.BindString16(index++,
-                        profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_STATE));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_CITY));
-    insert.BindString16(index++,
-                        profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
-    index++;  // SKip address_4 which we haven't added to AutofillProfile yet.
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_ZIP));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
-    insert.BindString16(index++, profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
-    insert.BindString(index++, profile.language_code());
-
-    insert.Run();
-    insert.Reset(true);
-  }
-
-  transaction.Commit();
+  SetServerProfilesAndMetadata(profiles, /*update_metadata=*/false);
 }
 
 void AutofillTable::SetCreditCardCloudTokenData(
@@ -1982,20 +2180,13 @@
     return;
 
   // Deletes all old values.
-  sql::Statement delete_cloud_token(
-      db_->GetUniqueStatement("DELETE FROM server_card_cloud_token_data"));
-  delete_cloud_token.Run();
+  Delete(db_, kServerCardCloudTokenDataTable);
 
   // Inserts new values.
-  sql::Statement insert_cloud_token(
-      db_->GetUniqueStatement("INSERT INTO server_card_cloud_token_data("
-                              "id,"                 // 0
-                              "suffix,"             // 1
-                              "exp_month,"          // 2
-                              "exp_year,"           // 3
-                              "card_art_url,"       // 4
-                              "instrument_token) "  // 5
-                              "VALUES (?,?,?,?,?,?)"));
+  sql::Statement insert_cloud_token;
+  InsertBuilder(
+      db_, insert_cloud_token, kServerCardCloudTokenDataTable,
+      {kId, kSuffix, kExpMonth, kExpYear, kCardArtUrl, kInstrumentToken});
 
   for (const CreditCardCloudTokenData& data : credit_card_cloud_token_data) {
     insert_cloud_token.BindString(0, data.masked_card_id);
@@ -2015,15 +2206,10 @@
         credit_card_cloud_token_data) {
   credit_card_cloud_token_data->clear();
 
-  sql::Statement s(
-      db_->GetUniqueStatement("SELECT "
-                              "id, "               // 0
-                              "suffix, "           // 1
-                              "exp_month, "        // 2
-                              "exp_year, "         // 3
-                              "card_art_url, "     // 4
-                              "instrument_token "  // 5
-                              "FROM server_card_cloud_token_data"));
+  sql::Statement s;
+  SelectBuilder(
+      db_, s, kServerCardCloudTokenDataTable,
+      {kId, kSuffix, kExpMonth, kExpYear, kCardArtUrl, kInstrumentToken});
 
   while (s.Step()) {
     int index = 0;
@@ -2048,13 +2234,12 @@
     return;
 
   // Delete all old values.
-  sql::Statement customer_data_delete(
-      db_->GetUniqueStatement("DELETE FROM payments_customer_data"));
-  customer_data_delete.Run();
+  Delete(db_, kPaymentsCustomerDataTable);
 
   if (customer_data) {
-    sql::Statement insert_customer_data(db_->GetUniqueStatement(
-        "INSERT INTO payments_customer_data (customer_id) VALUES (?)"));
+    sql::Statement insert_customer_data;
+    InsertBuilder(db_, insert_customer_data, kPaymentsCustomerDataTable,
+                  {kCustomerId});
     insert_customer_data.BindString(0, customer_data->customer_id);
     insert_customer_data.Run();
   }
@@ -2064,8 +2249,8 @@
 
 bool AutofillTable::GetPaymentsCustomerData(
     std::unique_ptr<PaymentsCustomerData>* customer_data) const {
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT customer_id FROM payments_customer_data"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kPaymentsCustomerDataTable, {kCustomerId});
   if (s.Step()) {
     *customer_data = std::make_unique<PaymentsCustomerData>(
         /*customer_id=*/s.ColumnString(0));
@@ -2081,28 +2266,16 @@
     return;
 
   // Delete all old values.
-  sql::Statement delete_offers(
-      db_->GetUniqueStatement("DELETE FROM offer_data"));
-  sql::Statement delete_offer_eligible_instruments(
-      db_->GetUniqueStatement("DELETE FROM offer_eligible_instrument"));
-  sql::Statement delete_offer_merchant_domains(
-      db_->GetUniqueStatement("DELETE FROM offer_merchant_domain"));
-  delete_offers.Run();
-  delete_offer_eligible_instruments.Run();
-  delete_offer_merchant_domains.Run();
+  Delete(db_, kOfferDataTable);
+  Delete(db_, kOfferEligibleInstrumentTable);
+  Delete(db_, kOfferMerchantDomainTable);
 
   // Insert new values.
-  sql::Statement insert_offers(
-      db_->GetUniqueStatement("INSERT INTO offer_data("
-                              "offer_id, "                 // 0
-                              "offer_reward_amount, "      // 1
-                              "expiry, "                   // 2
-                              "offer_details_url, "        // 3
-                              "promo_code, "               // 4
-                              "value_prop_text, "          // 5
-                              "see_details_text, "         // 6
-                              "usage_instructions_text) "  // 7
-                              "VALUES (?,?,?,?,?,?,?,?)"));
+  sql::Statement insert_offers;
+  InsertBuilder(
+      db_, insert_offers, kOfferDataTable,
+      {kOfferId, kOfferRewardAmount, kExpiry, kOfferDetailsUrl, kPromoCode,
+       kValuePropText, kSeeDetailsText, kUsageInstructionsText});
 
   for (const AutofillOfferData& data : autofill_offer_data) {
     insert_offers.BindInt64(0, data.GetOfferId());
@@ -2120,28 +2293,22 @@
 
     for (const int64_t instrument_id : data.GetEligibleInstrumentIds()) {
       // Insert new offer_eligible_instrument values.
-      sql::Statement insert_offer_eligible_instruments(
-          db_->GetUniqueStatement("INSERT INTO offer_eligible_instrument("
-                                  "offer_id, "       // 0
-                                  "instrument_id) "  // 1
-                                  "VALUES (?,?)"));
+      sql::Statement insert_offer_eligible_instruments;
+      InsertBuilder(db_, insert_offer_eligible_instruments,
+                    kOfferEligibleInstrumentTable, {kOfferId, kInstrumentId});
       insert_offer_eligible_instruments.BindInt64(0, data.GetOfferId());
       insert_offer_eligible_instruments.BindInt64(1, instrument_id);
       insert_offer_eligible_instruments.Run();
-      insert_offer_eligible_instruments.Reset(true);
     }
 
     for (const GURL& merchant_origin : data.GetMerchantOrigins()) {
       // Insert new offer_merchant_domain values.
-      sql::Statement insert_offer_merchant_domains(
-          db_->GetUniqueStatement("INSERT INTO offer_merchant_domain("
-                                  "offer_id, "         // 0
-                                  "merchant_domain) "  // 1
-                                  "VALUES (?,?)"));
+      sql::Statement insert_offer_merchant_domains;
+      InsertBuilder(db_, insert_offer_merchant_domains,
+                    kOfferMerchantDomainTable, {kOfferId, kMerchantDomain});
       insert_offer_merchant_domains.BindInt64(0, data.GetOfferId());
       insert_offer_merchant_domains.BindString(1, merchant_origin.spec());
       insert_offer_merchant_domains.Run();
-      insert_offer_merchant_domains.Reset(true);
     }
   }
   transaction.Commit();
@@ -2151,17 +2318,11 @@
     std::vector<std::unique_ptr<AutofillOfferData>>* autofill_offer_data) {
   autofill_offer_data->clear();
 
-  sql::Statement s(
-      db_->GetUniqueStatement("SELECT "
-                              "offer_id, "                // 0
-                              "offer_reward_amount, "     // 1
-                              "expiry, "                  // 2
-                              "offer_details_url, "       // 3
-                              "promo_code, "              // 4
-                              "value_prop_text, "         // 5
-                              "see_details_text, "        // 6
-                              "usage_instructions_text "  // 7
-                              "FROM offer_data"));
+  sql::Statement s;
+  SelectBuilder(
+      db_, s, kOfferDataTable,
+      {kOfferId, kOfferRewardAmount, kExpiry, kOfferDetailsUrl, kPromoCode,
+       kValuePropText, kSeeDetailsText, kUsageInstructionsText});
 
   while (s.Step()) {
     int index = 0;
@@ -2179,12 +2340,10 @@
     std::vector<int64_t> eligible_instrument_id;
     std::vector<GURL> merchant_origins;
 
-    sql::Statement s_offer_eligible_instrument(
-        db_->GetUniqueStatement("SELECT "
-                                "offer_id, "      // 0
-                                "instrument_id "  // 1
-                                "FROM offer_eligible_instrument "
-                                "WHERE offer_id = ?"));
+    sql::Statement s_offer_eligible_instrument;
+    SelectBuilder(db_, s_offer_eligible_instrument,
+                  kOfferEligibleInstrumentTable, {kOfferId, kInstrumentId},
+                  "WHERE offer_id = ?");
     s_offer_eligible_instrument.BindInt64(0, offer_id);
     while (s_offer_eligible_instrument.Step()) {
       const int64_t instrument_id = s_offer_eligible_instrument.ColumnInt64(1);
@@ -2193,12 +2352,9 @@
       }
     }
 
-    sql::Statement s_offer_merchant_domain(
-        db_->GetUniqueStatement("SELECT "
-                                "offer_id, "        // 0
-                                "merchant_domain "  // 1
-                                "FROM offer_merchant_domain "
-                                "WHERE offer_id = ?"));
+    sql::Statement s_offer_merchant_domain;
+    SelectBuilder(db_, s_offer_merchant_domain, kOfferMerchantDomainTable,
+                  {kOfferId, kMerchantDomain}, "WHERE offer_id = ?");
     s_offer_merchant_domain.BindInt64(0, offer_id);
     while (s_offer_merchant_domain.Step()) {
       const std::string merchant_domain =
@@ -2230,8 +2386,8 @@
   if (!transaction.Begin())
     return false;
 
-  sql::Statement insert_upi_id_statement(
-      db_->GetUniqueStatement("INSERT INTO payments_upi_vpa (vpa) VALUES (?)"));
+  sql::Statement insert_upi_id_statement;
+  InsertBuilder(db_, insert_upi_id_statement, kPaymentsUpiVpaTable, {kVpa});
   insert_upi_id_statement.BindString(0, upi_id);
   insert_upi_id_statement.Run();
 
@@ -2241,8 +2397,8 @@
 }
 
 std::vector<std::string> AutofillTable::GetAllUpiIds() {
-  sql::Statement select_upi_id_statement(
-      db_->GetUniqueStatement("SELECT vpa FROM payments_upi_vpa"));
+  sql::Statement select_upi_id_statement;
+  SelectBuilder(db_, select_upi_id_statement, kPaymentsUpiVpaTable, {kVpa});
 
   std::vector<std::string> upi_ids;
   while (select_upi_id_statement.Step()) {
@@ -2256,55 +2412,16 @@
   if (!transaction.Begin())
     return false;  // Some error, nothing was changed.
 
-  sql::Statement masked(
-      db_->GetUniqueStatement("DELETE FROM masked_credit_cards"));
-  masked.Run();
-  bool changed = db_->GetLastChangeCount() > 0;
-
-  sql::Statement unmasked(
-      db_->GetUniqueStatement("DELETE FROM unmasked_credit_cards"));
-  unmasked.Run();
-  changed |= db_->GetLastChangeCount() > 0;
-
-  sql::Statement addresses(
-      db_->GetUniqueStatement("DELETE FROM server_addresses"));
-  addresses.Run();
-  changed |= db_->GetLastChangeCount() > 0;
-
-  sql::Statement card_metadata(
-      db_->GetUniqueStatement("DELETE FROM server_card_metadata"));
-  card_metadata.Run();
-  changed |= db_->GetLastChangeCount() > 0;
-
-  sql::Statement address_metadata(
-      db_->GetUniqueStatement("DELETE FROM server_address_metadata"));
-  address_metadata.Run();
-  changed |= db_->GetLastChangeCount() > 0;
-
-  sql::Statement customer_data(
-      db_->GetUniqueStatement("DELETE FROM payments_customer_data"));
-  customer_data.Run();
-  changed |= db_->GetLastChangeCount() > 0;
-
-  sql::Statement cloud_token_data(
-      db_->GetUniqueStatement("DELETE FROM server_card_cloud_token_data"));
-  cloud_token_data.Run();
-  changed |= db_->GetLastChangeCount() > 0;
-
-  sql::Statement autofill_offer_data(
-      db_->GetUniqueStatement("DELETE FROM offer_data"));
-  autofill_offer_data.Run();
-  changed |= db_->GetLastChangeCount() > 0;
-
-  sql::Statement autofill_offer_eligible_instrument(
-      db_->GetUniqueStatement("DELETE FROM offer_eligible_instrument"));
-  autofill_offer_eligible_instrument.Run();
-  changed |= db_->GetLastChangeCount() > 0;
-
-  sql::Statement autofill_offer_merchant_domain(
-      db_->GetUniqueStatement("DELETE FROM offer_merchant_domain"));
-  autofill_offer_merchant_domain.Run();
-  changed |= db_->GetLastChangeCount() > 0;
+  bool changed = false;
+  for (base::StringPiece table_name :
+       {kMaskedCreditCardsTable, kUnmaskedCreditCardsTable,
+        kServerAddressesTable, kServerCardMetadataTable,
+        kServerAddressMetadataTable, kPaymentsCustomerDataTable,
+        kServerCardCloudTokenDataTable, kOfferDataTable,
+        kOfferEligibleInstrumentTable, kOfferMerchantDomainTable}) {
+    Delete(db_, table_name);
+    changed |= db_->GetLastChangeCount() > 0;
+  }
 
   transaction.Commit();
   return changed;
@@ -2335,11 +2452,9 @@
   time_t delete_end_t = GetEndTime(delete_end);
 
   // Remember Autofill profiles in the time range.
-  sql::Statement s_profiles_get(db_->GetUniqueStatement(
-      "SELECT guid FROM autofill_profiles "
-      "WHERE date_modified >= ? AND date_modified < ?"));
-  s_profiles_get.BindInt64(0, delete_begin_t);
-  s_profiles_get.BindInt64(1, delete_end_t);
+  sql::Statement s_profiles_get;
+  SelectBetween(db_, s_profiles_get, kAutofillProfilesTable, {kGuid},
+                kDateModified, delete_begin_t, delete_end_t);
 
   profiles->clear();
   while (s_profiles_get.Step()) {
@@ -2359,9 +2474,9 @@
   }
 
   // Remove Autofill profiles in the time range.
-  sql::Statement s_profiles(db_->GetUniqueStatement(
-      "DELETE FROM autofill_profiles "
-      "WHERE date_modified >= ? AND date_modified < ?"));
+  sql::Statement s_profiles;
+  DeleteBuilder(db_, s_profiles, kAutofillProfilesTable,
+                "date_modified >= ? AND date_modified < ?");
   s_profiles.BindInt64(0, delete_begin_t);
   s_profiles.BindInt64(1, delete_end_t);
 
@@ -2369,11 +2484,9 @@
     return false;
 
   // Remember Autofill credit cards in the time range.
-  sql::Statement s_credit_cards_get(db_->GetUniqueStatement(
-      "SELECT guid FROM credit_cards "
-      "WHERE date_modified >= ? AND date_modified < ?"));
-  s_credit_cards_get.BindInt64(0, delete_begin_t);
-  s_credit_cards_get.BindInt64(1, delete_end_t);
+  sql::Statement s_credit_cards_get;
+  SelectBetween(db_, s_credit_cards_get, kCreditCardsTable, {kGuid},
+                kDateModified, delete_begin_t, delete_end_t);
 
   credit_cards->clear();
   while (s_credit_cards_get.Step()) {
@@ -2387,18 +2500,18 @@
     return false;
 
   // Remove Autofill credit cards in the time range.
-  sql::Statement s_credit_cards(db_->GetUniqueStatement(
-      "DELETE FROM credit_cards "
-      "WHERE date_modified >= ? AND date_modified < ?"));
+  sql::Statement s_credit_cards;
+  DeleteBuilder(db_, s_credit_cards, kCreditCardsTable,
+                "date_modified >= ? AND date_modified < ?");
   s_credit_cards.BindInt64(0, delete_begin_t);
   s_credit_cards.BindInt64(1, delete_end_t);
   if (!s_credit_cards.Run())
     return false;
 
   // Remove unmasked credit cards in the time range.
-  sql::Statement s_unmasked_cards(
-      db_->GetUniqueStatement("DELETE FROM unmasked_credit_cards "
-                              "WHERE unmask_date >= ? AND unmask_date < ?"));
+  sql::Statement s_unmasked_cards;
+  DeleteBuilder(db_, s_unmasked_cards, kUnmaskedCreditCardsTable,
+                "unmask_date >= ? AND unmask_date < ?");
   s_unmasked_cards.BindInt64(0, delete_begin.ToInternalValue());
   s_unmasked_cards.BindInt64(1, delete_end.ToInternalValue());
   return s_unmasked_cards.Run();
@@ -2414,11 +2527,9 @@
   time_t delete_end_t = GetEndTime(delete_end);
 
   // Remember Autofill profiles with URL origins in the time range.
-  sql::Statement s_profiles_get(db_->GetUniqueStatement(
-      "SELECT guid, origin FROM autofill_profiles "
-      "WHERE date_modified >= ? AND date_modified < ?"));
-  s_profiles_get.BindInt64(0, delete_begin_t);
-  s_profiles_get.BindInt64(1, delete_end_t);
+  sql::Statement s_profiles_get;
+  SelectBetween(db_, s_profiles_get, kAutofillProfilesTable, {kGuid, kOrigin},
+                kDateModified, delete_begin_t, delete_end_t);
 
   std::vector<std::string> profile_guids;
   while (s_profiles_get.Step()) {
@@ -2446,11 +2557,9 @@
   }
 
   // Remember Autofill credit cards with URL origins in the time range.
-  sql::Statement s_credit_cards_get(db_->GetUniqueStatement(
-      "SELECT guid, origin FROM credit_cards "
-      "WHERE date_modified >= ? AND date_modified < ?"));
-  s_credit_cards_get.BindInt64(0, delete_begin_t);
-  s_credit_cards_get.BindInt64(1, delete_end_t);
+  sql::Statement s_credit_cards_get;
+  SelectBetween(db_, s_credit_cards_get, kCreditCardsTable, {kGuid, kOrigin},
+                kDateModified, delete_begin_t, delete_end_t);
 
   std::vector<std::string> credit_card_guids;
   while (s_credit_cards_get.Step()) {
@@ -2475,44 +2584,16 @@
 }
 
 bool AutofillTable::ClearAutofillProfiles() {
-  sql::Statement s1(db_->GetUniqueStatement("DELETE FROM autofill_profiles"));
-
-  if (!s1.Run())
-    return false;
-
-  sql::Statement s2(
-      db_->GetUniqueStatement("DELETE FROM autofill_profile_names"));
-
-  if (!s2.Run())
-    return false;
-
-  sql::Statement s3(
-      db_->GetUniqueStatement("DELETE FROM autofill_profile_emails"));
-
-  if (!s3.Run())
-    return false;
-
-  sql::Statement s4(
-      db_->GetUniqueStatement("DELETE FROM autofill_profile_addresses"));
-
-  if (!s4.Run())
-    return false;
-
-  sql::Statement s5(
-      db_->GetUniqueStatement("DELETE FROM autofill_profile_phones"));
-
-  if (!s5.Run())
-    return false;
-
-  sql::Statement s6(
-      db_->GetUniqueStatement("DELETE FROM autofill_profile_birthdates"));
-
-  return s6.Run();
+  return Delete(db_, kAutofillProfilesTable) &&
+         Delete(db_, kAutofillProfileNamesTable) &&
+         Delete(db_, kAutofillProfileEmailsTable) &&
+         Delete(db_, kAutofillProfileAddressesTable) &&
+         Delete(db_, kAutofillProfilePhonesTable) &&
+         Delete(db_, kAutofillProfileBirthdatesTable);
 }
 
 bool AutofillTable::ClearCreditCards() {
-  sql::Statement s1(db_->GetUniqueStatement("DELETE FROM credit_cards"));
-  return s1.Run();
+  return Delete(db_, kCreditCardsTable);
 }
 
 bool AutofillTable::GetAllSyncMetadata(syncer::ModelType model_type,
@@ -2539,9 +2620,10 @@
   DCHECK(SupportsMetadataForModelType(model_type))
       << "Model type " << model_type << " not supported for metadata";
 
-  sql::Statement s(db_->GetUniqueStatement(
-      "INSERT OR REPLACE INTO autofill_sync_metadata "
-      "(model_type, storage_key, value) VALUES(?, ?, ?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kAutofillSyncMetadataTable,
+                {kModelType, kStorageKey, kValue},
+                /*or_replace=*/true);
   s.BindInt(0, GetKeyValueForModelType(model_type));
   s.BindString(1, storage_key);
   s.BindString(2, metadata.SerializeAsString());
@@ -2554,9 +2636,9 @@
   DCHECK(SupportsMetadataForModelType(model_type))
       << "Model type " << model_type << " not supported for metadata";
 
-  sql::Statement s(
-      db_->GetUniqueStatement("DELETE FROM autofill_sync_metadata WHERE "
-                              "model_type=? AND storage_key=?"));
+  sql::Statement s;
+  DeleteBuilder(db_, s, kAutofillSyncMetadataTable,
+                "model_type=? AND storage_key=?");
   s.BindInt(0, GetKeyValueForModelType(model_type));
   s.BindString(1, storage_key);
 
@@ -2571,9 +2653,9 @@
 
   // Hardcode the id to force a collision, ensuring that there remains only a
   // single entry.
-  sql::Statement s(db_->GetUniqueStatement(
-      "INSERT OR REPLACE INTO autofill_model_type_state (model_type, value) "
-      "VALUES(?,?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kAutofillModelTypeStateTable, {kModelType, kValue},
+                /*or_replace=*/true);
   s.BindInt(0, GetKeyValueForModelType(model_type));
   s.BindString(1, model_type_state.SerializeAsString());
 
@@ -2584,8 +2666,8 @@
   DCHECK(SupportsMetadataForModelType(model_type))
       << "Model type " << model_type << " not supported for metadata";
 
-  sql::Statement s(db_->GetUniqueStatement(
-      "DELETE FROM autofill_model_type_state WHERE model_type=?"));
+  sql::Statement s;
+  DeleteBuilder(db_, s, kAutofillModelTypeStateTable, "model_type=?");
   s.BindInt(0, GetKeyValueForModelType(model_type));
 
   return s.Run();
@@ -2624,11 +2706,14 @@
   if (!transaction.Begin())
     return false;
 
+  constexpr base::StringPiece kAddressLine1 = "address_line_1";
+  constexpr base::StringPiece kAddressLine2 = "address_line_2";
+
   // Test the existence of the |address_line_1| column as an indication that a
   // migration is needed.  It is possible that the new |autofill_profile_phones|
   // schema is in place because the table was newly created when migrating from
   // a pre-version-23 database.
-  if (db_->DoesColumnExist("autofill_profiles", "address_line_1")) {
+  if (DoesColumnExist(db_, kAutofillProfilesTable, kAddressLine1)) {
     // Create a temporary copy of the autofill_profiles table in the (newer)
     // version 54 format.  This table
     //   (a) adds columns for street_address, dependent_locality, and
@@ -2636,19 +2721,22 @@
     //   (b) removes the address_line_1 and address_line_2 columns, which are
     //       replaced by the street_address column, and
     //   (c) removes the country column, which was long deprecated.
-    if (db_->DoesTableExist("autofill_profiles_temp") ||
-        !db_->Execute("CREATE TABLE autofill_profiles_temp ( "
-                      "guid VARCHAR PRIMARY KEY, "
-                      "company_name VARCHAR, "
-                      "street_address VARCHAR, "
-                      "dependent_locality VARCHAR, "
-                      "city VARCHAR, "
-                      "state VARCHAR, "
-                      "zipcode VARCHAR, "
-                      "sorting_code VARCHAR, "
-                      "country_code VARCHAR, "
-                      "date_modified INTEGER NOT NULL DEFAULT 0, "
-                      "origin VARCHAR DEFAULT '')")) {
+    constexpr base::StringPiece kAutofillProfilesTempTable =
+        "autofill_profiles_temp";
+
+    if (db_->DoesTableExist(kAutofillProfilesTempTable) ||
+        !CreateTable(db_, kAutofillProfilesTempTable,
+                     {{kGuid, "VARCHAR PRIMARY KEY"},
+                      {kCompanyName, "VARCHAR"},
+                      {kStreetAddress, "VARCHAR"},
+                      {kDependentLocality, "VARCHAR"},
+                      {kCity, "VARCHAR"},
+                      {kState, "VARCHAR"},
+                      {kZipcode, "VARCHAR"},
+                      {kSortingCode, "VARCHAR"},
+                      {kCountryCode, "VARCHAR"},
+                      {kDateModified, "INTEGER NOT NULL DEFAULT 0"},
+                      {kOrigin, "VARCHAR DEFAULT ''"}})) {
       return false;
     }
 
@@ -2660,8 +2748,9 @@
                       "FROM autofill_profiles")) {
       return false;
     }
-    sql::Statement s(db_->GetUniqueStatement(
-        "SELECT guid, address_line_1, address_line_2 FROM autofill_profiles"));
+    sql::Statement s;
+    SelectBuilder(db_, s, kAutofillProfilesTable,
+                  {kGuid, kAddressLine1, kAddressLine2});
     while (s.Step()) {
       std::string guid = s.ColumnString(0);
       std::u16string line1 = s.ColumnString16(1);
@@ -2682,9 +2771,8 @@
 
     // Delete the existing (version 53) table and replace it with the contents
     // of the temporary table.
-    if (!db_->Execute("DROP TABLE autofill_profiles") ||
-        !db_->Execute("ALTER TABLE autofill_profiles_temp "
-                      "RENAME TO autofill_profiles")) {
+    if (!DropTable(db_, kAutofillProfilesTable) ||
+        !RenameTable(db_, kAutofillProfilesTempTable, kAutofillProfilesTable)) {
       return false;
     }
   }
@@ -2693,14 +2781,16 @@
   // is needed.  It is possible that the new |autofill_profile_phones| schema is
   // in place because the table was newly created when migrating from a
   // pre-version-23 database.
-  if (db_->DoesColumnExist("autofill_profile_phones", "type")) {
+  if (DoesColumnExist(db_, kAutofillProfilePhonesTable, kType)) {
     // Create a temporary copy of the autofill_profile_phones table in the
     // (newer) version 54 format.  This table removes the deprecated |type|
     // column.
-    if (db_->DoesTableExist("autofill_profile_phones_temp") ||
-        !db_->Execute("CREATE TABLE autofill_profile_phones_temp ( "
-                      "guid VARCHAR, "
-                      "number VARCHAR)")) {
+    constexpr base::StringPiece kAutofillProfilePhonesTempTable =
+        "autofill_profile_phones_temp";
+
+    if (db_->DoesTableExist(kAutofillProfilePhonesTempTable) ||
+        !CreateTable(db_, kAutofillProfilePhonesTempTable,
+                     {{kGuid, "VARCHAR"}, {kNumber, "VARCHAR"}})) {
       return false;
     }
 
@@ -2712,10 +2802,10 @@
 
     // Delete the existing (version 53) table and replace it with the contents
     // of the temporary table.
-    if (!db_->Execute("DROP TABLE autofill_profile_phones"))
+    if (!DropTable(db_, kAutofillProfilePhonesTable))
       return false;
-    if (!db_->Execute("ALTER TABLE autofill_profile_phones_temp "
-                      "RENAME TO autofill_profile_phones")) {
+    if (!RenameTable(db_, kAutofillProfilePhonesTempTable,
+                     kAutofillProfilePhonesTable)) {
       return false;
     }
   }
@@ -2728,15 +2818,17 @@
   if (!transaction.Begin())
     return false;
 
-  if (db_->DoesTableExist("autofill_temp") ||
-      !db_->Execute("CREATE TABLE autofill_temp ("
-                    "name VARCHAR, "
-                    "value VARCHAR, "
-                    "value_lower VARCHAR, "
-                    "date_created INTEGER DEFAULT 0, "
-                    "date_last_used INTEGER DEFAULT 0, "
-                    "count INTEGER DEFAULT 1, "
-                    "PRIMARY KEY (name, value))")) {
+  constexpr base::StringPiece kAutofillTempTable = "autofill_temp";
+
+  if (db_->DoesTableExist(kAutofillTempTable) ||
+      !CreateTable(db_, kAutofillTempTable,
+                   {{kName, "VARCHAR"},
+                    {kValue, "VARCHAR"},
+                    {kValueLower, "VARCHAR"},
+                    {kDateCreated, "INTEGER DEFAULT 0"},
+                    {kDateLastUsed, "INTEGER DEFAULT 0"},
+                    {kCount, "INTEGER DEFAULT 1"}},
+                   {kName, kValue})) {
     return false;
   }
 
@@ -2747,10 +2839,11 @@
       "FROM autofill a JOIN autofill_dates ad ON a.pair_id=ad.pair_id "
       "GROUP BY name, value, value_lower, count"));
   while (s.Step()) {
-    sql::Statement s_insert(db_->GetUniqueStatement(
-        "INSERT INTO autofill_temp "
-        "(name, value, value_lower, count, date_created, date_last_used) "
-        "VALUES (?, ?, ?, ?, ?, ?)"));
+    sql::Statement s_insert;
+    InsertBuilder(
+        db_, s_insert, kAutofillTempTable,
+        {kName, kValue, kValueLower, kCount, kDateCreated, kDateLastUsed});
+
     s_insert.BindString16(0, s.ColumnString16(0));
     s_insert.BindString16(1, s.ColumnString16(1));
     s_insert.BindString16(2, s.ColumnString16(2));
@@ -2766,17 +2859,14 @@
 
   // Delete the existing (version 54) tables and replace them with the contents
   // of the temporary table.
-  if (!db_->Execute("DROP TABLE autofill") ||
-      !db_->Execute("DROP TABLE autofill_dates") ||
-      !db_->Execute("ALTER TABLE autofill_temp "
-                    "RENAME TO autofill")) {
+  if (!DropTable(db_, kAutofillTable) || !DropTable(db_, "autofill_dates") ||
+      !RenameTable(db_, kAutofillTempTable, kAutofillTable)) {
     return false;
   }
 
   // Create indices on the new table, for fast lookups.
-  if (!db_->Execute("CREATE INDEX autofill_name ON autofill (name)") ||
-      !db_->Execute("CREATE INDEX autofill_name_value_lower ON "
-                    "autofill (name, value_lower)")) {
+  if (!CreateIndex(db_, kAutofillTable, {kName}) ||
+      !CreateIndex(db_, kAutofillTable, {kName, kValueLower})) {
     return false;
   }
 
@@ -2784,142 +2874,87 @@
 }
 
 bool AutofillTable::MigrateToVersion56AddProfileLanguageCodeForFormatting() {
-  return db_->Execute(
-      "ALTER TABLE autofill_profiles ADD COLUMN language_code VARCHAR");
+  return AddColumn(db_, kAutofillProfilesTable, kLanguageCode, "VARCHAR");
 }
 
 bool AutofillTable::MigrateToVersion57AddFullNameField() {
-  return db_->Execute(
-      "ALTER TABLE autofill_profile_names ADD COLUMN full_name VARCHAR");
+  return AddColumn(db_, kAutofillProfileNamesTable, kFullName, "VARCHAR");
 }
 
 bool AutofillTable::MigrateToVersion60AddServerCards() {
   sql::Transaction transaction(db_);
-  if (!transaction.Begin())
-    return false;
-
-  if (!db_->DoesTableExist("masked_credit_cards") &&
-      !db_->Execute("CREATE TABLE masked_credit_cards ("
-                    "id VARCHAR,"
-                    "status VARCHAR,"
-                    "name_on_card VARCHAR,"
-                    "type VARCHAR,"
-                    "last_four VARCHAR,"
-                    "exp_month INTEGER DEFAULT 0,"
-                    "exp_year INTEGER DEFAULT 0)")) {
-    return false;
-  }
-
-  if (!db_->DoesTableExist("unmasked_credit_cards") &&
-      !db_->Execute("CREATE TABLE unmasked_credit_cards ("
-                    "id VARCHAR,"
-                    "card_number_encrypted VARCHAR)")) {
-    return false;
-  }
-
-  if (!db_->DoesTableExist("server_addresses") &&
-      !db_->Execute("CREATE TABLE server_addresses ("
-                    "id VARCHAR,"
-                    "company_name VARCHAR,"
-                    "street_address VARCHAR,"
-                    "address_1 VARCHAR,"
-                    "address_2 VARCHAR,"
-                    "address_3 VARCHAR,"
-                    "address_4 VARCHAR,"
-                    "postal_code VARCHAR,"
-                    "sorting_code VARCHAR,"
-                    "country_code VARCHAR,"
-                    "language_code VARCHAR)")) {
-    return false;
-  }
-
-  return transaction.Commit();
+  return transaction.Begin() &&
+         CreateTableIfNotExists(db_, kMaskedCreditCardsTable,
+                                {{kId, "VARCHAR"},
+                                 {kStatus, "VARCHAR"},
+                                 {kNameOnCard, "VARCHAR"},
+                                 {kType, "VARCHAR"},
+                                 {kLastFour, "VARCHAR"},
+                                 {kExpMonth, "INTEGER DEFAULT 0"},
+                                 {kExpYear, "INTEGER DEFAULT 0"}}) &&
+         CreateTableIfNotExists(
+             db_, kUnmaskedCreditCardsTable,
+             {{kId, "VARCHAR"}, {kCardNumberEncrypted, "VARCHAR"}}) &&
+         CreateTableIfNotExists(db_, kServerAddressesTable,
+                                {{kId, "VARCHAR"},
+                                 {kCompanyName, "VARCHAR"},
+                                 {kStreetAddress, "VARCHAR"},
+                                 {kAddress1, "VARCHAR"},
+                                 {kAddress2, "VARCHAR"},
+                                 {kAddress3, "VARCHAR"},
+                                 {kAddress4, "VARCHAR"},
+                                 {kPostalCode, "VARCHAR"},
+                                 {kSortingCode, "VARCHAR"},
+                                 {kCountryCode, "VARCHAR"},
+                                 {kLanguageCode, "VARCHAR"}}) &&
+         transaction.Commit();
 }
 
 bool AutofillTable::MigrateToVersion61AddUsageStats() {
   sql::Transaction transaction(db_);
-  if (!transaction.Begin())
-    return false;
-
-  // Add use_count to autofill_profiles.
-  if (!db_->DoesColumnExist("autofill_profiles", "use_count") &&
-      !db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
-                    "use_count INTEGER NOT NULL DEFAULT 0")) {
-    return false;
-  }
-
-  // Add use_date to autofill_profiles.
-  if (!db_->DoesColumnExist("autofill_profiles", "use_date") &&
-      !db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
-                    "use_date INTEGER NOT NULL DEFAULT 0")) {
-    return false;
-  }
-
-  // Add use_count to credit_cards.
-  if (!db_->DoesColumnExist("credit_cards", "use_count") &&
-      !db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
-                    "use_count INTEGER NOT NULL DEFAULT 0")) {
-    return false;
-  }
-
-  // Add use_date to credit_cards.
-  if (!db_->DoesColumnExist("credit_cards", "use_date") &&
-      !db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
-                    "use_date INTEGER NOT NULL DEFAULT 0")) {
-    return false;
-  }
-
-  return transaction.Commit();
+  // Add:
+  // - use_count to autofill_profiles.
+  // - use_date to autofill_profiles.
+  // - use_count to credit_cards.
+  // - use_date to credit_cards.
+  return transaction.Begin() &&
+         AddColumnIfNotExists(db_, kAutofillProfilesTable, kUseCount,
+                              "INTEGER NOT NULL DEFAULT 0") &&
+         AddColumnIfNotExists(db_, kAutofillProfilesTable, kUseDate,
+                              "INTEGER NOT NULL DEFAULT 0") &&
+         AddColumnIfNotExists(db_, kCreditCardsTable, kUseCount,
+                              "INTEGER NOT NULL DEFAULT 0") &&
+         AddColumnIfNotExists(db_, kCreditCardsTable, kUseDate,
+                              "INTEGER NOT NULL DEFAULT 0") &&
+         transaction.Commit();
 }
 
 bool AutofillTable::MigrateToVersion62AddUsageStatsForUnmaskedCards() {
   sql::Transaction transaction(db_);
-  if (!transaction.Begin())
-    return false;
-
-  // Add use_count to unmasked_credit_cards.
-  if (!db_->DoesColumnExist("unmasked_credit_cards", "use_count") &&
-      !db_->Execute("ALTER TABLE unmasked_credit_cards ADD COLUMN "
-                    "use_count INTEGER NOT NULL DEFAULT 0")) {
-    return false;
-  }
-
-  // Add use_date to unmasked_credit_cards.
-  if (!db_->DoesColumnExist("unmasked_credit_cards", "use_date") &&
-      !db_->Execute("ALTER TABLE unmasked_credit_cards ADD COLUMN "
-                    "use_date INTEGER NOT NULL DEFAULT 0")) {
-    return false;
-  }
-
-  return transaction.Commit();
+  // Add:
+  // - use_count to unmasked_credit_cards.
+  // - use_date to unmasked_credit_cards.
+  return transaction.Begin() &&
+         AddColumnIfNotExists(db_, kUnmaskedCreditCardsTable, kUseCount,
+                              "INTEGER NOT NULL DEFAULT 0") &&
+         AddColumnIfNotExists(db_, kUnmaskedCreditCardsTable, kUseDate,
+                              "INTEGER NOT NULL DEFAULT 0") &&
+         transaction.Commit();
 }
 
 bool AutofillTable::MigrateToVersion63AddServerRecipientName() {
-  if (!db_->DoesColumnExist("server_addresses", "recipient_name") &&
-      !db_->Execute("ALTER TABLE server_addresses ADD COLUMN "
-                    "recipient_name VARCHAR")) {
-    return false;
-  }
-  return true;
+  return AddColumnIfNotExists(db_, kServerAddressesTable, kRecipientName,
+                              "VARCHAR");
 }
 
 bool AutofillTable::MigrateToVersion64AddUnmaskDate() {
   sql::Transaction transaction(db_);
-  if (!transaction.Begin())
-    return false;
-
-  if (!db_->DoesColumnExist("unmasked_credit_cards", "unmask_date") &&
-      !db_->Execute("ALTER TABLE unmasked_credit_cards ADD COLUMN "
-                    "unmask_date INTEGER NOT NULL DEFAULT 0")) {
-    return false;
-  }
-  if (!db_->DoesColumnExist("server_addresses", "phone_number") &&
-      !db_->Execute("ALTER TABLE server_addresses ADD COLUMN "
-                    "phone_number VARCHAR")) {
-    return false;
-  }
-
-  return transaction.Commit();
+  return transaction.Begin() &&
+         AddColumnIfNotExists(db_, kUnmaskedCreditCardsTable, kUnmaskDate,
+                              "INTEGER NOT NULL DEFAULT 0") &&
+         AddColumnIfNotExists(db_, kServerAddressesTable, kPhoneNumber,
+                              "VARCHAR") &&
+         transaction.Commit();
 }
 
 bool AutofillTable::MigrateToVersion65AddServerMetadataTables() {
@@ -2927,11 +2962,10 @@
   if (!transaction.Begin())
     return false;
 
-  if (!db_->DoesTableExist("server_card_metadata") &&
-      !db_->Execute("CREATE TABLE server_card_metadata ("
-                    "id VARCHAR NOT NULL,"
-                    "use_count INTEGER NOT NULL DEFAULT 0, "
-                    "use_date INTEGER NOT NULL DEFAULT 0)")) {
+  if (!CreateTableIfNotExists(db_, kServerCardMetadataTable,
+                              {{kId, "VARCHAR NOT NULL"},
+                               {kUseCount, "INTEGER NOT NULL DEFAULT 0"},
+                               {kUseDate, "INTEGER NOT NULL DEFAULT 0"}})) {
     return false;
   }
 
@@ -2943,31 +2977,19 @@
     return false;
   }
 
-  if (!db_->DoesTableExist("server_address_metadata") &&
-      !db_->Execute("CREATE TABLE server_address_metadata ("
-                    "id VARCHAR NOT NULL,"
-                    "use_count INTEGER NOT NULL DEFAULT 0, "
-                    "use_date INTEGER NOT NULL DEFAULT 0)")) {
+  if (!CreateTableIfNotExists(db_, kServerAddressMetadataTable,
+                              {{kId, "VARCHAR NOT NULL"},
+                               {kUseCount, "INTEGER NOT NULL DEFAULT 0"},
+                               {kUseDate, "INTEGER NOT NULL DEFAULT 0"}})) {
     return false;
   }
 
   // Get existing server addresses and generate IDs for them.
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT "
-      "id,"
-      "recipient_name,"
-      "company_name,"
-      "street_address,"
-      "address_1,"     // ADDRESS_HOME_STATE
-      "address_2,"     // ADDRESS_HOME_CITY
-      "address_3,"     // ADDRESS_HOME_DEPENDENT_LOCALITY
-      "address_4,"     // Not supported in AutofillProfile yet.
-      "postal_code,"   // ADDRESS_HOME_ZIP
-      "sorting_code,"  // ADDRESS_HOME_SORTING_CODE
-      "country_code,"  // ADDRESS_HOME_COUNTRY
-      "phone_number,"  // PHONE_HOME_WHOLE_NUMBER
-      "language_code "
-      "FROM server_addresses addresses"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kServerAddressesTable,
+                {kId, kRecipientName, kCompanyName, kStreetAddress, kAddress1,
+                 kAddress2, kAddress3, kAddress4, kPostalCode, kSortingCode,
+                 kCountryCode, kPhoneNumber, kLanguageCode});
   std::vector<AutofillProfile> profiles;
   while (s.Step()) {
     int index = 0;
@@ -2975,16 +2997,16 @@
                             s.ColumnString(index++));
 
     std::u16string recipient_name = s.ColumnString16(index++);
-    profile.SetRawInfo(COMPANY_NAME, s.ColumnString16(index++));
-    profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, s.ColumnString16(index++));
-    profile.SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(index++));
-    profile.SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(index++));
-    profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                       s.ColumnString16(index++));
+    for (ServerFieldType type :
+         {COMPANY_NAME, ADDRESS_HOME_STREET_ADDRESS, ADDRESS_HOME_STATE,
+          ADDRESS_HOME_CITY, ADDRESS_HOME_DEPENDENT_LOCALITY}) {
+      profile.SetRawInfo(type, s.ColumnString16(index++));
+    }
     index++;  // Skip address_4 which we haven't added to AutofillProfile yet.
-    profile.SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(index++));
-    profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, s.ColumnString16(index++));
-    profile.SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(index++));
+    for (ServerFieldType type :
+         {ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, ADDRESS_HOME_COUNTRY}) {
+      profile.SetRawInfo(type, s.ColumnString16(index++));
+    }
     std::u16string phone_number = s.ColumnString16(index++);
     profile.set_language_code(s.ColumnString(index++));
     profile.SetInfo(NAME_FULL, recipient_name, profile.language_code());
@@ -2995,42 +3017,35 @@
   }
 
   // Reinsert with the generated IDs.
-  sql::Statement delete_old(
-      db_->GetUniqueStatement("DELETE FROM server_addresses"));
-  delete_old.Run();
+  Delete(db_, kServerAddressesTable);
 
-  sql::Statement insert(db_->GetUniqueStatement(
-      "INSERT INTO server_addresses("
-      "id,"
-      "recipient_name,"
-      "company_name,"
-      "street_address,"
-      "address_1,"     // ADDRESS_HOME_STATE
-      "address_2,"     // ADDRESS_HOME_CITY
-      "address_3,"     // ADDRESS_HOME_DEPENDENT_LOCALITY
-      "address_4,"     // Not supported in AutofillProfile yet.
-      "postal_code,"   // ADDRESS_HOME_ZIP
-      "sorting_code,"  // ADDRESS_HOME_SORTING_CODE
-      "country_code,"  // ADDRESS_HOME_COUNTRY
-      "phone_number,"  // PHONE_HOME_WHOLE_NUMBER
-      "language_code) "
-      "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+  sql::Statement insert;
+  InsertBuilder(db_, insert, kServerAddressesTable,
+                {kId, kRecipientName, kCompanyName, kStreetAddress,
+                 kAddress1,     // ADDRESS_HOME_STATE
+                 kAddress2,     // ADDRESS_HOME_CITY
+                 kAddress3,     // ADDRESS_HOME_DEPENDENT_LOCALITY
+                 kAddress4,     // Not supported in AutofillProfile yet.
+                 kPostalCode,   // ADDRESS_HOME_ZIP
+                 kSortingCode,  // ADDRESS_HOME_SORTING_CODE
+                 kCountryCode,  // ADDRESS_HOME_COUNTRY
+                 kPhoneNumber,  // PHONE_HOME_WHOLE_NUMBER
+                 kLanguageCode});
   for (const AutofillProfile& profile : profiles) {
     int index = 0;
     insert.BindString(index++, profile.server_id());
-    insert.BindString16(index++, profile.GetRawInfo(NAME_FULL));
-    insert.BindString16(index++, profile.GetRawInfo(COMPANY_NAME));
-    insert.BindString16(index++,
-                        profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_STATE));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_CITY));
-    insert.BindString16(index++,
-                        profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
-    index++;  // SKip address_4 which we haven't added to AutofillProfile yet.
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_ZIP));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE));
-    insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
-    insert.BindString16(index++, profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
+    for (ServerFieldType type :
+         {NAME_FULL, COMPANY_NAME, ADDRESS_HOME_STREET_ADDRESS,
+          ADDRESS_HOME_STATE, ADDRESS_HOME_CITY,
+          ADDRESS_HOME_DEPENDENT_LOCALITY}) {
+      insert.BindString16(index++, profile.GetRawInfo(type));
+    }
+    index++;  // Skip address_4 which we haven't added to AutofillProfile yet.
+    for (ServerFieldType type :
+         {ADDRESS_HOME_ZIP, ADDRESS_HOME_SORTING_CODE, ADDRESS_HOME_COUNTRY,
+          PHONE_HOME_WHOLE_NUMBER}) {
+      insert.BindString16(index++, profile.GetRawInfo(type));
+    }
     insert.BindString(index++, profile.language_code());
     insert.Run();
     insert.Reset(true);
@@ -3042,26 +3057,23 @@
 bool AutofillTable::MigrateToVersion66AddCardBillingAddress() {
   // The default value for this column is null, but Connection::ColumnString()
   // returns an empty string for that.
-  return db_->Execute(
-      "ALTER TABLE credit_cards ADD COLUMN billing_address_id VARCHAR");
+  return AddColumn(db_, kCreditCardsTable, kBillingAddressId, "VARCHAR");
 }
 
 bool AutofillTable::MigrateToVersion67AddMaskedCardBillingAddress() {
   // The default value for this column is null, but Connection::ColumnString()
   // returns an empty string for that.
-  return db_->Execute(
-      "ALTER TABLE masked_credit_cards ADD COLUMN billing_address_id VARCHAR");
+  return AddColumn(db_, kMaskedCreditCardsTable, kBillingAddressId, "VARCHAR");
 }
 
 bool AutofillTable::MigrateToVersion70AddSyncMetadata() {
-  if (!db_->Execute("CREATE TABLE autofill_sync_metadata ("
-                    "storage_key VARCHAR PRIMARY KEY NOT NULL,"
-                    "value BLOB)")) {
+  if (!CreateTable(
+          db_, kAutofillSyncMetadataTable,
+          {{kStorageKey, "VARCHAR PRIMARY KEY NOT NULL"}, {kValue, "BLOB"}})) {
     return false;
   }
-  return db_->Execute(
-      "CREATE TABLE autofill_model_type_state (id INTEGER PRIMARY KEY, value "
-      "BLOB)");
+  return CreateTable(db_, kAutofillModelTypeStateTable,
+                     {{kId, "INTEGER PRIMARY KEY"}, {kValue, "BLOB"}});
 }
 
 bool AutofillTable::
@@ -3071,16 +3083,14 @@
     return false;
 
   // Add the new has_converted column to the server_address_metadata table.
-  if (!db_->DoesColumnExist("server_address_metadata", "has_converted") &&
-      !db_->Execute("ALTER TABLE server_address_metadata ADD COLUMN "
-                    "has_converted BOOL NOT NULL DEFAULT FALSE")) {
+  if (!AddColumnIfNotExists(db_, kServerAddressMetadataTable, kHasConverted,
+                            "BOOL NOT NULL DEFAULT FALSE")) {
     return false;
   }
 
   // Add the new billing_address_id column to the server_card_metadata table.
-  if (!db_->DoesColumnExist("server_card_metadata", "billing_address_id") &&
-      !db_->Execute("ALTER TABLE server_card_metadata ADD COLUMN "
-                    "billing_address_id VARCHAR")) {
+  if (!AddColumnIfNotExists(db_, kServerCardMetadataTable, kBillingAddressId,
+                            "VARCHAR")) {
     return false;
   }
 
@@ -3094,22 +3104,25 @@
     return false;
   }
 
-  if (db_->DoesTableExist("masked_credit_cards_temp") &&
-      !db_->Execute("DROP TABLE masked_credit_cards_temp")) {
+  constexpr base::StringPiece kMaskedCreditCardsTempTable =
+      "masked_credit_cards_temp";
+
+  if (db_->DoesTableExist(kMaskedCreditCardsTempTable) &&
+      !DropTable(db_, kMaskedCreditCardsTempTable)) {
     return false;
   }
 
   // Remove the billing_address_id column from the masked_credit_cards table.
   // Create a temporary table that is a copy of masked_credit_cards but without
   // the billing_address_id column.
-  if (!db_->Execute("CREATE TABLE masked_credit_cards_temp ("
-                    "id VARCHAR,"
-                    "status VARCHAR,"
-                    "name_on_card VARCHAR,"
-                    "type VARCHAR,"
-                    "last_four VARCHAR,"
-                    "exp_month INTEGER DEFAULT 0,"
-                    "exp_year INTEGER DEFAULT 0)")) {
+  if (!CreateTable(db_, kMaskedCreditCardsTempTable,
+                   {{kId, "VARCHAR"},
+                    {kStatus, "VARCHAR"},
+                    {kNameOnCard, "VARCHAR"},
+                    {kType, "VARCHAR"},
+                    {kLastFour, "VARCHAR"},
+                    {kExpMonth, "INTEGER DEFAULT 0"},
+                    {kExpYear, "INTEGER DEFAULT 0"}})) {
     return false;
   }
   // Copy over the data from the original masked_credit_cards table.
@@ -3121,9 +3134,8 @@
   }
   // Delete the existing table and replace it with the contents of the
   // temporary table.
-  if (!db_->Execute("DROP TABLE masked_credit_cards") ||
-      !db_->Execute("ALTER TABLE masked_credit_cards_temp "
-                    "RENAME TO masked_credit_cards")) {
+  if (!DropTable(db_, kMaskedCreditCardsTable) ||
+      !RenameTable(db_, kMaskedCreditCardsTempTable, kMaskedCreditCardsTable)) {
     return false;
   }
 
@@ -3135,51 +3147,51 @@
   if (!transaction.Begin())
     return false;
 
-  if (db_->DoesTableExist("masked_credit_cards_temp") &&
-      !db_->Execute("DROP TABLE masked_credit_cards_temp")) {
+  constexpr base::StringPiece kMaskedCreditCardsTempTable =
+      "masked_credit_cards_temp";
+
+  if (db_->DoesTableExist(kMaskedCreditCardsTempTable) &&
+      !DropTable(db_, kMaskedCreditCardsTempTable)) {
     return false;
   }
 
-  return db_->Execute(
-             "CREATE TABLE masked_credit_cards_temp ("
-             "id VARCHAR,"
-             "status VARCHAR,"
-             "name_on_card VARCHAR,"
-             "network VARCHAR,"
-             "last_four VARCHAR,"
-             "exp_month INTEGER DEFAULT 0,"
-             "exp_year INTEGER DEFAULT 0)") &&
+  return CreateTable(db_, kMaskedCreditCardsTempTable,
+                     {{kId, "VARCHAR"},
+                      {kStatus, "VARCHAR"},
+                      {kNameOnCard, "VARCHAR"},
+                      {kNetwork, "VARCHAR"},
+                      {kLastFour, "VARCHAR"},
+                      {kExpMonth, "INTEGER DEFAULT 0"},
+                      {kExpYear, "INTEGER DEFAULT 0"}}) &&
          db_->Execute(
              "INSERT INTO masked_credit_cards_temp ("
              "id, status, name_on_card, network, last_four, exp_month, exp_year"
              ") SELECT "
              "id, status, name_on_card, type,    last_four, exp_month, exp_year"
              " FROM masked_credit_cards") &&
-         db_->Execute("DROP TABLE masked_credit_cards") &&
-         db_->Execute(
-             "ALTER TABLE masked_credit_cards_temp "
-             "RENAME TO masked_credit_cards") &&
+         DropTable(db_, kMaskedCreditCardsTable) &&
+         RenameTable(db_, kMaskedCreditCardsTempTable,
+                     kMaskedCreditCardsTable) &&
          transaction.Commit();
 }
 
 bool AutofillTable::MigrateToVersion73AddMaskedCardBankName() {
   // Add the new bank_name column to the masked_credit_cards table.
-  return db_->DoesColumnExist("masked_credit_cards", "bank_name") ||
-         db_->Execute(
-             "ALTER TABLE masked_credit_cards ADD COLUMN bank_name VARCHAR");
+  return AddColumnIfNotExists(db_, kMaskedCreditCardsTable, kBankName,
+                              "VARCHAR");
 }
 
 bool AutofillTable::MigrateToVersion74AddServerCardTypeColumn() {
   // Version 73 was actually used by two different schemas; an attempt to add
-  // the "type" column (as in this version 74) was landed and reverted, and then
+  // the kType column (as in this version 74) was landed and reverted, and then
   // the "bank_name" column was added (and stuck). Some clients may have been
   // upgraded to one and some the other. Figure out which is the case.
   const bool added_type_column_in_v73 =
-      db_->DoesColumnExist("masked_credit_cards", "type");
+      DoesColumnExist(db_, kMaskedCreditCardsTable, kType);
 
-  // If we previously added the "type" column, then it's already present with
+  // If we previously added the kType column, then it's already present with
   // the correct semantics, but we now need to run the "bank_name" migration.
-  // Otherwise, we need to add "type" now.
+  // Otherwise, we need to add kType now.
   return added_type_column_in_v73 ? MigrateToVersion73AddMaskedCardBankName()
                                   : db_->Execute(
                                         "ALTER TABLE masked_credit_cards ADD "
@@ -3188,9 +3200,8 @@
 
 bool AutofillTable::MigrateToVersion75AddProfileValidityBitfieldColumn() {
   // Add the new valdity_bitfield column to the autofill_profiles table.
-  return db_->Execute(
-      "ALTER TABLE autofill_profiles ADD COLUMN validity_bitfield UNSIGNED NOT "
-      "NULL DEFAULT 0");
+  return AddColumn(db_, kAutofillProfilesTable, "validity_bitfield",
+                   "UNSIGNED NOT NULL DEFAULT 0");
 }
 
 bool AutofillTable::MigrateToVersion78AddModelTypeColumns() {
@@ -3199,23 +3210,29 @@
   if (!transaction.Begin())
     return false;
 
-  if (db_->DoesTableExist("autofill_sync_metadata_temp") &&
-      !db_->Execute("DROP TABLE autofill_sync_metadata_temp")) {
+  constexpr base::StringPiece kAutofillSyncMetadataTempTable =
+      "autofill_sync_metadata_temp";
+  constexpr base::StringPiece kAutofillModelTypeStateTempTable =
+      "autofill_model_type_state_temp";
+
+  if (db_->DoesTableExist(kAutofillSyncMetadataTempTable) &&
+      !DropTable(db_, kAutofillSyncMetadataTempTable)) {
     return false;
   }
 
-  if (db_->DoesTableExist("autofill_model_type_state_temp") &&
-      !db_->Execute("DROP TABLE autofill_model_type_state_temp")) {
+  if (db_->DoesTableExist(kAutofillModelTypeStateTempTable) &&
+      !DropTable(db_, kAutofillModelTypeStateTempTable)) {
     return false;
   }
 
-  if (!db_->Execute("CREATE TABLE autofill_sync_metadata_temp ("
-                    "model_type INTEGER NOT NULL, "
-                    "storage_key VARCHAR NOT NULL, "
-                    "value BLOB, "
-                    "PRIMARY KEY (model_type, storage_key))") ||
-      !db_->Execute("CREATE TABLE autofill_model_type_state_temp ("
-                    "model_type INTEGER NOT NULL PRIMARY KEY, value BLOB)")) {
+  if (!CreateTable(db_, kAutofillSyncMetadataTempTable,
+                   {{kModelType, "INTEGER NOT NULL"},
+                    {kStorageKey, "VARCHAR NOT NULL"},
+                    {kValue, "BLOB"}},
+                   {kModelType, kStorageKey}) ||
+      !CreateTable(
+          db_, kAutofillModelTypeStateTempTable,
+          {{kModelType, "INTEGER NOT NULL PRIMARY KEY"}, {kValue, "BLOB"}})) {
     return false;
   }
 
@@ -3246,24 +3263,21 @@
     return false;
   }
 
-  return db_->Execute("DROP TABLE autofill_sync_metadata") &&
-         db_->Execute(
-             "ALTER TABLE autofill_sync_metadata_temp "
-             "RENAME TO autofill_sync_metadata") &&
-         db_->Execute("DROP TABLE autofill_model_type_state") &&
-         db_->Execute(
-             "ALTER TABLE autofill_model_type_state_temp "
-             "RENAME TO autofill_model_type_state") &&
+  return DropTable(db_, kAutofillSyncMetadataTable) &&
+         RenameTable(db_, kAutofillSyncMetadataTempTable,
+                     kAutofillSyncMetadataTable) &&
+         DropTable(db_, kAutofillModelTypeStateTable) &&
+         RenameTable(db_, kAutofillModelTypeStateTempTable,
+                     kAutofillModelTypeStateTable) &&
          transaction.Commit();
 }
 
 bool AutofillTable::MigrateToVersion80AddIsClientValidityStatesUpdatedColumn() {
   // Add the client validity states updated flag column to the autofill_profiles
   // table.
-  return db_->Execute(
-      "ALTER TABLE autofill_profiles ADD COLUMN "
-      "is_client_validity_states_updated BOOL NOT "
-      "NULL DEFAULT FALSE");
+  return AddColumn(db_, kAutofillProfilesTable,
+                   "is_client_validity_states_updated",
+                   "BOOL NOT NULL DEFAULT FALSE");
 }
 
 bool AutofillTable::MigrateToVersion81CleanUpWrongModelTypeData() {
@@ -3280,12 +3294,14 @@
   if (!transaction.Begin())
     return false;
 
-  sql::Statement delete_bad_model_type_state(db_->GetUniqueStatement(
-      "DELETE FROM autofill_model_type_state WHERE model_type = ?;"));
+  sql::Statement delete_bad_model_type_state;
+  DeleteBuilder(db_, delete_bad_model_type_state, kAutofillModelTypeStateTable,
+                "model_type = ?");
   delete_bad_model_type_state.BindInt(0, bad_model_type_id);
 
-  sql::Statement delete_bad_sync_metadata(db_->GetUniqueStatement(
-      "DELETE FROM autofill_sync_metadata WHERE model_type = ?;"));
+  sql::Statement delete_bad_sync_metadata;
+  DeleteBuilder(db_, delete_bad_sync_metadata, kAutofillSyncMetadataTable,
+                "model_type = ?");
   delete_bad_sync_metadata.BindInt(0, bad_model_type_id);
 
   return delete_bad_model_type_state.Run() && delete_bad_sync_metadata.Run() &&
@@ -3295,71 +3311,60 @@
 bool AutofillTable::MigrateToVersion83RemoveServerCardTypeColumn() {
   // Sqlite does not support "alter table drop column" syntax, so it has be done
   // manually.
+  constexpr base::StringPiece kMaskedCreditCardsTempTable =
+      "masked_credit_cards_temp";
   sql::Transaction transaction(db_);
   return transaction.Begin() &&
-         db_->Execute(
-             "CREATE TABLE masked_credit_cards_temp ("
-             "id VARCHAR,"
-             "status VARCHAR,"
-             "name_on_card VARCHAR,"
-             "network VARCHAR,"
-             "last_four VARCHAR,"
-             "exp_month INTEGER DEFAULT 0,"
-             "exp_year INTEGER DEFAULT 0, "
-             "bank_name VARCHAR)") &&
+         CreateTable(db_, kMaskedCreditCardsTempTable,
+                     {{kId, "VARCHAR"},
+                      {kStatus, "VARCHAR"},
+                      {kNameOnCard, "VARCHAR"},
+                      {kNetwork, "VARCHAR"},
+                      {kLastFour, "VARCHAR"},
+                      {kExpMonth, "INTEGER DEFAULT 0"},
+                      {kExpYear, "INTEGER DEFAULT 0"},
+                      {kBankName, "VARCHAR"}}) &&
          db_->Execute(
              "INSERT INTO masked_credit_cards_temp "
              "SELECT id, status, name_on_card, network, last_four, exp_month,"
              "exp_year, bank_name "
              "FROM masked_credit_cards") &&
-         db_->Execute("DROP TABLE masked_credit_cards") &&
-         db_->Execute(
-             "ALTER TABLE masked_credit_cards_temp "
-             "RENAME TO masked_credit_cards") &&
+         DropTable(db_, kMaskedCreditCardsTable) &&
+         RenameTable(db_, kMaskedCreditCardsTempTable,
+                     kMaskedCreditCardsTable) &&
          transaction.Commit();
 }
 
 bool AutofillTable::MigrateToVersion84AddNicknameColumn() {
   // Add the nickname column to the masked_credit_cards table.
-  return db_->DoesColumnExist("masked_credit_cards", "nickname") ||
-         db_->Execute(
-             "ALTER TABLE masked_credit_cards ADD COLUMN nickname VARCHAR");
+  return AddColumnIfNotExists(db_, kMaskedCreditCardsTable, kNickname,
+                              "VARCHAR");
 }
 
 bool AutofillTable::MigrateToVersion85AddCardIssuerColumnToMaskedCreditCard() {
   // Add the new card_issuer column to the masked_credit_cards table and set the
   // default value to ISSUER_UNKNOWN.
-  return db_->DoesColumnExist("masked_credit_cards", "card_issuer") ||
-         db_->Execute(
-             "ALTER TABLE masked_credit_cards "
-             "ADD COLUMN card_issuer INTEGER "
-             "DEFAULT 0");
+  return AddColumnIfNotExists(db_, kMaskedCreditCardsTable, kCardIssuer,
+                              "INTEGER DEFAULT 0");
 }
 
 bool AutofillTable::MigrateToVersion88AddNewNameColumns() {
-  for (const char* column : {"honorific_prefix", "first_last_name",
-                             "conjunction_last_name", "second_last_name"}) {
-    if (!db_->DoesColumnExist("autofill_profile_names", column) &&
-        !db_->Execute(
-            base::StrCat({"ALTER TABLE autofill_profile_names ADD COLUMN ",
-                          column, " VARCHAR"})
-                .c_str())) {
+  for (base::StringPiece column : {kHonorificPrefix, kFirstLastName,
+                                   kConjunctionLastName, kSecondLastName}) {
+    if (!AddColumnIfNotExists(db_, kAutofillProfileNamesTable, column,
+                              "VARCHAR")) {
       return false;
     }
   }
 
-  for (const char* column :
-       {"honorific_prefix_status", "first_name_status", "middle_name_status",
-        "last_name_status", "first_last_name_status",
-        "conjunction_last_name_status", "second_last_name_status",
-        "full_name_status"}) {
+  for (base::StringPiece column :
+       {kHonorificPrefixStatus, kFirstNameStatus, kMiddleNameStatus,
+        kLastNameStatus, kFirstLastNameStatus, kConjunctionLastNameStatus,
+        kSecondLastNameStatus, kFullNameStatus}) {
     // The default value of 0 corresponds to the verification status
     // |kNoStatus|.
-    if (!db_->DoesColumnExist("autofill_profile_names", column) &&
-        !db_->Execute(
-            base::StrCat({"ALTER TABLE autofill_profile_names ADD COLUMN ",
-                          column, " INTEGER DEFAULT 0"})
-                .c_str())) {
+    if (!AddColumnIfNotExists(db_, kAutofillProfileNamesTable, column,
+                              "INTEGER DEFAULT 0")) {
       return false;
     }
   }
@@ -3367,78 +3372,58 @@
 }
 
 bool AutofillTable::MigrateToVersion92AddNewPrefixedNameColumn() {
-  if (!db_->DoesColumnExist("autofill_profile_names",
-                            "full_name_with_honorific_prefix") &&
-      !db_->Execute(
-          base::StrCat({"ALTER TABLE autofill_profile_names ADD COLUMN ",
-                        "full_name_with_honorific_prefix", " VARCHAR"})
-              .c_str())) {
-    return false;
-  }
-  if (!db_->DoesColumnExist("autofill_profile_names",
-                            "full_name_with_honorific_prefix_status") &&
-      !db_->Execute(
-          base::StrCat({"ALTER TABLE autofill_profile_names ADD COLUMN ",
-                        "full_name_with_honorific_prefix_status",
-                        " INTEGER DEFAULT 0"})
-              .c_str())) {
-    return false;
-  }
-  return true;
+  return AddColumnIfNotExists(db_, kAutofillProfileNamesTable,
+                              kFullNameWithHonorificPrefix, "VARCHAR") &&
+         AddColumnIfNotExists(db_, kAutofillProfileNamesTable,
+                              kFullNameWithHonorificPrefixStatus,
+                              "INTEGER DEFAULT 0");
 }
 
 bool AutofillTable::MigrateToVersion86RemoveUnmaskedCreditCardsUseColumns() {
   // Sqlite does not support "alter table drop column" syntax, so it has be
   // done manually.
+  constexpr base::StringPiece kUnmaskedCreditCardsTempTable =
+      "unmasked_credit_cards_temp";
   sql::Transaction transaction(db_);
   return transaction.Begin() &&
-         db_->Execute(
-             "CREATE TABLE unmasked_credit_cards_temp ("
-             "id VARCHAR,"
-             "card_number_encrypted VARCHAR,"
-             "unmask_date INTEGER NOT NULL DEFAULT 0)") &&
+         CreateTable(db_, kUnmaskedCreditCardsTempTable,
+                     {{kId, "VARCHAR"},
+                      {kCardNumberEncrypted, "VARCHAR"},
+                      {kUnmaskDate, "INTEGER NOT NULL DEFAULT 0"}}) &&
          db_->Execute(
              "INSERT INTO unmasked_credit_cards_temp "
              "SELECT id, card_number_encrypted, unmask_date "
              "FROM unmasked_credit_cards") &&
-         db_->Execute("DROP TABLE unmasked_credit_cards") &&
-         db_->Execute(
-             "ALTER TABLE unmasked_credit_cards_temp "
-             "RENAME TO unmasked_credit_cards") &&
+         DropTable(db_, kUnmaskedCreditCardsTable) &&
+         RenameTable(db_, kUnmaskedCreditCardsTempTable,
+                     kUnmaskedCreditCardsTable) &&
          transaction.Commit();
 }
 
 bool AutofillTable::MigrateToVersion87AddCreditCardNicknameColumn() {
   // Add the nickname column to the credit_card table.
-  return db_->DoesColumnExist("credit_cards", "nickname") ||
-         db_->Execute("ALTER TABLE credit_cards ADD COLUMN nickname VARCHAR");
+  return AddColumnIfNotExists(db_, kCreditCardsTable, kNickname, "VARCHAR");
 }
 
 bool AutofillTable::MigrateToVersion90AddNewStructuredAddressColumns() {
   if (!db_->DoesTableExist("autofill_profile_addresses"))
     InitProfileAddressesTable();
 
-  for (const char* column : {"dependent_locality", "city", "state", "zip_code",
-                             "sorting_code", "country_code"}) {
-    if (!db_->DoesColumnExist("autofill_profile_addresses", column) &&
-        !db_->Execute(
-            base::StrCat({"ALTER TABLE autofill_profile_addresses ADD COLUMN ",
-                          column, " VARCHAR"})
-                .c_str())) {
+  for (base::StringPiece column : {kDependentLocality, kCity, kState, kZipCode,
+                                   kSortingCode, kCountryCode}) {
+    if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column,
+                              "VARCHAR")) {
       return false;
     }
   }
 
-  for (const char* column :
-       {"dependent_locality_status", "city_status", "state_status",
-        "zip_code_status", "sorting_code_status", "country_code_status"}) {
+  for (base::StringPiece column :
+       {kDependentLocalityStatus, kCityStatus, kStateStatus, kZipCodeStatus,
+        kSortingCodeStatus, kCountryCodeStatus}) {
     // The default value of 0 corresponds to the verification status
     // |kNoStatus|.
-    if (!db_->DoesColumnExist("autofill_profile_addresses", column) &&
-        !db_->Execute(
-            base::StrCat({"ALTER TABLE autofill_profile_addresses ADD COLUMN ",
-                          column, " INTEGER DEFAULT 0"})
-                .c_str())) {
+    if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column,
+                              "INTEGER DEFAULT 0")) {
       return false;
     }
   }
@@ -3446,27 +3431,21 @@
 }
 
 bool AutofillTable::MigrateToVersion91AddMoreStructuredAddressColumns() {
-  if (!db_->DoesTableExist("autofill_profile_addresses"))
+  if (!db_->DoesTableExist(kAutofillProfileAddressesTable))
     InitProfileAddressesTable();
 
-  for (const char* column : {"apartment_number", "floor"}) {
-    if (!db_->DoesColumnExist("autofill_profile_addresses", column) &&
-        !db_->Execute(
-            base::StrCat({"ALTER TABLE autofill_profile_addresses ADD COLUMN ",
-                          column, " VARCHAR"})
-                .c_str())) {
+  for (base::StringPiece column : {kApartmentNumber, kFloor}) {
+    if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column,
+                              "VARCHAR")) {
       return false;
     }
   }
 
-  for (const char* column : {"apartment_number_status", "floor_status"}) {
+  for (base::StringPiece column : {kApartmentNumberStatus, kFloorStatus}) {
     // The default value of 0 corresponds to the verification status
     // |kNoStatus|.
-    if (!db_->DoesColumnExist("autofill_profile_addresses", column) &&
-        !db_->Execute(
-            base::StrCat({"ALTER TABLE autofill_profile_addresses ADD COLUMN ",
-                          column, " INTEGER DEFAULT 0"})
-                .c_str())) {
+    if (!AddColumnIfNotExists(db_, kAutofillProfileAddressesTable, column,
+                              "INTEGER DEFAULT 0")) {
       return false;
     }
   }
@@ -3474,34 +3453,28 @@
 }
 
 bool AutofillTable::MigrateToVersion93AddAutofillProfileLabelColumn() {
-  if (!db_->DoesTableExist("autofill_profiles"))
+  if (!db_->DoesTableExist(kAutofillProfilesTable))
     InitProfileAddressesTable();
 
-  return db_->DoesColumnExist("autofill_profiles", "label") ||
-         db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN label VARCHAR");
+  return AddColumnIfNotExists(db_, kAutofillProfilesTable, kLabel, "VARCHAR");
 }
 
 bool AutofillTable::
     MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn() {
-  if (!db_->DoesTableExist("autofill_profiles"))
+  if (!db_->DoesTableExist(kAutofillProfilesTable))
     InitProfileAddressesTable();
 
-  return db_->DoesColumnExist("autofill_profiles",
-                              "disallow_settings_visible_updates") ||
-         db_->Execute(
-             "ALTER TABLE autofill_profiles ADD COLUMN "
-             "disallow_settings_visible_updates INTEGER NOT NULL DEFAULT 0");
+  return AddColumnIfNotExists(db_, kAutofillProfilesTable,
+                              kDisallowSettingsVisibleUpdates,
+                              "INTEGER NOT NULL DEFAULT 0");
 }
 
 bool AutofillTable::
     MigrateToVersion89AddInstrumentIdColumnToMaskedCreditCard() {
   // Add the new instrument_id column to the masked_credit_cards table and set
   // the default value to 0.
-  return db_->DoesColumnExist("masked_credit_cards", "instrument_id") ||
-         db_->Execute(
-             "ALTER TABLE masked_credit_cards "
-             "ADD COLUMN instrument_id INTEGER "
-             "DEFAULT 0");
+  return AddColumnIfNotExists(db_, kMaskedCreditCardsTable, kInstrumentId,
+                              "INTEGER DEFAULT 0");
 }
 
 bool AutofillTable::MigrateToVersion94AddPromoCodeColumnsToOfferData() {
@@ -3509,17 +3482,14 @@
   if (!transaction.Begin())
     return false;
 
-  if (!db_->DoesTableExist("offer_data"))
+  if (!db_->DoesTableExist(kOfferDataTable))
     InitOfferDataTable();
 
   // Add the new promo_code and DisplayStrings text columns to the offer_data
   // table.
-  for (const char* column : {"promo_code", "value_prop_text",
-                             "see_details_text", "usage_instructions_text"}) {
-    if (!db_->DoesColumnExist("offer_data", column) &&
-        !db_->Execute(base::StrCat({"ALTER TABLE offer_data ADD COLUMN ",
-                                    column, " VARCHAR"})
-                          .c_str())) {
+  for (base::StringPiece column :
+       {kPromoCode, kValuePropText, kSeeDetailsText, kUsageInstructionsText}) {
+    if (!AddColumnIfNotExists(db_, kOfferDataTable, column, "VARCHAR")) {
       return false;
     }
   }
@@ -3531,21 +3501,18 @@
   if (!transaction.Begin())
     return false;
 
-  if (!db_->DoesTableExist("masked_credit_cards"))
+  if (!db_->DoesTableExist(kMaskedCreditCardsTable))
     InitMaskedCreditCardsTable();
 
   // Add virtual_card_enrollment_state to masked_credit_cards.
-  if (!db_->DoesColumnExist("masked_credit_cards",
-                            "virtual_card_enrollment_state") &&
-      !db_->Execute("ALTER TABLE masked_credit_cards ADD COLUMN "
-                    "virtual_card_enrollment_state INTEGER DEFAULT 0")) {
+  if (!AddColumnIfNotExists(db_, kMaskedCreditCardsTable,
+                            kVirtualCardEnrollmentState, "INTEGER DEFAULT 0")) {
     return false;
   }
 
   // Add card_art_url to masked_credit_cards.
-  if (!db_->DoesColumnExist("masked_credit_cards", "card_art_url") &&
-      !db_->Execute("ALTER TABLE masked_credit_cards ADD COLUMN "
-                    "card_art_url VARCHAR")) {
+  if (!AddColumnIfNotExists(db_, kMaskedCreditCardsTable, kCardArtUrl,
+                            "VARCHAR")) {
     return false;
   }
 
@@ -3555,39 +3522,38 @@
 bool AutofillTable::MigrateToVersion98RemoveStatusColumnMaskedCreditCards() {
   // Sqlite does not support "alter table drop column" syntax, so it has be done
   // manually.
+  constexpr base::StringPiece kMaskedCreditCardsTempTable =
+      "masked_credit_cards_temp";
   sql::Transaction transaction(db_);
   return transaction.Begin() &&
-         db_->Execute(
-             "CREATE TABLE masked_credit_cards_temp ("
-             "id VARCHAR,"
-             "name_on_card VARCHAR,"
-             "network VARCHAR,"
-             "last_four VARCHAR,"
-             "exp_month INTEGER DEFAULT 0,"
-             "exp_year INTEGER DEFAULT 0, "
-             "bank_name VARCHAR, "
-             "nickname VARCHAR, "
-             "card_issuer INTEGER DEFAULT 0, "
-             "instrument_id INTEGER DEFAULT 0, "
-             "virtual_card_enrollment_state INTEGER DEFAULT 0, "
-             "card_art_url VARCHAR)") &&
+         CreateTable(db_, kMaskedCreditCardsTempTable,
+                     {{kId, "VARCHAR"},
+                      {kNameOnCard, "VARCHAR"},
+                      {kNetwork, "VARCHAR"},
+                      {kLastFour, "VARCHAR"},
+                      {kExpMonth, "INTEGER DEFAULT 0"},
+                      {kExpYear, "INTEGER DEFAULT 0"},
+                      {kBankName, "VARCHAR"},
+                      {kNickname, "VARCHAR"},
+                      {kCardIssuer, "INTEGER DEFAULT 0"},
+                      {kInstrumentId, "INTEGER DEFAULT 0"},
+                      {kVirtualCardEnrollmentState, "INTEGER DEFAULT 0"},
+                      {kCardArtUrl, "VARCHAR"}}) &&
          db_->Execute(
              "INSERT INTO masked_credit_cards_temp "
              "SELECT id, name_on_card, network, last_four, exp_month, "
              "exp_year, bank_name, nickname, card_issuer, instrument_id, "
              "virtual_card_enrollment_state, card_art_url "
              "FROM masked_credit_cards") &&
-         db_->Execute("DROP TABLE masked_credit_cards") &&
-         db_->Execute(
-             "ALTER TABLE masked_credit_cards_temp "
-             "RENAME TO masked_credit_cards") &&
+         DropTable(db_, kMaskedCreditCardsTable) &&
+         RenameTable(db_, kMaskedCreditCardsTempTable,
+                     kMaskedCreditCardsTable) &&
          transaction.Commit();
 }
 
 bool AutofillTable::MigrateToVersion99RemoveAutofillProfilesTrashTable() {
   sql::Transaction transaction(db_);
-  return transaction.Begin() &&
-         db_->Execute("DROP TABLE autofill_profiles_trash") &&
+  return transaction.Begin() && DropTable(db_, "autofill_profiles_trash") &&
          transaction.Commit();
 }
 
@@ -3597,24 +3563,24 @@
   sql::Transaction transaction(db_);
 
   return transaction.Begin() &&
-         db_->Execute(
-             "CREATE TABLE autofill_profiles_tmp ( "
-             "guid VARCHAR PRIMARY KEY, "
-             "company_name VARCHAR, "
-             "street_address VARCHAR, "
-             "dependent_locality VARCHAR, "
-             "city VARCHAR, "
-             "state VARCHAR, "
-             "zipcode VARCHAR, "
-             "sorting_code VARCHAR, "
-             "country_code VARCHAR, "
-             "date_modified INTEGER NOT NULL DEFAULT 0, "
-             "origin VARCHAR DEFAULT '', "
-             "language_code VARCHAR, "
-             "use_count INTEGER NOT NULL DEFAULT 0, "
-             "use_date INTEGER NOT NULL DEFAULT 0, "
-             "label VARCHAR, "
-             "disallow_settings_visible_updates INTEGER NOT NULL DEFAULT 0)") &&
+         CreateTable(db_, "autofill_profiles_tmp",
+                     {{kGuid, "VARCHAR PRIMARY KEY"},
+                      {kCompanyName, "VARCHAR"},
+                      {kStreetAddress, "VARCHAR"},
+                      {kDependentLocality, "VARCHAR"},
+                      {kCity, "VARCHAR"},
+                      {kState, "VARCHAR"},
+                      {kZipcode, "VARCHAR"},
+                      {kSortingCode, "VARCHAR"},
+                      {kCountryCode, "VARCHAR"},
+                      {kDateModified, "INTEGER NOT NULL DEFAULT 0"},
+                      {kOrigin, "VARCHAR DEFAULT ''"},
+                      {kLanguageCode, "VARCHAR"},
+                      {kUseCount, "INTEGER NOT NULL DEFAULT 0"},
+                      {kUseDate, "INTEGER NOT NULL DEFAULT 0"},
+                      {kLabel, "VARCHAR"},
+                      {kDisallowSettingsVisibleUpdates,
+                       "INTEGER NOT NULL DEFAULT 0"}}) &&
          db_->Execute(
              "INSERT INTO autofill_profiles_tmp "
              "SELECT guid, company_name, street_address, dependent_locality, "
@@ -3622,10 +3588,8 @@
              "origin, language_code, use_count, use_date, label, "
              "disallow_settings_visible_updates "
              " FROM autofill_profiles") &&
-         db_->Execute("DROP TABLE autofill_profiles") &&
-         db_->Execute(
-             "ALTER TABLE autofill_profiles_tmp "
-             "RENAME TO autofill_profiles") &&
+         DropTable(db_, kAutofillProfilesTable) &&
+         RenameTable(db_, "autofill_profiles_tmp", kAutofillProfilesTable) &&
          transaction.Commit();
 }
 
@@ -3639,12 +3603,11 @@
 bool AutofillTable::MigrateToVersion102AddAutofillBirthdatesTable() {
   sql::Transaction transaction(db_);
   return transaction.Begin() &&
-         db_->Execute(
-             "CREATE TABLE autofill_profile_birthdates ( "
-             "guid VARCHAR, "
-             "day INTEGER DEFAULT 0, "
-             "month INTEGER DEFAULT 0, "
-             "year INTEGER DEFAULT 0)") &&
+         CreateTable(db_, kAutofillProfileBirthdatesTable,
+                     {{kGuid, "VARCHAR"},
+                      {kDay, "INTEGER DEFAULT 0"},
+                      {kMonth, "INTEGER DEFAULT 0"},
+                      {kYear, "INTEGER DEFAULT 0"}}) &&
          transaction.Commit();
 }
 
@@ -3653,13 +3616,12 @@
   if (!transaction.Begin())
     return false;
 
-  if (!db_->DoesTableExist("masked_credit_cards"))
+  if (!db_->DoesTableExist(kMaskedCreditCardsTable))
     InitMaskedCreditCardsTable();
 
   // Add product_description to masked_credit_cards.
-  if (!db_->DoesColumnExist("masked_credit_cards", "product_description") &&
-      !db_->Execute("ALTER TABLE masked_credit_cards ADD COLUMN "
-                    "product_description VARCHAR")) {
+  if (!AddColumnIfNotExists(db_, kMaskedCreditCardsTable, kProductDescription,
+                            "VARCHAR")) {
     return false;
   }
 
@@ -3709,10 +3671,10 @@
       return false;
   } else {
     time_t time_as_time_t = time.ToTimeT();
-    sql::Statement s(db_->GetUniqueStatement(
-        "INSERT INTO autofill "
-        "(name, value, value_lower, date_created, date_last_used, count) "
-        "VALUES (?, ?, ?, ?, ?, ?)"));
+    sql::Statement s;
+    InsertBuilder(
+        db_, s, kAutofillTable,
+        {kName, kValue, kValueLower, kDateCreated, kDateLastUsed, kCount});
     s.BindString16(0, element.name);
     s.BindString16(1, element.value);
     s.BindString16(2, base::i18n::ToLower(element.value));
@@ -3750,9 +3712,9 @@
       << "Model type " << model_type << " not supported for metadata";
   DCHECK(metadata_batch);
 
-  sql::Statement s(
-      db_->GetUniqueStatement("SELECT storage_key, value FROM "
-                              "autofill_sync_metadata WHERE model_type=?"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kAutofillSyncMetadataTable, {kStorageKey, kValue},
+                "WHERE model_type=?");
   s.BindInt(0, GetKeyValueForModelType(model_type));
 
   while (s.Step()) {
@@ -3775,8 +3737,9 @@
   DCHECK(SupportsMetadataForModelType(model_type))
       << "Model type " << model_type << " not supported for metadata";
 
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT value FROM autofill_model_type_state WHERE model_type=?"));
+  sql::Statement s;
+  SelectBuilder(db_, s, kAutofillModelTypeStateTable, {kValue},
+                "WHERE model_type=?");
   s.BindInt(0, GetKeyValueForModelType(model_type));
 
   if (!s.Step()) {
@@ -3788,11 +3751,10 @@
 }
 
 bool AutofillTable::InsertAutofillEntry(const AutofillEntry& entry) {
-  std::string sql =
-      "INSERT INTO autofill "
-      "(name, value, value_lower, date_created, date_last_used, count) "
-      "VALUES (?, ?, ?, ?, ?, ?)";
-  sql::Statement s(db_->GetUniqueStatement(sql.c_str()));
+  sql::Statement s;
+  InsertBuilder(
+      db_, s, kAutofillTable,
+      {kName, kValue, kValueLower, kDateCreated, kDateLastUsed, kCount});
   s.BindString16(0, entry.key().name());
   s.BindString16(1, entry.key().value());
   s.BindString16(2, base::i18n::ToLower(entry.key().value()));
@@ -3809,22 +3771,13 @@
 void AutofillTable::AddMaskedCreditCards(
     const std::vector<CreditCard>& credit_cards) {
   DCHECK_GT(db_->transaction_nesting(), 0);
-  sql::Statement masked_insert(
-      db_->GetUniqueStatement("INSERT INTO masked_credit_cards("
-                              "id,"                              // 0
-                              "network,"                         // 1
-                              "name_on_card,"                    // 2
-                              "last_four,"                       // 3
-                              "exp_month,"                       // 4
-                              "exp_year,"                        // 5
-                              "bank_name,"                       // 6
-                              "nickname,"                        // 7
-                              "card_issuer,"                     // 8
-                              "instrument_id,"                   // 9
-                              "virtual_card_enrollment_state, "  // 10
-                              "card_art_url, "                   // 11
-                              "product_description )"            // 12
-                              "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+  sql::Statement masked_insert;
+  InsertBuilder(
+      db_, masked_insert, kMaskedCreditCardsTable,
+      {kId, kNetwork, kNameOnCard, kLastFour, kExpMonth, kExpYear, kBankName,
+       kNickname, kCardIssuer, kInstrumentId, kVirtualCardEnrollmentState,
+       kCardArtUrl, kProductDescription});
+
   int index;
   for (const CreditCard& card : credit_cards) {
     DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type());
@@ -3853,12 +3806,9 @@
 
 void AutofillTable::AddUnmaskedCreditCard(const std::string& id,
                                           const std::u16string& full_number) {
-  sql::Statement s(
-      db_->GetUniqueStatement("INSERT INTO unmasked_credit_cards("
-                              "id,"
-                              "card_number_encrypted,"
-                              "unmask_date)"
-                              "VALUES (?,?,?)"));
+  sql::Statement s;
+  InsertBuilder(db_, s, kUnmaskedCreditCardsTable,
+                {kId, kCardNumberEncrypted, kUnmaskDate});
   s.BindString(0, id);
 
   std::string encrypted_data;
@@ -3870,394 +3820,262 @@
 }
 
 bool AutofillTable::DeleteFromMaskedCreditCards(const std::string& id) {
-  sql::Statement s(
-      db_->GetUniqueStatement("DELETE FROM masked_credit_cards WHERE id = ?"));
-  s.BindString(0, id);
-  s.Run();
+  DeleteWhereColumnEq(db_, kMaskedCreditCardsTable, kId, id);
   return db_->GetLastChangeCount() > 0;
 }
 
 bool AutofillTable::DeleteFromUnmaskedCreditCards(const std::string& id) {
-  sql::Statement s(db_->GetUniqueStatement(
-      "DELETE FROM unmasked_credit_cards WHERE id = ?"));
-  s.BindString(0, id);
-  s.Run();
+  DeleteWhereColumnEq(db_, kUnmaskedCreditCardsTable, kId, id);
   return db_->GetLastChangeCount() > 0;
 }
 
 bool AutofillTable::InitMainTable() {
-  if (!db_->DoesTableExist("autofill")) {
-    if (!db_->Execute("CREATE TABLE autofill ("
-                      "name VARCHAR, "
-                      "value VARCHAR, "
-                      "value_lower VARCHAR, "
-                      "date_created INTEGER DEFAULT 0, "
-                      "date_last_used INTEGER DEFAULT 0, "
-                      "count INTEGER DEFAULT 1, "
-                      "PRIMARY KEY (name, value))") ||
-        !db_->Execute("CREATE INDEX autofill_name ON autofill (name)") ||
-        !db_->Execute("CREATE INDEX autofill_name_value_lower ON "
-                      "autofill (name, value_lower)")) {
-      NOTREACHED();
-      return false;
-    }
+  if (!db_->DoesTableExist(kAutofillTable)) {
+    return CreateTable(db_, kAutofillTable,
+                       {{kName, "VARCHAR"},
+                        {kValue, "VARCHAR"},
+                        {kValueLower, "VARCHAR"},
+                        {kDateCreated, "INTEGER DEFAULT 0"},
+                        {kDateLastUsed, "INTEGER DEFAULT 0"},
+                        {kCount, "INTEGER DEFAULT 1"}},
+                       {kName, kValue}) &&
+           CreateIndex(db_, kAutofillTable, {kName}) &&
+           CreateIndex(db_, kAutofillTable, {kName, kValueLower});
   }
   return true;
 }
 
 bool AutofillTable::InitCreditCardsTable() {
-  if (!db_->DoesTableExist("credit_cards")) {
-    if (!db_->Execute("CREATE TABLE credit_cards ( "
-                      "guid VARCHAR PRIMARY KEY, "
-                      "name_on_card VARCHAR, "
-                      "expiration_month INTEGER, "
-                      "expiration_year INTEGER, "
-                      "card_number_encrypted BLOB, "
-                      "date_modified INTEGER NOT NULL DEFAULT 0, "
-                      "origin VARCHAR DEFAULT '', "
-                      "use_count INTEGER NOT NULL DEFAULT 0, "
-                      "use_date INTEGER NOT NULL DEFAULT 0, "
-                      "billing_address_id VARCHAR, "
-                      "nickname VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-
-  return true;
+  return CreateTableIfNotExists(db_, kCreditCardsTable,
+                                {{kGuid, "VARCHAR PRIMARY KEY"},
+                                 {kNameOnCard, "VARCHAR"},
+                                 {kExpirationMonth, "INTEGER"},
+                                 {kExpirationYear, "INTEGER"},
+                                 {kCardNumberEncrypted, "BLOB"},
+                                 {kDateModified, "INTEGER NOT NULL DEFAULT 0"},
+                                 {kOrigin, "VARCHAR DEFAULT ''"},
+                                 {kUseCount, "INTEGER NOT NULL DEFAULT 0"},
+                                 {kUseDate, "INTEGER NOT NULL DEFAULT 0"},
+                                 {kBillingAddressId, "VARCHAR"},
+                                 {kNickname, "VARCHAR"}});
 }
 
 bool AutofillTable::InitProfilesTable() {
-  if (!db_->DoesTableExist("autofill_profiles")) {
-    if (!db_->Execute(
-            "CREATE TABLE autofill_profiles ( "
-            "guid VARCHAR PRIMARY KEY, "
-            "company_name VARCHAR, "
-            "street_address VARCHAR, "
-            "dependent_locality VARCHAR, "
-            "city VARCHAR, "
-            "state VARCHAR, "
-            "zipcode VARCHAR, "
-            "sorting_code VARCHAR, "
-            "country_code VARCHAR, "
-            "date_modified INTEGER NOT NULL DEFAULT 0, "
-            "origin VARCHAR DEFAULT '', "
-            "language_code VARCHAR, "
-            "use_count INTEGER NOT NULL DEFAULT 0, "
-            "use_date INTEGER NOT NULL DEFAULT 0, "
-            "label VARCHAR, "
-            "disallow_settings_visible_updates INTEGER NOT NULL DEFAULT 0)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(
+      db_, kAutofillProfilesTable,
+      {{kGuid, "VARCHAR PRIMARY KEY"},
+       {kCompanyName, "VARCHAR"},
+       {kStreetAddress, "VARCHAR"},
+       {kDependentLocality, "VARCHAR"},
+       {kCity, "VARCHAR"},
+       {kState, "VARCHAR"},
+       {kZipcode, "VARCHAR"},
+       {kSortingCode, "VARCHAR"},
+       {kCountryCode, "VARCHAR"},
+       {kDateModified, "INTEGER NOT NULL DEFAULT 0"},
+       {kOrigin, "VARCHAR DEFAULT ''"},
+       {kLanguageCode, "VARCHAR"},
+       {kUseCount, "INTEGER NOT NULL DEFAULT 0"},
+       {kUseDate, "INTEGER NOT NULL DEFAULT 0"},
+       {kLabel, "VARCHAR"},
+       {kDisallowSettingsVisibleUpdates, "INTEGER NOT NULL DEFAULT 0"}});
 }
 
 bool AutofillTable::InitProfileNamesTable() {
-  if (!db_->DoesTableExist("autofill_profile_names")) {
-    // The default value of 0 corresponds to the verification status
-    // |kNoStatus|.
-    if (!db_->Execute(
-            "CREATE TABLE autofill_profile_names ( "
-            "guid VARCHAR, "
-            "first_name VARCHAR, "
-            "middle_name VARCHAR, "
-            "last_name VARCHAR, "
-            "full_name VARCHAR, "
-            "honorific_prefix VARCHAR, "
-            "first_last_name VARCHAR, "
-            "conjunction_last_name VARCHAR, "
-            "second_last_name VARCHAR, "
-            "honorific_prefix_status INTEGER DEFAULT 0, "
-            "first_name_status INTEGER DEFAULT 0, "
-            "middle_name_status INTEGER DEFAULT 0, "
-            "last_name_status INTEGER DEFAULT 0, "
-            "first_last_name_status INTEGER DEFAULT 0, "
-            "conjunction_last_name_status INTEGER DEFAULT 0, "
-            "second_last_name_status INTEGER DEFAULT 0, "
-            "full_name_status INTEGER DEFAULT 0, "
-            "full_name_with_honorific_prefix VARCHAR, "
-            "full_name_with_honorific_prefix_status INTEGER DEFAULT 0)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  // The default value of 0 corresponds to the verification status
+  // |kNoStatus|.
+  return CreateTableIfNotExists(
+      db_, kAutofillProfileNamesTable,
+      {{kGuid, "VARCHAR"},
+       {kFirstName, "VARCHAR"},
+       {kMiddleName, "VARCHAR"},
+       {kLastName, "VARCHAR"},
+       {kFullName, "VARCHAR"},
+       {kHonorificPrefix, "VARCHAR"},
+       {kFirstLastName, "VARCHAR"},
+       {kConjunctionLastName, "VARCHAR"},
+       {kSecondLastName, "VARCHAR"},
+       {kHonorificPrefixStatus, "INTEGER DEFAULT 0"},
+       {kFirstNameStatus, "INTEGER DEFAULT 0"},
+       {kMiddleNameStatus, "INTEGER DEFAULT 0"},
+       {kLastNameStatus, "INTEGER DEFAULT 0"},
+       {kFirstLastNameStatus, "INTEGER DEFAULT 0"},
+       {kConjunctionLastNameStatus, "INTEGER DEFAULT 0"},
+       {kSecondLastNameStatus, "INTEGER DEFAULT 0"},
+       {kFullNameStatus, "INTEGER DEFAULT 0"},
+       {kFullNameWithHonorificPrefix, "VARCHAR"},
+       {kFullNameWithHonorificPrefixStatus, "INTEGER DEFAULT 0"}});
 }
 
 bool AutofillTable::InitProfileAddressesTable() {
-  if (!db_->DoesTableExist("autofill_profile_addresses")) {
-    // The default value of 0 corresponds to the verification status
-    // |kNoStatus|.
-    if (!db_->Execute("CREATE TABLE autofill_profile_addresses ( "
-                      "guid VARCHAR, "
-                      "street_address VARCHAR, "
-                      "street_name VARCHAR, "
-                      "dependent_street_name VARCHAR, "
-                      "house_number VARCHAR, "
-                      "subpremise VARCHAR, "
-                      "premise_name VARCHAR, "
-                      "street_address_status INTEGER DEFAULT 0, "
-                      "street_name_status INTEGER DEFAULT 0, "
-                      "dependent_street_name_status INTEGER DEFAULT 0, "
-                      "house_number_status INTEGER DEFAULT 0, "
-                      "subpremise_status INTEGER DEFAULT 0, "
-                      "premise_name_status INTEGER DEFAULT 0, "
-                      "dependent_locality VARCHAR, "
-                      "city VARCHAR, "
-                      "state VARCHAR, "
-                      "zip_code VARCHAR, "
-                      "sorting_code VARCHAR, "
-                      "country_code VARCHAR, "
-                      "dependent_locality_status INTEGER DEFAULT 0, "
-                      "city_status INTEGER DEFAULT 0, "
-                      "state_status INTEGER DEFAULT 0, "
-                      "zip_code_status INTEGER DEFAULT 0, "
-                      "sorting_code_status INTEGER DEFAULT 0, "
-                      "country_code_status INTEGER DEFAULT 0, "
-                      "apartment_number VARCHAR, "
-                      "floor VARCHAR, "
-                      "apartment_number_status INTEGER DEFAULT 0, "
-                      "floor_status INTEGER DEFAULT 0)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  // The default value of 0 corresponds to the verification status
+  // |kNoStatus|.
+  return CreateTableIfNotExists(
+      db_, kAutofillProfileAddressesTable,
+      {{kGuid, "VARCHAR"},
+       {kStreetAddress, "VARCHAR"},
+       {kStreetName, "VARCHAR"},
+       {kDependentStreetName, "VARCHAR"},
+       {kHouseNumber, "VARCHAR"},
+       {kSubpremise, "VARCHAR"},
+       {kPremiseName, "VARCHAR"},
+       {kStreetAddressStatus, "INTEGER DEFAULT 0"},
+       {kStreetNameStatus, "INTEGER DEFAULT 0"},
+       {kDependentStreetNameStatus, "INTEGER DEFAULT 0"},
+       {kHouseNumberStatus, "INTEGER DEFAULT 0"},
+       {kSubpremiseStatus, "INTEGER DEFAULT 0"},
+       {kPremiseNameStatus, "INTEGER DEFAULT 0"},
+       {kDependentLocality, "VARCHAR"},
+       {kCity, "VARCHAR"},
+       {kState, "VARCHAR"},
+       {kZipCode, "VARCHAR"},
+       {kSortingCode, "VARCHAR"},
+       {kCountryCode, "VARCHAR"},
+       {kDependentLocalityStatus, "INTEGER DEFAULT 0"},
+       {kCityStatus, "INTEGER DEFAULT 0"},
+       {kStateStatus, "INTEGER DEFAULT 0"},
+       {kZipCodeStatus, "INTEGER DEFAULT 0"},
+       {kSortingCodeStatus, "INTEGER DEFAULT 0"},
+       {kCountryCodeStatus, "INTEGER DEFAULT 0"},
+       {kApartmentNumber, "VARCHAR"},
+       {kFloor, "VARCHAR"},
+       {kApartmentNumberStatus, "INTEGER DEFAULT 0"},
+       {kFloorStatus, "INTEGER DEFAULT 0"}});
 }
 
 bool AutofillTable::InitProfileEmailsTable() {
-  if (!db_->DoesTableExist("autofill_profile_emails")) {
-    if (!db_->Execute("CREATE TABLE autofill_profile_emails ( "
-                      "guid VARCHAR, "
-                      "email VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kAutofillProfileEmailsTable,
+                                {{kGuid, "VARCHAR"}, {kEmail, "VARCHAR"}});
 }
 
 bool AutofillTable::InitProfilePhonesTable() {
-  if (!db_->DoesTableExist("autofill_profile_phones")) {
-    if (!db_->Execute("CREATE TABLE autofill_profile_phones ( "
-                      "guid VARCHAR, "
-                      "number VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kAutofillProfilePhonesTable,
+                                {{kGuid, "VARCHAR"}, {kNumber, "VARCHAR"}});
 }
 
 bool AutofillTable::InitProfileBirthdatesTable() {
-  if (!db_->DoesTableExist("autofill_profile_birthdates")) {
-    if (!db_->Execute("CREATE TABLE autofill_profile_birthdates ( "
-                      "guid VARCHAR, "
-                      "day INTEGER DEFAULT 0, "
-                      "month INTEGER DEFAULT 0, "
-                      "year INTEGER DEFAULT 0)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kAutofillProfileBirthdatesTable,
+                                {{kGuid, "VARCHAR"},
+                                 {kDay, "INTEGER DEFAULT 0"},
+                                 {kMonth, "INTEGER DEFAULT 0"},
+                                 {kYear, "INTEGER DEFAULT 0"}});
 }
 
 bool AutofillTable::InitMaskedCreditCardsTable() {
-  if (!db_->DoesTableExist("masked_credit_cards")) {
-    if (!db_->Execute("CREATE TABLE masked_credit_cards ("
-                      "id VARCHAR,"
-                      "name_on_card VARCHAR,"
-                      "network VARCHAR,"
-                      "last_four VARCHAR,"
-                      "exp_month INTEGER DEFAULT 0,"
-                      "exp_year INTEGER DEFAULT 0, "
-                      "bank_name VARCHAR, "
-                      "nickname VARCHAR, "
-                      "card_issuer INTEGER DEFAULT 0, "
-                      "instrument_id INTEGER DEFAULT 0, "
-                      "virtual_card_enrollment_state INTEGER DEFAULT 0, "
-                      "card_art_url VARCHAR, "
-                      "product_description VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(
+      db_, kMaskedCreditCardsTable,
+      {{kId, "VARCHAR"},
+       {kNameOnCard, "VARCHAR"},
+       {kNetwork, "VARCHAR"},
+       {kLastFour, "VARCHAR"},
+       {kExpMonth, "INTEGER DEFAULT 0"},
+       {kExpYear, "INTEGER DEFAULT 0"},
+       {kBankName, "VARCHAR"},
+       {kNickname, "VARCHAR"},
+       {kCardIssuer, "INTEGER DEFAULT 0"},
+       {kInstrumentId, "INTEGER DEFAULT 0"},
+       {kVirtualCardEnrollmentState, "INTEGER DEFAULT 0"},
+       {kCardArtUrl, "VARCHAR"},
+       {kProductDescription, "VARCHAR"}});
 }
 
 bool AutofillTable::InitUnmaskedCreditCardsTable() {
-  if (!db_->DoesTableExist("unmasked_credit_cards")) {
-    if (!db_->Execute("CREATE TABLE unmasked_credit_cards ("
-                      "id VARCHAR,"
-                      "card_number_encrypted VARCHAR,"
-                      "unmask_date INTEGER NOT NULL DEFAULT 0)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kUnmaskedCreditCardsTable,
+                                {{kId, "VARCHAR"},
+                                 {kCardNumberEncrypted, "VARCHAR"},
+                                 {kUnmaskDate, "INTEGER NOT NULL DEFAULT 0"}});
 }
 
 bool AutofillTable::InitServerCardMetadataTable() {
-  if (!db_->DoesTableExist("server_card_metadata")) {
-    if (!db_->Execute("CREATE TABLE server_card_metadata ("
-                      "id VARCHAR NOT NULL,"
-                      "use_count INTEGER NOT NULL DEFAULT 0, "
-                      "use_date INTEGER NOT NULL DEFAULT 0, "
-                      "billing_address_id VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kServerCardMetadataTable,
+                                {{kId, "VARCHAR NOT NULL"},
+                                 {kUseCount, "INTEGER NOT NULL DEFAULT 0"},
+                                 {kUseDate, "INTEGER NOT NULL DEFAULT 0"},
+                                 {kBillingAddressId, "VARCHAR"}});
 }
 
 bool AutofillTable::InitServerAddressesTable() {
-  if (!db_->DoesTableExist("server_addresses")) {
-    // The space after language_code is necessary to match what sqlite does
-    // when it appends the column in migration.
-    if (!db_->Execute("CREATE TABLE server_addresses ("
-                      "id VARCHAR,"
-                      "company_name VARCHAR,"
-                      "street_address VARCHAR,"
-                      "address_1 VARCHAR,"
-                      "address_2 VARCHAR,"
-                      "address_3 VARCHAR,"
-                      "address_4 VARCHAR,"
-                      "postal_code VARCHAR,"
-                      "sorting_code VARCHAR,"
-                      "country_code VARCHAR,"
-                      "language_code VARCHAR, "   // Space required.
-                      "recipient_name VARCHAR, "  // Ditto.
-                      "phone_number VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kServerAddressesTable,
+                                {{kId, "VARCHAR"},
+                                 {kCompanyName, "VARCHAR"},
+                                 {kStreetAddress, "VARCHAR"},
+                                 {kAddress1, "VARCHAR"},
+                                 {kAddress2, "VARCHAR"},
+                                 {kAddress3, "VARCHAR"},
+                                 {kAddress4, "VARCHAR"},
+                                 {kPostalCode, "VARCHAR"},
+                                 {kSortingCode, "VARCHAR"},
+                                 {kCountryCode, "VARCHAR"},
+                                 {kLanguageCode, "VARCHAR"},
+                                 {kRecipientName, "VARCHAR"},
+                                 {kPhoneNumber, "VARCHAR"}});
 }
 
 bool AutofillTable::InitServerAddressMetadataTable() {
-  if (!db_->DoesTableExist("server_address_metadata")) {
-    if (!db_->Execute("CREATE TABLE server_address_metadata ("
-                      "id VARCHAR NOT NULL,"
-                      "use_count INTEGER NOT NULL DEFAULT 0, "
-                      "use_date INTEGER NOT NULL DEFAULT 0, "
-                      "has_converted BOOL NOT NULL DEFAULT FALSE)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(
+      db_, kServerAddressMetadataTable,
+      {{kId, "VARCHAR NOT NULL"},
+       {kUseCount, "INTEGER NOT NULL DEFAULT 0"},
+       {kUseDate, "INTEGER NOT NULL DEFAULT 0"},
+       {kHasConverted, "BOOL NOT NULL DEFAULT FALSE"}});
 }
 
 bool AutofillTable::InitAutofillSyncMetadataTable() {
-  if (!db_->DoesTableExist("autofill_sync_metadata")) {
-    if (!db_->Execute("CREATE TABLE autofill_sync_metadata ("
-                      "model_type INTEGER NOT NULL, "
-                      "storage_key VARCHAR NOT NULL, "
-                      "value BLOB, "
-                      "PRIMARY KEY (model_type, storage_key))")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kAutofillSyncMetadataTable,
+                                {{kModelType, "INTEGER NOT NULL"},
+                                 {kStorageKey, "VARCHAR NOT NULL"},
+                                 {kValue, "BLOB"}},
+                                {kModelType, kStorageKey});
 }
 
 bool AutofillTable::InitModelTypeStateTable() {
-  if (!db_->DoesTableExist("autofill_model_type_state")) {
-    if (!db_->Execute("CREATE TABLE autofill_model_type_state ("
-                      "model_type INTEGER NOT NULL PRIMARY KEY, value BLOB)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(
+      db_, kAutofillModelTypeStateTable,
+      {{kModelType, "INTEGER NOT NULL PRIMARY KEY"}, {kValue, "BLOB"}});
 }
 
 bool AutofillTable::InitPaymentsCustomerDataTable() {
-  if (!db_->DoesTableExist("payments_customer_data")) {
-    if (!db_->Execute("CREATE TABLE payments_customer_data "
-                      "(customer_id VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kPaymentsCustomerDataTable,
+                                {{kCustomerId, "VARCHAR"}});
 }
 
 bool AutofillTable::InitPaymentsUPIVPATable() {
-  if (!db_->DoesTableExist("payments_upi_vpa")) {
-    if (!db_->Execute("CREATE TABLE payments_upi_vpa ("
-                      "vpa VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kPaymentsUpiVpaTable, {{kVpa, "VARCHAR"}});
 }
 
 bool AutofillTable::InitServerCreditCardCloudTokenDataTable() {
-  if (!db_->DoesTableExist("server_card_cloud_token_data")) {
-    if (!db_->Execute("CREATE TABLE server_card_cloud_token_data ( "
-                      "id VARCHAR, "
-                      "suffix VARCHAR, "
-                      "exp_month INTEGER DEFAULT 0, "
-                      "exp_year INTEGER DEFAULT 0, "
-                      "card_art_url VARCHAR, "
-                      "instrument_token VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kServerCardCloudTokenDataTable,
+                                {{kId, "VARCHAR"},
+                                 {kSuffix, "VARCHAR"},
+                                 {kExpMonth, "INTEGER DEFAULT 0"},
+                                 {kExpYear, "INTEGER DEFAULT 0"},
+                                 {kCardArtUrl, "VARCHAR"},
+                                 {kInstrumentToken, "VARCHAR"}});
 }
 
 bool AutofillTable::InitOfferDataTable() {
-  if (!db_->DoesTableExist("offer_data")) {
-    if (!db_->Execute("CREATE TABLE offer_data ( "
-                      "offer_id UNSIGNED LONG, "
-                      "offer_reward_amount VARCHAR, "
-                      "expiry UNSIGNED LONG, "
-                      "offer_details_url VARCHAR, "
-                      "merchant_domain VARCHAR, "
-                      "promo_code VARCHAR, "
-                      "value_prop_text VARCHAR, "
-                      "see_details_text VARCHAR, "
-                      "usage_instructions_text VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(db_, kOfferDataTable,
+                                {{kOfferId, "UNSIGNED LONG"},
+                                 {kOfferRewardAmount, "VARCHAR"},
+                                 {kExpiry, "UNSIGNED LONG"},
+                                 {kOfferDetailsUrl, "VARCHAR"},
+                                 {kMerchantDomain, "VARCHAR"},
+                                 {kPromoCode, "VARCHAR"},
+                                 {kValuePropText, "VARCHAR"},
+                                 {kSeeDetailsText, "VARCHAR"},
+                                 {kUsageInstructionsText, "VARCHAR"}});
 }
 
 bool AutofillTable::InitOfferEligibleInstrumentTable() {
-  if (!db_->DoesTableExist("offer_eligible_instrument")) {
-    if (!db_->Execute("CREATE TABLE offer_eligible_instrument ( "
-                      "offer_id UNSIGNED LONG,"
-                      "instrument_id UNSIGNED LONG)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(
+      db_, kOfferEligibleInstrumentTable,
+      {{kOfferId, "UNSIGNED LONG"}, {kInstrumentId, "UNSIGNED LONG"}});
 }
 
 bool AutofillTable::InitOfferMerchantDomainTable() {
-  if (!db_->DoesTableExist("offer_merchant_domain")) {
-    if (!db_->Execute("CREATE TABLE offer_merchant_domain ( "
-                      "offer_id UNSIGNED LONG,"
-                      "merchant_domain VARCHAR)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
+  return CreateTableIfNotExists(
+      db_, kOfferMerchantDomainTable,
+      {{kOfferId, "UNSIGNED LONG"}, {kMerchantDomain, "VARCHAR"}});
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h
index 351bc47..016713d 100644
--- a/components/autofill/core/browser/webdata/autofill_table.h
+++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -180,6 +180,7 @@
 //   first_last_name_status
 //   conjunction_last_name_status
 //   second_last_name_status
+//   full_name_status
 //   full_name_with_honorific_prefix_status
 //                      Each token of the names has an additional validation
 //                      status that indicates if Autofill parsed the value out
@@ -390,7 +391,7 @@
 // payments_upi_vpa     Contains saved UPI/VPA payment data.
 //                      https://en.wikipedia.org/wiki/Unified_Payments_Interface
 //
-//   vpa_id             A string representing the UPI ID (a.k.a. VPA) value.
+//   vpa                A string representing the UPI ID (a.k.a. VPA) value.
 //
 // offer_data           The data for Autofill offers which will be presented in
 //                      payments autofill flows.
@@ -805,6 +806,12 @@
   bool DeleteFromMaskedCreditCards(const std::string& id);
   bool DeleteFromUnmaskedCreditCards(const std::string& id);
 
+  // Helper function extracting common code between `SetServerProfiles()` and
+  // `SetServerAddressData()`.
+  void SetServerProfilesAndMetadata(
+      const std::vector<AutofillProfile>& profiles,
+      bool update_metadata);
+
   bool InitMainTable();
   bool InitCreditCardsTable();
   bool InitProfilesTable();
diff --git a/components/autofill/core/common/form_field_data.h b/components/autofill/core/common/form_field_data.h
index de784bca..f4855c62 100644
--- a/components/autofill/core/common/form_field_data.h
+++ b/components/autofill/core/common/form_field_data.h
@@ -123,8 +123,6 @@
     return is_focusable && role != RoleAttribute::kPresentation;
   }
 
-  // These functions do not work for Autofill code.
-  // TODO(https://crbug.com/1006745): Fix this.
   bool DidUserType() const;
   bool HadFocus() const;
   bool WasAutofilled() const;
diff --git a/components/autofill_assistant/browser/android/starter_delegate_android.cc b/components/autofill_assistant/browser/android/starter_delegate_android.cc
index 77661db..09abeef5 100644
--- a/components/autofill_assistant/browser/android/starter_delegate_android.cc
+++ b/components/autofill_assistant/browser/android/starter_delegate_android.cc
@@ -15,6 +15,7 @@
 #include "components/autofill_assistant/browser/android/trigger_script_bridge_android.h"
 #include "components/autofill_assistant/browser/android/ui_controller_android_utils.h"
 #include "components/autofill_assistant/browser/assistant_field_trial_util.h"
+#include "components/autofill_assistant/browser/headless/headless_script_controller_impl.h"
 #include "components/autofill_assistant/browser/public/runtime_manager_impl.h"
 #include "components/autofill_assistant/browser/script_parameters.h"
 #include "components/autofill_assistant/browser/website_login_manager_impl.h"
@@ -295,6 +296,11 @@
   java_onboarding_helper_ = *(++array.begin());
 }
 
+void StarterDelegateAndroid::HeadlessControllerDoneCallback(
+    HeadlessScriptController::ScriptResult result) {
+  headless_script_controller_.reset();
+}
+
 void StarterDelegateAndroid::Start(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& jcaller,
@@ -312,7 +318,20 @@
       /* onboarding_shown = */ false, /* is_direct_action = */ false,
       jinitial_url, GetIsCustomTab());
 
-  starter_->Start(std::move(trigger_context));
+  if (trigger_context->GetScriptParameters().GetRunHeadless()) {
+    headless_script_controller_ =
+        std::make_unique<HeadlessScriptControllerImpl>(
+            &GetWebContents(), /*action_extension_delegate=*/nullptr);
+
+    headless_script_controller_->StartScript(
+        // Note: this ignores device-only parameters.
+        ui_controller_android_utils::CreateStringMapFromJava(
+            env, jparameter_names, jparameter_values),
+        base::BindOnce(&StarterDelegateAndroid::HeadlessControllerDoneCallback,
+                       base::Unretained(this)));
+  } else {
+    starter_->Start(std::move(trigger_context));
+  }
 }
 
 void StarterDelegateAndroid::StartScriptDefaultUi(
diff --git a/components/autofill_assistant/browser/android/starter_delegate_android.h b/components/autofill_assistant/browser/android/starter_delegate_android.h
index 4b44ed6..fc10e5a 100644
--- a/components/autofill_assistant/browser/android/starter_delegate_android.h
+++ b/components/autofill_assistant/browser/android/starter_delegate_android.h
@@ -15,6 +15,7 @@
 #include "components/autofill_assistant/browser/assistant_field_trial_util.h"
 #include "components/autofill_assistant/browser/metrics.h"
 #include "components/autofill_assistant/browser/onboarding_result.h"
+#include "components/autofill_assistant/browser/public/headless_script_controller.h"
 #include "components/autofill_assistant/browser/starter.h"
 #include "components/autofill_assistant/browser/starter_platform_delegate.h"
 #include "components/autofill_assistant/browser/trigger_context.h"
@@ -130,10 +131,14 @@
 
   void CreateJavaDependenciesIfNecessary();
 
+  void HeadlessControllerDoneCallback(
+      HeadlessScriptController::ScriptResult result);
+
   WEB_CONTENTS_USER_DATA_KEY_DECL();
   base::WeakPtr<Starter> starter_;
   // Contains AssistantStaticDependencies which do not change.
   const std::unique_ptr<const DependenciesAndroid> dependencies_;
+  std::unique_ptr<HeadlessScriptController> headless_script_controller_;
   // Can change based on activity attachment.
   base::android::ScopedJavaGlobalRef<jobject> java_dependencies_;
 
diff --git a/components/autofill_assistant/browser/script_parameters.cc b/components/autofill_assistant/browser/script_parameters.cc
index 99bab29..2493dde 100644
--- a/components/autofill_assistant/browser/script_parameters.cc
+++ b/components/autofill_assistant/browser/script_parameters.cc
@@ -137,6 +137,7 @@
 const char kDetailsImageClickthroughUrl[] = "DETAILS_IMAGE_CLICKTHROUGH_URL";
 const char kDetailsTotalPriceLabel[] = "DETAILS_TOTAL_PRICE_LABEL";
 const char kDetailsTotalPrice[] = "DETAILS_TOTAL_PRICE";
+const char kRunHeadless[] = "RUN_HEADLESS";
 
 ScriptParameters::ScriptParameters(
     const base::flat_map<std::string, std::string>& parameters) {
@@ -292,6 +293,10 @@
   return GetTypedParameter<bool>(parameters_, kSendAnnotateDomModelVersion);
 }
 
+absl::optional<bool> ScriptParameters::GetRunHeadless() const {
+  return GetTypedParameter<bool>(parameters_, kRunHeadless);
+}
+
 absl::optional<bool> ScriptParameters::GetDetailsShowInitial() const {
   return GetTypedParameter<bool>(parameters_, kDetailsShowInitialParameterName);
 }
diff --git a/components/autofill_assistant/browser/script_parameters.h b/components/autofill_assistant/browser/script_parameters.h
index a87c2c7..189d167d 100644
--- a/components/autofill_assistant/browser/script_parameters.h
+++ b/components/autofill_assistant/browser/script_parameters.h
@@ -67,6 +67,7 @@
   std::vector<std::string> GetExperiments() const;
   absl::optional<bool> GetDisableRpcSigning() const;
   absl::optional<bool> GetSendAnnotateDomModelVersion() const;
+  absl::optional<bool> GetRunHeadless() const;
 
   // Details parameters.
   absl::optional<bool> GetDetailsShowInitial() const;
diff --git a/components/background_sync/OWNERS b/components/background_sync/OWNERS
index 9a19c81..5b8437b 100644
--- a/components/background_sync/OWNERS
+++ b/components/background_sync/OWNERS
@@ -1,5 +1,4 @@
 iclelland@chromium.org
-jkarlin@chromium.org
 nator@chromium.org
 peter@chromium.org
 rayankans@chromium.org
diff --git a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java
index eac1150..318cfc1 100644
--- a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java
+++ b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetControllerImpl.java
@@ -95,6 +95,13 @@
     private final BackPressHandler mBackPressHandler;
 
     /**
+     * An observer that observes changes to the bottom sheet content {@code
+     * BottomSheetContent#mBackPressStateChangedSupplier} and updates the {@code
+     * BottomSheetControllerImpl#mBackPressStateChangedSupplier}.
+     */
+    private Callback<Boolean> mContentBackPressStateChangedObserver;
+
+    /**
      * Build a new controller of the bottom sheet.
      * @param scrim A supplier of the scrim that shows when the bottom sheet is opened.
      * @param initializedCallback A callback for the sheet being created (as the sheet is not
@@ -117,8 +124,16 @@
         mBackPressHandler = new BackPressHandler() {
             @Override
             public void handleBackPress() {
-                boolean ret = BottomSheetControllerImpl.this.handleBackPress();
-                assert ret;
+                assert mBottomSheet != null && !mSuppressionTokens.hasTokens()
+                        && mBottomSheet.getCurrentSheetContent() != null;
+                if (Boolean.TRUE.equals(mBottomSheet.getCurrentSheetContent()
+                                                .getBackPressStateChangedSupplier()
+                                                .get())) {
+                    mBottomSheet.getCurrentSheetContent().onBackPressed();
+                    return;
+                }
+                int sheetState = mBottomSheet.getMinSwipableSheetState();
+                mBottomSheet.setSheetState(sheetState, true, StateChangeReason.BACK_PRESS);
             }
 
             @Override
@@ -191,6 +206,7 @@
 
                 mScrimCoordinatorSupplier.get().showScrim(scrimProperties);
                 mScrimShown = true;
+                updateBackPressStateChangedSupplier();
             }
 
             @Override
@@ -214,6 +230,7 @@
                         mBottomSheet.setSheetState(SheetState.HIDDEN, true);
                     }
                 }
+                updateBackPressStateChangedSupplier();
             }
 
             @Override
@@ -545,6 +562,16 @@
         }
 
         BottomSheetContent nextContent = mContentQueue.poll();
+        if (mBottomSheet.getCurrentSheetContent() != null) {
+            mBottomSheet.getCurrentSheetContent().getBackPressStateChangedSupplier().removeObserver(
+                    mContentBackPressStateChangedObserver);
+        }
+        if (nextContent != null) {
+            mContentBackPressStateChangedObserver =
+                    (contentWillHandleBackPress) -> updateBackPressStateChangedSupplier();
+            nextContent.getBackPressStateChangedSupplier().addObserver(
+                    mContentBackPressStateChangedObserver);
+        }
         mBottomSheet.showContent(nextContent);
         mBottomSheet.setSheetState(mBottomSheet.getOpeningState(), animate);
     }
@@ -597,6 +624,10 @@
      */
     private void updateBackPressStateChangedSupplier() {
         mBackPressStateChangedSupplier.set(mBottomSheet != null && !mSuppressionTokens.hasTokens()
-                && mBottomSheet.getCurrentSheetContent() != null);
+                && mBottomSheet.getCurrentSheetContent() != null
+                && (Boolean.TRUE.equals(mBottomSheet.getCurrentSheetContent()
+                                                .getBackPressStateChangedSupplier()
+                                                .get())
+                        || mBottomSheet.isSheetOpen()));
     }
 }
diff --git a/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetContent.java b/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetContent.java
index 9b0c55e7..8cc82b5 100644
--- a/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetContent.java
+++ b/components/browser_ui/bottomsheet/android/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetContent.java
@@ -10,6 +10,7 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.base.Callback;
+import org.chromium.base.supplier.ObservableSupplierImpl;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -184,6 +185,23 @@
     }
 
     /**
+     * @return An observable supplier that will hold true if the content will intercept and handle a
+     *         back press event, false otherwise. If left {@code false}, the sheet will collapse to
+     *         its minimum state on back press or do nothing if in the minimum / peeking state.
+     */
+    default ObservableSupplierImpl<Boolean> getBackPressStateChangedSupplier() {
+        ObservableSupplierImpl<Boolean> supplier = new ObservableSupplierImpl<>();
+        supplier.set(false);
+        return supplier;
+    }
+
+    /**
+     * Invoked in the event of a back press that is pre-emptively determined by
+     * #getBackPressStateChangedSupplier.
+     */
+    default void onBackPressed() {}
+
+    /**
      * @return The resource id of the content description for the bottom sheet. This is
      *         generally the name of the feature/content that is showing. 'Swipe down to close.'
      *         will be automatically appended after the content description.
diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd
index 6eb6aa1..15a2ed9 100644
--- a/components/browser_ui/strings/android/browser_ui_strings.grd
+++ b/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -372,6 +372,10 @@
         This page is dangerous
       </message>
 
+      <message name="IDS_CONCAT_TWO_STRINGS_WITH_PERIODS" desc="This string concatenates two other strings. In the English language, this particular concatenation is done via a period and a whitespace after the first string, and a period after the second string. For example: '1 compromised password. 2 weak passwords.'">
+        <ph name="TYPE_1">%1$s<ex>2 compromised passwords</ex></ph>. <ph name="TYPE_2">%2$s<ex>7 weak passwords</ex></ph>.
+      </message>
+
       <!-- Cookie controls UI -->
       <message name="IDS_COOKIE_CONTROLS_BLOCKED_COOKIES" desc="Text showing the number of blocked cookies on a site.">
         {COOKIE_COUNT, plural,
diff --git a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_CONCAT_TWO_STRINGS_WITH_PERIODS.png.sha1 b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_CONCAT_TWO_STRINGS_WITH_PERIODS.png.sha1
new file mode 100644
index 0000000..88d45b3e
--- /dev/null
+++ b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_CONCAT_TWO_STRINGS_WITH_PERIODS.png.sha1
@@ -0,0 +1 @@
+7c4759e9ff383f9089f965694cc1964fe8145715
\ No newline at end of file
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb
index 7fee2b0..abe12b9 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">ጣቢያዎች የዙሪያዎ የ3ል ካርታ እንዲፈጥሩ ወይም የካሜራ ቦታን እንዲከታተል ከመፍቀድ በፊት ጠይቅ (የሚመከር)</translation>
 <translation id="2212565012507486665">ኩኪዎችን ፍቀድ</translation>
 <translation id="2228071138934252756">የእርስዎን ካሜራ <ph name="APP_NAME" /> እንዲደርስበት ለማድረግ፣ በ <ph name="BEGIN_LINK" />Android ቅንብሮች<ph name="END_LINK" /> ውስጥ ካሜራን በተጨማሪ ያብሩ።</translation>
+<translation id="2238944249568001759">በእርስዎ የመጨረሻ ትር ላይ በመመስረት የተጠቆሙ ፍለጋዎች</translation>
 <translation id="2241634353105152135">አንድ ጊዜ ብቻ</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" />ን አስወግድ</translation>
 <translation id="2289270750774289114">አንድ ጣቢያ በአቅራቢያ ያሉ ብሉቱዝ መሣሪያዎችን ፈልጎ ለማግኘት ሲፈልግ ጠይቅ (የሚመከር)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_ar.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_ar.xtb
index 129066d..edb8db7 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_ar.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_ar.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">طلب الإذن قبل السماح لموقع إلكتروني بإنشاء خريطة ثلاثية الأبعاد للبيئة المحيطة بك أو تتبُّع موضع الكاميرا (مقترَح)</translation>
 <translation id="2212565012507486665">السماح بملفات تعريف الارتباط</translation>
 <translation id="2228071138934252756">‏للسماح لتطبيق <ph name="APP_NAME" /> بالوصول إلى الكاميرا، يُرجى أيضًا تفعيل الكاميرا في <ph name="BEGIN_LINK" />إعدادات Android<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">عمليات البحث المقترَحة استنادًا إلى علامة التبويب الأخيرة</translation>
 <translation id="2241634353105152135">مرة واحدة فقط</translation>
 <translation id="2253414712144136228">إزالة <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">طلب الإذن عند محاولة موقع إلكتروني العثور على أجهزة البلوتوث المجاورة (إجراء موصَى به)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_eu.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_eu.xtb
index 74d5c7b..c45489a 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_eu.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_eu.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Eskatu zure baimena webguneei inguruaren 3D-ko mapa bat sortu edo kameraren posizioaren jarraipena egiteko baimena eman aurretik (gomendatua)</translation>
 <translation id="2212565012507486665">Onartu cookieak</translation>
 <translation id="2228071138934252756"><ph name="APP_NAME" /> aplikazioari kamera atzitzeko baimena emateko, kamera atzitzeko baimena aktibatu behar duzu <ph name="BEGIN_LINK" />Android-en ezarpenetan<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Azken fitxaren arabera iradokitako bilaketak</translation>
 <translation id="2241634353105152135">Behin soilik</translation>
 <translation id="2253414712144136228">Kendu <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">Eskatu nire baimena webgune batek inguruko Bluetooth bidezko gailuak bilatu nahi dituenean (gomendatua)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_fi.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_fi.xtb
index 4b99ba3..f7ede62 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_fi.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_fi.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Kysy, saavatko sivustot luoda 3D-kartan ympäristöstäsi tai seurata kameran asentoa (suositus)</translation>
 <translation id="2212565012507486665">Salli evästeet</translation>
 <translation id="2228071138934252756">Laita kamera päälle myös <ph name="BEGIN_LINK" />Androidin asetuksista<ph name="END_LINK" />, jotta <ph name="APP_NAME" /> saa pääsyn kameraasi.</translation>
+<translation id="2238944249568001759">Viime välilehteen perustuvat hakuehdotukset</translation>
 <translation id="2241634353105152135">Vain kerran</translation>
 <translation id="2253414712144136228">Poista <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">Kysy aina, kun sivusto pyytää lupaa löytää lähellä olevat Bluetooth-laitteet (suositus)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_fr.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_fr.xtb
index 11825a3..be6c4e9 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_fr.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_fr.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Demander avant d'autoriser les sites à créer un plan 3D de votre environnement ou à suivre la position de la caméra (recommandé)</translation>
 <translation id="2212565012507486665">Autoriser les cookies</translation>
 <translation id="2228071138934252756">Pour autoriser <ph name="APP_NAME" /> à accéder à votre caméra, activez-la également dans les <ph name="BEGIN_LINK" />paramètres Android<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Suggestions de recherches basées sur votre dernier onglet</translation>
 <translation id="2241634353105152135">Une seule fois</translation>
 <translation id="2253414712144136228">Supprimer <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">Me demander lorsqu'un site souhaite accéder aux appareils Bluetooth se trouvant à proximité (recommandé)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_gl.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_gl.xtb
index 04f611e..b9a8589f 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_gl.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_gl.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Preguntar antes de permitir que os sitios creen un mapa 3D do que te rodea e fagan un seguimento da posición da cámara (recomendado)</translation>
 <translation id="2212565012507486665">Permitir uso de cookies</translation>
 <translation id="2228071138934252756">Para permitir que <ph name="APP_NAME" /> acceda á cámara, actívaa tamén en <ph name="BEGIN_LINK" />Configuración de Android<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Buscas suxeridas baseadas na última pestana</translation>
 <translation id="2241634353105152135">Só unha vez</translation>
 <translation id="2253414712144136228">Eliminar <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">Preguntar cando un sitio web queira detectar dispositivos Bluetooth próximos (recomendado)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_gu.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_gu.xtb
index e99d8d7..04cac2d 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_gu.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_gu.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">કોઈ સાઇટને તમારી આજુબાજુનો 3D નકશો બનાવતા અથવા કૅમેરાના સ્ટેટસને ટ્રૅક કરવાની મંજૂરી આપતા પહેલાં પૂછો (સુઝાવ આપીએ છીએ)</translation>
 <translation id="2212565012507486665">કુકીને મંજૂરી આપો</translation>
 <translation id="2228071138934252756"><ph name="APP_NAME" /> તમારો કૅમેરા ઍક્સેસ કરી શકે તે માટે <ph name="BEGIN_LINK" />Android સેટિંગ<ph name="END_LINK" />માં પણ કૅમેરા ચાલુ કરો.</translation>
+<translation id="2238944249568001759">તમારા છેલ્લા ટૅબ પર આધારિત સૂચવેલી શોધ</translation>
 <translation id="2241634353105152135">માત્ર એક વખત</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" /> કાઢી નાખો</translation>
 <translation id="2289270750774289114">જ્યારે કોઈ સાઇટ નજીકના બ્લૂટૂથ ડિવાઇસને શોધવા માગે ત્યારે પૂછો (સુઝાવ આપેલ)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb
index 42e6170..982a4c7 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Prikaži upit prije omogućivanja web-lokacijama da izrađuju 3D kartu vašeg okruženja i prate položaj kamere (preporučeno)</translation>
 <translation id="2212565012507486665">Dopusti kolačiće</translation>
 <translation id="2228071138934252756">Da bi aplikacija <ph name="APP_NAME" /> mogla pristupiti vašoj kameri, uključite kameru i u <ph name="BEGIN_LINK" />Androidovim postavkama<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Predložena pretraživanja na temelju vaše posljednje kartice</translation>
 <translation id="2241634353105152135">Samo jednom</translation>
 <translation id="2253414712144136228">Ukloni <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">Prikaži upit kad web-lokacija želi tražiti Bluetooth uređaje u blizini (preporučeno)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_hy.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_hy.xtb
index 0915644..86a48f20 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_hy.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_hy.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Կայքերի համար թույլտվություն խնդրել՝ ստեղծելու շրջակայքի եռաչափ քարտեզն ու հետագծելու ձեր տեսախցիկի դիրքը (խորհուրդ է տրվում)</translation>
 <translation id="2212565012507486665">Թույլատրել քուքիները</translation>
 <translation id="2228071138934252756">Որպեսզի տեսախցիկը հասանելի դառնա <ph name="APP_NAME" />-ին, միացրեք այն <ph name="BEGIN_LINK" />Android-ի կարգավորումներում<ph name="END_LINK" />։</translation>
+<translation id="2238944249568001759">Առաջարկվող որոնման հարցումներ ձեր վերջին ներդիրի հիման վրա</translation>
 <translation id="2241634353105152135">Միայն այս անգամ</translation>
 <translation id="2253414712144136228">Հեռացնել «<ph name="NAME_OF_LIST_ITEM" />» կետը</translation>
 <translation id="2289270750774289114">Հարցնել, երբ որևէ կայք ուզում է հայտնաբերել մոտակա Bluetooth սարքերը (խորհուրդ է տրվում)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_id.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_id.xtb
index ebb1617..8bac1e7 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_id.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_id.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Tanyakan sebelum mengizinkan situs membuat peta 3D untuk area di sekeliling Anda atau melacak posisi kamera (direkomendasikan)</translation>
 <translation id="2212565012507486665">Izinkan cookie</translation>
 <translation id="2228071138934252756">Untuk mengizinkan <ph name="APP_NAME" /> mengakses kamera Anda, aktifkan juga kamera di <ph name="BEGIN_LINK" />Setelan Android<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Penelusuran yang disarankan berdasarkan tab terakhir Anda</translation>
 <translation id="2241634353105152135">Sekali ini saja</translation>
 <translation id="2253414712144136228">Hapus <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">Tanyakan saat situs ingin menemukan perangkat Bluetooth di sekitar (direkomendasikan)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb
index 9691c12..9d6161a 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">תוצג שאלה לפני מתן הרשאה לאתרים ליצור מפה בתלת ממד של הסביבה שלך או לעקוב אחר מיקום המצלמה (מומלץ)</translation>
 <translation id="2212565012507486665">‏אישור קובצי cookie</translation>
 <translation id="2228071138934252756">‏כדי לאפשר ל-<ph name="APP_NAME" /> לגשת אל המצלמה, צריך להפעיל אותה גם ב<ph name="BEGIN_LINK" />הגדרות Android<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">הצעות לחיפושים על סמך הכרטיסייה האחרונה שלך</translation>
 <translation id="2241634353105152135">פעם אחת בלבד</translation>
 <translation id="2253414712144136228">הסרה של <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">‏המערכת מבקשת אישור כשאתר רוצה לאתר התקני Bluetooth קרובים (מומלץ)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_ja.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_ja.xtb
index 976c5cf..b000e57 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_ja.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_ja.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">サイトに周囲の 3D マップの作成またはカメラ位置の追跡を許可する前に確認します(推奨)</translation>
 <translation id="2212565012507486665">Cookie を許可</translation>
 <translation id="2228071138934252756"><ph name="APP_NAME" /> にカメラへのアクセスを許可するには、<ph name="BEGIN_LINK" />Android の設定<ph name="END_LINK" />でもカメラをオンにしてください。</translation>
+<translation id="2238944249568001759">最後のタブに基づく検索キーワードの候補</translation>
 <translation id="2241634353105152135">一回限り</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" /> を削除</translation>
 <translation id="2289270750774289114">サイトから近くにある Bluetooth デバイスの検出を求められたときに確認する(推奨)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_ko.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_ko.xtb
index fd75170..bf8880a 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_ko.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_ko.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">사이트에서 주변 환경의 3D 지도를 생성하거나 카메라 위치를 추적하도록 허용하기 전에 확인(권장)</translation>
 <translation id="2212565012507486665">쿠키 허용</translation>
 <translation id="2228071138934252756"><ph name="APP_NAME" />에서 카메라에 액세스하도록 허용하려면 <ph name="BEGIN_LINK" />Android 설정<ph name="END_LINK" />에서도 카메라를 사용 설정하세요.</translation>
+<translation id="2238944249568001759">마지막 탭을 바탕으로 한 추천 검색어</translation>
 <translation id="2241634353105152135">한 번만</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" /> 삭제</translation>
 <translation id="2289270750774289114">사이트가 주변 블루투스 기기를 조회하려고 할 때 확인(권장)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_ky.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_ky.xtb
index 99e9380..1a8163f 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_ky.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_ky.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Сайттар айланаңыздын 3D картасын түзгөнү же камераңыздын абалын көргөнү жатканда уруксат суралсын (сунушталат)</translation>
 <translation id="2212565012507486665">Cookies файлдарына уруксат берүү</translation>
 <translation id="2228071138934252756"><ph name="APP_NAME" /> колдонмосуна камерага кирүүгө уруксат берүү үчүн, <ph name="BEGIN_LINK" />Android Жөндөөлөрүнөн<ph name="END_LINK" /> камераны күйгүзүңүз.</translation>
+<translation id="2238944249568001759">Соңку өтмөктүн негизинде табылган нерселер</translation>
 <translation id="2241634353105152135">Бир гана жлу</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" /> өчүрүү</translation>
 <translation id="2289270750774289114">Сайт жакын жердеги Bluetooth түзмөктөрүн колдонгону жатканда уруксат суралсын (сунушталат)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_or.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_or.xtb
index ec368d5..4b629f2 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_or.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_or.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">ଆପଣଙ୍କ ପରିପାର୍ଶ୍ୱର ଏକ 3D ମ୍ୟାପ୍ ତିଆରି କରିବା ଏବଂ କ୍ୟାମେରା ସ୍ଥିତି ଟ୍ରାକ୍ କରିବାକୁ ସାଇଟଗୁଡ଼ିକୁ ଅନୁମତି ଦେବା ପୂର୍ବରୁ ପଚାରନ୍ତୁ (ସୁପାରିଶ କରାଯାଇଛି)</translation>
 <translation id="2212565012507486665">କୁକୀଗୁଡ଼ିକୁ ଅନୁମତି ଦିଅନ୍ତୁ</translation>
 <translation id="2228071138934252756"><ph name="APP_NAME" />କୁ ଆପଣଙ୍କ କ୍ୟାମେରା ଆକ୍ସେସ୍ ଦେବା ପାଇଁ, <ph name="BEGIN_LINK" />Android ସେଟିଂସ<ph name="END_LINK" />ରେ କ୍ୟାମେରା ମଧ୍ୟ ଚାଲୁ କରନ୍ତୁ।</translation>
+<translation id="2238944249568001759">ଆପଣଙ୍କ ଶେଷ ଟାବ ଆଧାରରେ ପ୍ରସ୍ତାବିତ ସନ୍ଧାନଗୁଡ଼ିକ</translation>
 <translation id="2241634353105152135">ଥରେ ମାତ୍ର</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" />କୁ କାଢ଼ି ଦିଅନ୍ତୁ</translation>
 <translation id="2289270750774289114">ଯେତେବେଳେ ଏକ ସାଇଟ୍ ଆଖପାଖର ବ୍ଲୁଟୂଥ୍ ଡିଭାଇସ୍‍ଗୁଡ଼ିକୁ ଖୋଜିବାକୁ ଚାହୁଁଛି, ସେତେବେଳେ ପଚାରନ୍ତୁ (ସୁପାରିଶ କରାଯାଇଛି)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_pa.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_pa.xtb
index 4f4e7df..e004269b 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_pa.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_pa.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">ਸਾਈਟਾਂ ਵੱਲੋਂ ਤੁਹਾਡੇ ਆਲੇ-ਦੁਆਲੇ ਦਾ 3D ਨਕਸ਼ਾ ਬਣਾਉਣ ਜਾਂ ਕੈਮਰਾ ਸਥਿਤੀ ਨੂੰ ਟਰੈਕ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦੇਣ ਤੋਂ ਪਹਿਲਾਂ ਪੁੱਛੋ (ਸਿਫ਼ਾਰਸ਼ੀ)</translation>
 <translation id="2212565012507486665">ਕੁਕੀਜ਼ ਨੂੰ ਆਗਿਆ ਦਿਓ</translation>
 <translation id="2228071138934252756"><ph name="APP_NAME" /> ਨੂੰ ਆਪਣੇ ਕੈਮਰੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣ ਲਈ, <ph name="BEGIN_LINK" />Android ਸੈਟਿੰਗਾਂ<ph name="END_LINK" /> ਵਿੱਚ ਕੈਮਰਾ ਵੀ ਚਾਲੂ ਕਰੋ।</translation>
+<translation id="2238944249568001759">ਤੁਹਾਡੀ ਪਿਛਲੀ ਟੈਬ ਦੇ ਆਧਾਰ 'ਤੇ ਸੁਝਾਈਆਂ ਗਈਆਂ ਖੋਜਾਂ</translation>
 <translation id="2241634353105152135">ਸਿਰਫ ਇੱਕ ਵਾਰ</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" /> ਹਟਾਓ</translation>
 <translation id="2289270750774289114">ਕਿਸੇ ਸਾਈਟ ਵੱਲੋਂ ਨਜ਼ਦੀਕੀ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਦਾ ਪਤਾ ਲਗਾਉਣ ਵੇਲੇ ਪੁੱਛੋ (ਸਿਫ਼ਾਰਸ਼ੀ)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_ru.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_ru.xtb
index 1c9a797..4d2ddfe 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_ru.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_ru.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Запрашивать для сайтов разрешение на создание 3D-карты места, в котором вы находитесь, и отслеживание положения камеры (рекомендуется)</translation>
 <translation id="2212565012507486665">Разрешить файлы cookie</translation>
 <translation id="2228071138934252756">Чтобы у приложения "<ph name="APP_NAME" />" был доступ к камере, включите ее в <ph name="BEGIN_LINK" />настройках Android<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Варианты поисковых запросов, основанные на данных последней вкладки</translation>
 <translation id="2241634353105152135">Однократно</translation>
 <translation id="2253414712144136228">Удалить пункт "<ph name="NAME_OF_LIST_ITEM" />"</translation>
 <translation id="2289270750774289114">Запрашивать для сайтов разрешение на поиск Bluetooth-устройств поблизости (рекомендуется)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_sk.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_sk.xtb
index dc8db153..7bc14b1 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_sk.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_sk.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Pýtať sa, či chcete povoliť webu vytvárať priestorovú mapu okolia alebo sledovať pozíciu kamery (odporúčané)</translation>
 <translation id="2212565012507486665">Povoliť súbory cookie</translation>
 <translation id="2228071138934252756">Ak chcete povoliť aplikácii <ph name="APP_NAME" /> používať váš fotoaparát, zapnite ho aj v <ph name="BEGIN_LINK" />nastaveniach Androidu<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Navrhované vyhľadávania na základe vašej poslednej karty</translation>
 <translation id="2241634353105152135">Iba raz</translation>
 <translation id="2253414712144136228">Odobrať osobu alebo odstrániť položku <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">Opýtať sa, keď chce web objavovať zariadenia Bluetooth v okolí (odporúčané)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb
index e0e5743..024d70b3 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Vprašaj, preden se spletnim mestom dovoli ustvarjanje 3D-zemljevida vaše okolice ali spremljanje položaja kamere (priporočljivo)</translation>
 <translation id="2212565012507486665">Dovoli piškotke</translation>
 <translation id="2228071138934252756">Če želite aplikaciji <ph name="APP_NAME" /> omogočiti dostop do fotoaparata, fotoaparat vklopite tudi v <ph name="BEGIN_LINK" />nastavitvah za Android<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Predlagana iskanja na podlagi zadnjega zavihka</translation>
 <translation id="2241634353105152135">Samo enkrat</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" /> Odstrani</translation>
 <translation id="2289270750774289114">Vprašaj, ko želi spletno mesto odkrivati naprave Bluetooth v bližini (priporočljivo)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_ta.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_ta.xtb
index a460382..0ab0ea9a 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_ta.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_ta.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">உங்களைச் சுற்றியுள்ள இடங்களின் 3D மேப்பை உருவாக்கவோ கேமரா நிலையை டிராக் செய்யவோ தளங்களை அனுமதிப்பதற்கு முன்பாக அனுமதி கேட்கும் (பரிந்துரைக்கப்படுகிறது)</translation>
 <translation id="2212565012507486665">குக்கீகளை அனுமதி</translation>
 <translation id="2228071138934252756">உங்கள் கேமராவை அணுக <ph name="APP_NAME" /> ஆப்ஸை அனுமதிப்பதற்கு <ph name="BEGIN_LINK" />Android அமைப்புகளிலும்<ph name="END_LINK" /> கேமராவிற்கான அனுமதியை இயக்கவும்.</translation>
+<translation id="2238944249568001759">நீங்கள் கடைசியாகப் பார்வையிட்ட பக்கத்தின்படி பரிந்துரைக்கப்படும் தேடல்கள்</translation>
 <translation id="2241634353105152135">ஒருமுறை மட்டுமே</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" /> ஐ அகற்றும்</translation>
 <translation id="2289270750774289114">அருகிலுள்ள புளூடூத் சாதனங்களை வலைதளம் கண்டறிய முயலும்போது கேள் (பரிந்துரைக்கப்படுகிறது)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb
index 103b6e0..0d12fbd5 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">మీ పరిసరాల 3D మ్యాప్‌ను రూపొందించడానికి లేదా కెమెరా పొజిషన్‌ను ట్రాక్ చేయడానికి సైట్‌లను అనుమతించే ముందు అడగాలి (సిఫార్సు చేయడమైనది)</translation>
 <translation id="2212565012507486665">కుక్కీలను అనుమతించు</translation>
 <translation id="2228071138934252756">మీ కెమెరాను యాక్సెస్ చేయడానికి <ph name="APP_NAME" />ని అనుమతించడానికి, <ph name="BEGIN_LINK" />Android సెట్టింగ్‌ల<ph name="END_LINK" />లో కూడా కెమెరాను ఆన్ చేయండి.</translation>
+<translation id="2238944249568001759">మీ చివరి ట్యాబ్ ఆధారంగా సూచించబడిన సెర్చ్‌లు</translation>
 <translation id="2241634353105152135">ఒకసారి మాత్రమే</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" />‌ను తీసివేయండి</translation>
 <translation id="2289270750774289114">ఏదైనా ఒక సైట్ సమీపంలోని బ్లూటూత్ పరికరాలను కనుగొనాలనుకున్నప్పుడు అనుమతి అడుగుతుంది (సిఫార్సు చేయడమైనది)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_tr.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_tr.xtb
index 7560fa6c2..12b5de42 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_tr.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_tr.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Sitelerin çevremin 3D haritasını oluşturmasına veya kamera konumunu takip etmesine izin vermeden önce sor (önerilir)</translation>
 <translation id="2212565012507486665">Çerezlere izin ver</translation>
 <translation id="2228071138934252756"><ph name="APP_NAME" /> uygulamasının kameranıza erişebilmesi için <ph name="BEGIN_LINK" />Android Ayarları<ph name="END_LINK" />'nda da kamerayı açın.</translation>
+<translation id="2238944249568001759">Son sekmenize göre önerilen aramalar</translation>
 <translation id="2241634353105152135">Sadece bir defa</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" /> öğesini kaldır</translation>
 <translation id="2289270750774289114">Bir site yakındaki Bluetooth cihazları bulmak istediğinde sor (önerilir)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_uk.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_uk.xtb
index 4eb066f8..1b4c6d0 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_uk.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_uk.xtb
@@ -131,7 +131,7 @@
 <translation id="4008040567710660924">Дозволити файли cookie для конкретного сайту.</translation>
 <translation id="4046123991198612571">Наступна композиція</translation>
 <translation id="4149994727733219643">Спрощений перегляд веб-сторінок</translation>
-<translation id="4165986682804962316">Налаштування сайту</translation>
+<translation id="4165986682804962316">Налаштування сайтів</translation>
 <translation id="4169549551965910670">Підключено до пристрою USB</translation>
 <translation id="4194328954146351878">Запитувати, перш ніж дозволяти сайтам переглядати й змінювати інформацію на пристроях NFC (рекомендовано)</translation>
 <translation id="4200726100658658164">Відкрити налаштування доступу до моїх геоданих</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
index 4a350f5..65e43ee 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Saytlar atrofingiz 3D xaritasini yaratish yoki kamera holatini kuzatish oldin ruxsat olsin (tavsiya etiladi)</translation>
 <translation id="2212565012507486665">Cookie fayllariga ruxsat berish</translation>
 <translation id="2228071138934252756"><ph name="APP_NAME" /> kameradan foydalanishiga ruxsat berish uchun <ph name="BEGIN_LINK" />Android sozlamalari<ph name="END_LINK" /> orqali kamerani yoqing.</translation>
+<translation id="2238944249568001759">Oxirgi varaq asosida tavsiya etiladigan qidiruvlar</translation>
 <translation id="2241634353105152135">Bir marta</translation>
 <translation id="2253414712144136228">Olib tashlash: <ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">Sayt atrofdagi Bluetooth qurilmalarni tekshirmoqchi boʻlsa, xabar berilsin (tavsiya etiladi)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_vi.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_vi.xtb
index 0e68afa7..6b7baccf 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_vi.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_vi.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Hỏi trước khi cho phép các trang web tạo bản đồ 3D về các khu vực xung quanh bạn hoặc theo dõi thông tin vị trí của máy ảnh (khuyên dùng)</translation>
 <translation id="2212565012507486665">Cho phép cookie</translation>
 <translation id="2228071138934252756">Để cho phép <ph name="APP_NAME" /> truy cập vào máy ảnh của bạn, hãy bật cả máy ảnh trong phần <ph name="BEGIN_LINK" />Cài đặt Android<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Cụm từ tìm kiếm đề xuất dựa trên thẻ gần đây nhất của bạn</translation>
 <translation id="2241634353105152135">Chỉ một lần</translation>
 <translation id="2253414712144136228"><ph name="NAME_OF_LIST_ITEM" /> Xoá</translation>
 <translation id="2289270750774289114">Hỏi khi một trang web muốn tìm các thiết bị Bluetooth ở gần (khuyên dùng)</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb
index 79a12f2aa..842f48d 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb
@@ -49,6 +49,7 @@
 <translation id="2182457891543959921">Buza ngaphambi kokuvumela amasayithi ukudala imephu ye-3D yendawo ekuzungezile noma ukulandelela indawo yekhamera (kuyanconywa)</translation>
 <translation id="2212565012507486665">Vumela amakhukhi</translation>
 <translation id="2228071138934252756">Ukuze uvumele i-<ph name="APP_NAME" /> ifinyelele ikhamera yakho, vula nekhamera <ph name="BEGIN_LINK" />Kumasethingi e-Android<ph name="END_LINK" />.</translation>
+<translation id="2238944249568001759">Usesho oluphakanyisiwe ngokususelwe kuthebhu yakho yokugcina</translation>
 <translation id="2241634353105152135">Kanye nje</translation>
 <translation id="2253414712144136228">Susa i-<ph name="NAME_OF_LIST_ITEM" /></translation>
 <translation id="2289270750774289114">Buza uma isayithi lifuna ukuthola amadivayisi aseduze e-Bluetooth (kunconyiwe)</translation>
diff --git a/components/cast_streaming/browser/cast_streaming_session_unittest.cc b/components/cast_streaming/browser/cast_streaming_session_unittest.cc
index 30f0aef8..81ee8d5 100644
--- a/components/cast_streaming/browser/cast_streaming_session_unittest.cc
+++ b/components/cast_streaming/browser/cast_streaming_session_unittest.cc
@@ -73,10 +73,10 @@
                                                      &receiver_message_port);
 
     receiver_.Start(std::move(receiver_message_port));
-    EXPECT_TRUE(sender_.Start(
-        std::move(sender_message_port), net::IPAddress::IPv6Localhost(),
-        GetDefaultAudioConfig(), GetDefaultVideoConfig()));
-    sender_.RunUntilStarted();
+    sender_.Start(std::move(sender_message_port),
+                  net::IPAddress::IPv6Localhost(), GetDefaultAudioConfig(),
+                  GetDefaultVideoConfig());
+    ASSERT_TRUE(sender_.RunUntilActive());
     receiver_.RunUntilStarted();
   }
 
diff --git a/components/cast_streaming/browser/test/cast_message_port_sender_impl.cc b/components/cast_streaming/browser/test/cast_message_port_sender_impl.cc
index 805c251..1eb8cdde 100644
--- a/components/cast_streaming/browser/test/cast_message_port_sender_impl.cc
+++ b/components/cast_streaming/browser/test/cast_message_port_sender_impl.cc
@@ -15,8 +15,12 @@
 
 CastMessagePortSenderImpl::CastMessagePortSenderImpl(
     std::unique_ptr<cast_api_bindings::MessagePort> message_port,
-    base::OnceClosure on_close)
-    : message_port_(std::move(message_port)), on_close_(std::move(on_close)) {
+    base::OnceClosure on_close,
+    base::OnceClosure on_system_sender_message_received)
+    : message_port_(std::move(message_port)),
+      on_close_(std::move(on_close)),
+      on_system_sender_message_received_(
+          std::move(on_system_sender_message_received)) {
   VLOG(1) << __func__;
   message_port_->SetReceiver(this);
 }
@@ -93,7 +97,14 @@
           << ". Namespace: " << message_namespace
           << ". Message: " << str_message;
 
-  client_->OnMessage(sender_id, message_namespace, str_message);
+  if (message_namespace == kSystemNamespace) {
+    if (on_system_sender_message_received_) {
+      std::move(on_system_sender_message_received_).Run();
+    }
+  } else {
+    client_->OnMessage(sender_id, message_namespace, str_message);
+  }
+
   return true;
 }
 
diff --git a/components/cast_streaming/browser/test/cast_message_port_sender_impl.h b/components/cast_streaming/browser/test/cast_message_port_sender_impl.h
index 88c8f71..8d799ad6 100644
--- a/components/cast_streaming/browser/test/cast_message_port_sender_impl.h
+++ b/components/cast_streaming/browser/test/cast_message_port_sender_impl.h
@@ -20,7 +20,8 @@
  public:
   explicit CastMessagePortSenderImpl(
       std::unique_ptr<cast_api_bindings::MessagePort> message_port,
-      base::OnceClosure on_close);
+      base::OnceClosure on_close,
+      base::OnceClosure on_system_sender_message_received);
   ~CastMessagePortSenderImpl() override;
 
   CastMessagePortSenderImpl(const CastMessagePortSenderImpl&) = delete;
@@ -48,6 +49,7 @@
   raw_ptr<Client> client_ = nullptr;
   std::unique_ptr<cast_api_bindings::MessagePort> message_port_;
   base::OnceClosure on_close_;
+  base::OnceClosure on_system_sender_message_received_;
 };
 
 }  // namespace cast_streaming
diff --git a/components/cast_streaming/browser/test/cast_streaming_test_sender.cc b/components/cast_streaming/browser/test/cast_streaming_test_sender.cc
index 2e3cfb6..464f14c 100644
--- a/components/cast_streaming/browser/test/cast_streaming_test_sender.cc
+++ b/components/cast_streaming/browser/test/cast_streaming_test_sender.cc
@@ -65,13 +65,13 @@
 
 CastStreamingTestSender::~CastStreamingTestSender() = default;
 
-bool CastStreamingTestSender::Start(
+void CastStreamingTestSender::Start(
     std::unique_ptr<cast_api_bindings::MessagePort> message_port,
     net::IPAddress receiver_address,
     absl::optional<media::AudioDecoderConfig> audio_config,
     absl::optional<media::VideoDecoderConfig> video_config) {
   VLOG(1) << __func__;
-  CHECK(!is_active_);
+  CHECK(!has_startup_completed_);
   CHECK(!sender_session_);
   CHECK(audio_config || video_config);
 
@@ -79,6 +79,8 @@
   message_port_ = std::make_unique<CastMessagePortSenderImpl>(
       std::move(message_port),
       base::BindOnce(&CastStreamingTestSender::OnCastChannelClosed,
+                     base::Unretained(this)),
+      base::BindOnce(&CastStreamingTestSender::OnSystemSenderMessageReceived,
                      base::Unretained(this)));
   sender_session_ = std::make_unique<openscreen::cast::SenderSession>(
       openscreen::cast::SenderSession::Configuration{
@@ -86,27 +88,13 @@
           message_port_.get(), kSenderId, kReceiverId,
           true /* use_android_rtp_hack */});
 
-  std::vector<openscreen::cast::AudioCaptureConfig> audio_configs;
   if (audio_config) {
-    audio_configs.push_back(ToAudioCaptureConfig(audio_config.value()));
+    audio_configs_.push_back(ToAudioCaptureConfig(audio_config.value()));
   }
 
-  std::vector<openscreen::cast::VideoCaptureConfig> video_configs;
   if (video_config) {
-    video_configs.push_back(ToVideoCaptureConfig(video_config.value()));
+    video_configs_.push_back(ToVideoCaptureConfig(video_config.value()));
   }
-
-  openscreen::Error error = sender_session_->Negotiate(
-      std::move(audio_configs), std::move(video_configs));
-
-  if (error == openscreen::Error::None()) {
-    return true;
-  }
-
-  LOG(ERROR) << "Failed to start sender session. " << error.ToString();
-  sender_session_.reset();
-  message_port_.reset();
-  return false;
 }
 
 void CastStreamingTestSender::Stop() {
@@ -118,7 +106,7 @@
   video_sender_ = nullptr;
   audio_decoder_config_.reset();
   video_decoder_config_.reset();
-  is_active_ = false;
+  has_startup_completed_ = false;
 
   if (sender_stopped_closure_) {
     std::move(sender_stopped_closure_).Run();
@@ -130,11 +118,14 @@
   VLOG(3) << __func__;
   CHECK(audio_sender_);
 
-  if (audio_sender_->EnqueueFrame(DataBufferToEncodedFrame(
+  openscreen::cast::Sender::EnqueueFrameResult result =
+      audio_sender_->EnqueueFrame(DataBufferToEncodedFrame(
           audio_buffer, true /* is_key_frame */,
           audio_sender_->GetNextFrameId(), &last_audio_reference_frame_id_,
-          audio_sender_->rtp_timebase())) !=
-      openscreen::cast::Sender::EnqueueFrameResult::OK) {
+          audio_sender_->rtp_timebase()));
+
+  if (result != openscreen::cast::Sender::EnqueueFrameResult::OK) {
+    LOG(ERROR) << "Failed to enqueue audio buffer " << result;
     Stop();
   }
 }
@@ -145,27 +136,32 @@
   VLOG(3) << __func__;
   CHECK(video_sender_);
 
-  if (video_sender_->EnqueueFrame(DataBufferToEncodedFrame(
+  openscreen::cast::Sender::EnqueueFrameResult result =
+      video_sender_->EnqueueFrame(DataBufferToEncodedFrame(
           video_buffer, is_key_frame, video_sender_->GetNextFrameId(),
-          &last_video_reference_frame_id_, video_sender_->rtp_timebase())) !=
-      openscreen::cast::Sender::EnqueueFrameResult::OK) {
+          &last_video_reference_frame_id_, video_sender_->rtp_timebase()));
+
+  if (result != openscreen::cast::Sender::EnqueueFrameResult::OK) {
+    LOG(ERROR) << "Failed to enqueue video buffer " << result;
     Stop();
   }
 }
 
-void CastStreamingTestSender::RunUntilStarted() {
+bool CastStreamingTestSender::RunUntilActive() {
   VLOG(1) << __func__;
-  while (!is_active_) {
+  while (!has_startup_completed_) {
     base::RunLoop run_loop;
     CHECK(!sender_started_closure_);
     sender_started_closure_ = run_loop.QuitClosure();
     run_loop.Run();
   }
+
+  return !!sender_session_;
 }
 
 void CastStreamingTestSender::RunUntilStopped() {
   VLOG(1) << __func__;
-  while (is_active_) {
+  while (has_startup_completed_) {
     base::RunLoop run_loop;
     CHECK(!sender_stopped_closure_);
     sender_stopped_closure_ = run_loop.QuitClosure();
@@ -178,6 +174,22 @@
   Stop();
 }
 
+void CastStreamingTestSender::OnSystemSenderMessageReceived() {
+  openscreen::Error error = sender_session_->Negotiate(
+      std::move(audio_configs_), std::move(video_configs_));
+
+  if (error != openscreen::Error::None()) {
+    LOG(ERROR) << "Failed to start sender session. " << error.ToString();
+    sender_session_.reset();
+    message_port_.reset();
+
+    has_startup_completed_ = true;
+    if (sender_started_closure_) {
+      std::move(sender_started_closure_).Run();
+    }
+  }
+}
+
 void CastStreamingTestSender::OnNegotiated(
     const openscreen::cast::SenderSession* session,
     openscreen::cast::SenderSession::ConfiguredSenders senders,
@@ -197,7 +209,7 @@
     video_decoder_config_ = ToVideoDecoderConfig(senders.video_config);
   }
 
-  is_active_ = true;
+  has_startup_completed_ = true;
   if (sender_started_closure_) {
     std::move(sender_started_closure_).Run();
   }
diff --git a/components/cast_streaming/browser/test/cast_streaming_test_sender.h b/components/cast_streaming/browser/test/cast_streaming_test_sender.h
index e9c4dc9..7cc5010e 100644
--- a/components/cast_streaming/browser/test/cast_streaming_test_sender.h
+++ b/components/cast_streaming/browser/test/cast_streaming_test_sender.h
@@ -52,10 +52,10 @@
   CastStreamingTestSender& operator=(const CastStreamingTestSender&) = delete;
 
   // Uses |message_port| as the Sender-end of a Cast Streaming MessagePort to
-  // start a Cast Streaming Session with a Cast Streaming Receiver at
+  // instantiate a Cast Streaming Session with a Cast Streaming Receiver at
   // |receiver_address|. At least one of |audio_config| or |video_config| must
-  // be set. Returns true on success.
-  bool Start(std::unique_ptr<cast_api_bindings::MessagePort> message_port,
+  // be set.
+  void Start(std::unique_ptr<cast_api_bindings::MessagePort> message_port,
              net::IPAddress receiver_address,
              absl::optional<media::AudioDecoderConfig> audio_config,
              absl::optional<media::VideoDecoderConfig> video_config);
@@ -64,21 +64,22 @@
   void Stop();
 
   // Sends |audio_buffer| or |video_buffer| to the Receiver. These can only be
-  // called when is_active() returns true.
+  // called when |has_startup_completed_| is true.
   void SendAudioBuffer(scoped_refptr<media::DataBuffer> audio_buffer);
   void SendVideoBuffer(scoped_refptr<media::DataBuffer> video_buffer,
                        bool is_key_frame);
 
-  // After a successful call to Start(), will run until the Cast Streaming
-  // Sender Session is active. After this call, is_active() will return true
-  // and at least one of audio_decoder_config() or video_decoder_config() will
-  // be set.
-  void RunUntilStarted();
+  // After a call to Start(), will run until the Cast Streaming
+  // Sender Session is active or has failed. After this call,
+  // |has_startup_completed_| will return true. If the session started
+  // successfully, at least one of audio_decoder_config() or
+  // video_decoder_config() will be set, and method will return true. Otherwise
+  // returns false.
+  [[nodiscard]] bool RunUntilActive();
 
-  // Runs until is_active() returns false.
+  // Runs until |has_startup_completed_| is false.
   void RunUntilStopped();
 
-  bool is_active() const { return is_active_; }
   const absl::optional<media::AudioDecoderConfig>& audio_decoder_config()
       const {
     return audio_decoder_config_;
@@ -91,6 +92,10 @@
  private:
   void OnCastChannelClosed();
 
+  // After a system sender message is received, negotiates Cast Streaming Sender
+  // Session with given audio and video configs.
+  void OnSystemSenderMessageReceived();
+
   // openscreen::cast::SenderSession::Client implementation.
   void OnNegotiated(const openscreen::cast::SenderSession* session,
                     openscreen::cast::SenderSession::ConfiguredSenders senders,
@@ -110,13 +115,16 @@
   openscreen::cast::FrameId last_audio_reference_frame_id_;
   openscreen::cast::FrameId last_video_reference_frame_id_;
 
-  bool is_active_ = false;
+  bool has_startup_completed_ = false;
   absl::optional<media::AudioDecoderConfig> audio_decoder_config_;
   absl::optional<media::VideoDecoderConfig> video_decoder_config_;
 
   // Used to implement RunUntilStarted() and RunUntilStopped().
   base::OnceClosure sender_started_closure_;
   base::OnceClosure sender_stopped_closure_;
+
+  std::vector<openscreen::cast::AudioCaptureConfig> audio_configs_;
+  std::vector<openscreen::cast::VideoCaptureConfig> video_configs_;
 };
 
 }  // namespace cast_streaming
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index 7539d7e..267ded3 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "10.19",
-  "log_list_timestamp": "2022-06-21T12:54:51Z",
+  "version": "10.20",
+  "log_list_timestamp": "2022-06-22T12:55:33Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/device_signals/core/common/BUILD.gn b/components/device_signals/core/common/BUILD.gn
index 3d707b7..1dab8096 100644
--- a/components/device_signals/core/common/BUILD.gn
+++ b/components/device_signals/core/common/BUILD.gn
@@ -8,10 +8,25 @@
   sources = [ "signals_constants.cc" ]
 }
 
+source_set("features") {
+  public = [ "signals_features.h" ]
+
+  sources = [ "signals_features.cc" ]
+
+  public_deps = [ "//base" ]
+}
+
 source_set("unit_tests") {
   testonly = true
+  sources = [ "signals_features_unittest.cc" ]
 
+  deps = [
+    ":features",
+    "//base",
+    "//base/test:test_support",
+    "//testing/gtest",
+  ]
   if (is_win) {
-    deps = [ "//components/device_signals/core/common/win:unit_tests" ]
+    deps += [ "//components/device_signals/core/common/win:unit_tests" ]
   }
 }
diff --git a/chrome/browser/enterprise/signals/signals_features.cc b/components/device_signals/core/common/signals_features.cc
similarity index 95%
rename from chrome/browser/enterprise/signals/signals_features.cc
rename to components/device_signals/core/common/signals_features.cc
index ed22aec..4da5464 100644
--- a/chrome/browser/enterprise/signals/signals_features.cc
+++ b/components/device_signals/core/common/signals_features.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 "chrome/browser/enterprise/signals/signals_features.h"
+#include "components/device_signals/core/common/signals_features.h"
 
 namespace enterprise_signals::features {
 
diff --git a/chrome/browser/enterprise/signals/signals_features.h b/components/device_signals/core/common/signals_features.h
similarity index 84%
rename from chrome/browser/enterprise/signals/signals_features.h
rename to components/device_signals/core/common/signals_features.h
index 8b5df77..07bf89d4c5 100644
--- a/chrome/browser/enterprise/signals/signals_features.h
+++ b/components/device_signals/core/common/signals_features.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ENTERPRISE_SIGNALS_SIGNALS_FEATURES_H_
-#define CHROME_BROWSER_ENTERPRISE_SIGNALS_SIGNALS_FEATURES_H_
+#ifndef COMPONENTS_DEVICE_SIGNALS_CORE_COMMON_SIGNALS_FEATURES_H_
+#define COMPONENTS_DEVICE_SIGNALS_CORE_COMMON_SIGNALS_FEATURES_H_
 
 #include "base/feature_list.h"
 #include "base/metrics/field_trial_params.h"
@@ -29,4 +29,4 @@
 
 }  // namespace enterprise_signals::features
 
-#endif  // CHROME_BROWSER_ENTERPRISE_SIGNALS_SIGNALS_FEATURES_H_
+#endif  // COMPONENTS_DEVICE_SIGNALS_CORE_COMMON_SIGNALS_FEATURES_H_
diff --git a/chrome/browser/enterprise/signals/signals_features_unittest.cc b/components/device_signals/core/common/signals_features_unittest.cc
similarity index 97%
rename from chrome/browser/enterprise/signals/signals_features_unittest.cc
rename to components/device_signals/core/common/signals_features_unittest.cc
index 32a171d9..7ecf6d6 100644
--- a/chrome/browser/enterprise/signals/signals_features_unittest.cc
+++ b/components/device_signals/core/common/signals_features_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 "chrome/browser/enterprise/signals/signals_features.h"
+#include "components/device_signals/core/common/signals_features.h"
 
 #include "base/test/scoped_feature_list.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc
index 22b5c89..e8157d6 100644
--- a/components/download/internal/common/download_item_impl.cc
+++ b/components/download/internal/common/download_item_impl.cc
@@ -331,7 +331,6 @@
     bool transient,
     const std::vector<DownloadItem::ReceivedSlice>& received_slices,
     const DownloadItemRerouteInfo& reroute_info,
-    absl::optional<DownloadSchedule> download_schedule,
     int64_t range_request_from,
     int64_t range_request_to,
     std::unique_ptr<DownloadEntry> download_entry)
@@ -377,7 +376,6 @@
       etag_(etag),
       received_slices_(received_slices),
       is_updating_observers_(false),
-      download_schedule_(std::move(download_schedule)),
       reroute_info_(reroute_info) {
   delegate_->Attach();
   DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL ||
@@ -1737,7 +1735,6 @@
     const base::FilePath& intermediate_path,
     const base::FilePath& display_name,
     const std::string& mime_type,
-    absl::optional<DownloadSchedule> download_schedule,
     DownloadInterruptReason interrupt_reason) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   if (state_ == CANCELLED_INTERNAL)
@@ -1760,10 +1757,6 @@
     return;
   }
 
-  if (download_schedule)
-    RecordDownloadLaterEvent(DownloadLaterEvent::kScheduleAdded);
-  SwapDownloadSchedule(std::move(download_schedule));
-
   // There were no other pending errors, and we just failed to determined the
   // download target. The target path, if it is non-empty, should be considered
   // suspect. The safe option here is to interrupt the download without doing an
diff --git a/components/download/internal/common/download_item_impl_delegate.cc b/components/download/internal/common/download_item_impl_delegate.cc
index 9fbe16d..9a6ec97 100644
--- a/components/download/internal/common/download_item_impl_delegate.cc
+++ b/components/download/internal/common/download_item_impl_delegate.cc
@@ -38,8 +38,7 @@
       target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, target_path, base::FilePath(),
-      std::string(), absl::nullopt /*download_schedule*/,
-      DOWNLOAD_INTERRUPT_REASON_NONE);
+      std::string(), DOWNLOAD_INTERRUPT_REASON_NONE);
 }
 
 bool DownloadItemImplDelegate::ShouldCompleteDownload(
diff --git a/components/download/internal/common/download_item_impl_unittest.cc b/components/download/internal/common/download_item_impl_unittest.cc
index bb34780..6c2eea7 100644
--- a/components/download/internal/common/download_item_impl_unittest.cc
+++ b/components/download/internal/common/download_item_impl_unittest.cc
@@ -296,8 +296,7 @@
         download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, reason, false, false,
         false, base::Time::Now(), true,
         std::vector<download::DownloadItem::ReceivedSlice>(), reroute_info,
-        absl::nullopt /*download_schedule*/, kInvalidRange, kInvalidRange,
-        nullptr /* download_entry */);
+        kInvalidRange, kInvalidRange, nullptr /* download_entry */);
     return item;
   }
 
@@ -353,8 +352,7 @@
     EXPECT_TRUE(item->GetTargetFilePath().empty());
     DownloadItemImplDelegate::DownloadTargetCallback callback;
     MockDownloadFile* file = CallDownloadItemStart(item, &callback);
-    DoRenameAndRunTargetCallback(item, file, std::move(callback), danger_type,
-                                 absl::nullopt);
+    DoRenameAndRunTargetCallback(item, file, std::move(callback), danger_type);
     return file;
   }
 
@@ -362,8 +360,7 @@
       DownloadItemImpl* item,
       MockDownloadFile* download_file,
       DownloadItemImplDelegate::DownloadTargetCallback callback,
-      DownloadDangerType danger_type,
-      absl::optional<DownloadSchedule> download_schedule) {
+      DownloadDangerType danger_type) {
     base::FilePath target_path(kDummyTargetPath);
     base::FilePath intermediate_path(kDummyIntermediatePath);
     auto task_runner = base::ThreadTaskRunnerHandle::Get();
@@ -373,7 +370,7 @@
     std::move(callback).Run(
         target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE, danger_type,
         DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
-        base::FilePath(), std::string() /*mime_type*/, download_schedule,
+        base::FilePath(), std::string() /*mime_type*/,
         DOWNLOAD_INTERRUPT_REASON_NONE);
     task_environment_.RunUntilIdle();
   }
@@ -636,7 +633,7 @@
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
       base::FilePath(), std::string() /*mime_type*/,
-      absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+      DOWNLOAD_INTERRUPT_REASON_NONE);
   EXPECT_FALSE(observer.CheckAndResetDownloadUpdated());
   task_environment_.RunUntilIdle();
   EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
@@ -926,7 +923,7 @@
         DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
         DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
         base::FilePath(), std::string() /*mime_type*/,
-        absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+        DOWNLOAD_INTERRUPT_REASON_NONE);
     task_environment_.RunUntilIdle();
 
     // Use a continuable interrupt.
@@ -1020,8 +1017,7 @@
            DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
            DownloadItem::MixedContentStatus::UNKNOWN,
            base::FilePath(kDummyIntermediatePath), base::FilePath(),
-           std::string() /*mime_type*/, absl::nullopt /*download_schedule*/,
-           DOWNLOAD_INTERRUPT_REASON_NONE);
+           std::string() /*mime_type*/, DOWNLOAD_INTERRUPT_REASON_NONE);
   task_environment_.RunUntilIdle();
 
   ASSERT_TRUE(item->GetResponseHeaders());
@@ -1224,7 +1220,7 @@
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
       base::FilePath(), std::string() /*mime_type*/,
-      absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+      DOWNLOAD_INTERRUPT_REASON_NONE);
   task_environment_.RunUntilIdle();
   EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
             item->GetFileNameToReportUser().value());
@@ -1278,8 +1274,7 @@
            DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
            DownloadItem::MixedContentStatus::UNKNOWN,
            base::FilePath(kDummyIntermediatePath), base::FilePath(),
-           std::string() /*mime_type*/, absl::nullopt /*download_schedule*/,
-           DOWNLOAD_INTERRUPT_REASON_NONE);
+           std::string() /*mime_type*/, DOWNLOAD_INTERRUPT_REASON_NONE);
   task_environment_.RunUntilIdle();
 
   EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
@@ -1323,7 +1318,7 @@
            DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
            DownloadItem::MixedContentStatus::UNKNOWN, target_path,
            base::FilePath(), std::string() /*mime_type*/,
-           absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+           DOWNLOAD_INTERRUPT_REASON_NONE);
   task_environment_.RunUntilIdle();
 
   // Interrupt reason carried in create info should be recorded.
@@ -1355,7 +1350,7 @@
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
       base::FilePath(), std::string() /*mime_type*/,
-      absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+      DOWNLOAD_INTERRUPT_REASON_NONE);
   task_environment_.RunUntilIdle();
   // All the callbacks should have happened by now.
   ::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1406,7 +1401,7 @@
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
       base::FilePath(), std::string() /*mime_type*/,
-      absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+      DOWNLOAD_INTERRUPT_REASON_NONE);
   task_environment_.RunUntilIdle();
   // All the callbacks should have happened by now.
   ::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1472,7 +1467,7 @@
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
       base::FilePath(), std::string() /*mime_type*/,
-      absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+      DOWNLOAD_INTERRUPT_REASON_NONE);
   task_environment_.RunUntilIdle();
   // All the callbacks should have happened by now.
   ::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1519,7 +1514,7 @@
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
       base::FilePath(), std::string() /*mime_type*/,
-      absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+      DOWNLOAD_INTERRUPT_REASON_NONE);
   task_environment_.RunUntilIdle();
   // All the callbacks should have happened by now.
   ::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1561,7 +1556,7 @@
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
       base::FilePath(), std::string() /*mime_type*/,
-      absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+      DOWNLOAD_INTERRUPT_REASON_NONE);
   task_environment_.RunUntilIdle();
   // All the callbacks should have happened by now.
   ::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1605,7 +1600,6 @@
                           DownloadItem::MixedContentStatus::UNKNOWN,
                           base::FilePath(FILE_PATH_LITERAL("bar")),
                           base::FilePath(), std::string() /*mime_type*/,
-                          absl::nullopt /*download_schedule*/,
                           DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
   EXPECT_EQ(DownloadItem::CANCELLED, item->GetState());
 }
@@ -1621,7 +1615,7 @@
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, base::FilePath(),
       base::FilePath(), std::string() /*mime_type*/,
-      absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+      DOWNLOAD_INTERRUPT_REASON_NONE);
   EXPECT_EQ(DownloadItem::CANCELLED, item->GetState());
 }
 
@@ -1636,7 +1630,7 @@
       target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, target_path, base::FilePath(),
-      std::string() /*mime_type*/, absl::nullopt /*download_schedule*/,
+      std::string() /*mime_type*/,
       DOWNLOAD_INTERRUPT_REASON_FILE_SAME_AS_SOURCE);
   EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
   EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_SAME_AS_SOURCE,
@@ -1658,8 +1652,7 @@
       target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
       DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
       DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
-      base::FilePath(), mime_type, absl::nullopt /*download_schedule*/,
-      DOWNLOAD_INTERRUPT_REASON_NONE);
+      base::FilePath(), mime_type, DOWNLOAD_INTERRUPT_REASON_NONE);
   EXPECT_EQ(mime_type, item->GetMimeType());
   CleanupItem(item, file, DownloadItem::IN_PROGRESS);
 }
@@ -2526,7 +2519,7 @@
            DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
            DownloadItem::MixedContentStatus::UNKNOWN, base::FilePath(),
            base::FilePath(), std::string() /*mime_type*/,
-           absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+           DOWNLOAD_INTERRUPT_REASON_NONE);
   EXPECT_EQ(DownloadItem::CANCELLED, item_->GetState());
   EXPECT_TRUE(canceled());
   task_environment_.RunUntilIdle();
@@ -2576,8 +2569,7 @@
            DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
            DownloadItem::MixedContentStatus::UNKNOWN,
            base::FilePath(kDummyIntermediatePath), base::FilePath(),
-           std::string() /*mime_type*/, absl::nullopt /*download_schedule*/,
-           DOWNLOAD_INTERRUPT_REASON_NONE);
+           std::string() /*mime_type*/, DOWNLOAD_INTERRUPT_REASON_NONE);
 
   task_environment_.RunUntilIdle();
   ASSERT_FALSE(intermediate_rename_callback.is_null());
@@ -2642,8 +2634,7 @@
            DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
            DownloadItem::MixedContentStatus::UNKNOWN,
            base::FilePath(kDummyIntermediatePath), base::FilePath(),
-           std::string() /*mime_type*/, absl::nullopt /*download_schedule*/,
-           DOWNLOAD_INTERRUPT_REASON_NONE);
+           std::string() /*mime_type*/, DOWNLOAD_INTERRUPT_REASON_NONE);
 
   task_environment_.RunUntilIdle();
   ASSERT_FALSE(intermediate_rename_callback.is_null());
@@ -2674,139 +2665,6 @@
   task_environment_.RunUntilIdle();
 }
 
-// --------------------------------------------------------------
-// Download later feature test.
-struct DownloadLaterTestParam {
-  // Input to build DownloadSchedule and config network type.
-  bool only_on_wifi;
-  absl::optional<base::Time> start_time;
-  bool is_active_network_metered;
-
-  // Output and expectation.
-  DownloadItem::DownloadState state;
-  bool allow_metered;
-};
-
-std::vector<DownloadLaterTestParam> DownloadLaterTestParams() {
-  std::vector<DownloadLaterTestParam> params;
-  // Required wifi, and currently on wifi, the download won't stop.
-  params.push_back(
-      {true, absl::nullopt, false, DownloadItem::IN_PROGRESS, false});
-  // Don't require wifi, and currently not on wifi, the download won't stop.
-  params.push_back(
-      {false, absl::nullopt, true, DownloadItem::IN_PROGRESS, true});
-  // Download later, will be interrupted.
-  auto future_time = base::Time::Now() + base::Days(10);
-  params.push_back({false, future_time, true, DownloadItem::INTERRUPTED, true});
-  return params;
-}
-
-class DownloadLaterTest
-    : public DownloadItemTest,
-      public ::testing::WithParamInterface<DownloadLaterTestParam> {
- public:
-  DownloadLaterTest() = default;
-  ~DownloadLaterTest() override = default;
-};
-
-INSTANTIATE_TEST_SUITE_P(All,
-                         DownloadLaterTest,
-                         testing::ValuesIn(DownloadLaterTestParams()));
-
-TEST_P(DownloadLaterTest, TestDownloadScheduleAfterTargetDetermined) {
-  const auto& param = GetParam();
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kDownloadLater);
-
-  DownloadItemImpl* item = CreateDownloadItem();
-
-  // Setup network type and download schedule.
-  EXPECT_CALL(*mock_delegate(), IsActiveNetworkMetered)
-      .WillRepeatedly(Return(param.is_active_network_metered));
-  EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
-  EXPECT_TRUE(item->GetTargetFilePath().empty());
-  DownloadItemImplDelegate::DownloadTargetCallback callback;
-  MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
-
-  if (param.state == DownloadItem::INTERRUPTED) {
-    EXPECT_CALL(*download_file, Detach());
-  }
-
-  absl::optional<DownloadSchedule> download_schedule =
-      absl::make_optional<DownloadSchedule>(param.only_on_wifi,
-                                            param.start_time);
-
-  DoRenameAndRunTargetCallback(item, download_file, std::move(callback),
-                               DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
-                               std::move(download_schedule));
-
-  // Verify final states.
-  ASSERT_EQ(param.allow_metered, item->AllowMetered());
-  ASSERT_EQ(param.state, item->GetState());
-  ASSERT_EQ(0, item->GetAutoResumeCount())
-      << "Download should not be auto resumed with DownloadSchedule.";
-  if (param.state == DownloadItem::INTERRUPTED) {
-    ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_CRASH, item->GetLastReason());
-  }
-
-  if (param.state == DownloadItem::IN_PROGRESS) {
-    EXPECT_FALSE(item->GetDownloadSchedule().has_value())
-        << "Download schedule should be cleared before completion.";
-  }
-
-  CleanupItem(item, download_file, param.state);
-}
-
-TEST_P(DownloadLaterTest, TestOnDownloadScheduleChanged) {
-  const auto& param = GetParam();
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kDownloadLater);
-
-  auto item = CreateDownloadItem(DownloadItem::DownloadState::INTERRUPTED,
-                                 DOWNLOAD_INTERRUPT_REASON_CRASH);
-  EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
-
-  // Setup network type and download schedule.
-  EXPECT_CALL(*mock_delegate(), IsActiveNetworkMetered)
-      .WillRepeatedly(Return(param.is_active_network_metered));
-
-  bool will_resume = (param.state == DownloadItem::DownloadState::IN_PROGRESS);
-  EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_))
-      .Times(will_resume);
-
-  // Change the download schedule.
-  absl::optional<DownloadSchedule> download_schedule =
-      absl::make_optional<DownloadSchedule>(param.only_on_wifi,
-                                            param.start_time);
-
-  item->OnDownloadScheduleChanged(std::move(download_schedule));
-
-  // Verify final states.
-  ASSERT_EQ(param.allow_metered, item->AllowMetered());
-  ASSERT_EQ(param.state, item->GetState());
-  ASSERT_EQ(0, item->GetAutoResumeCount())
-      << "Download should not be auto resumed with DownloadSchedule.";
-  if (param.state == DownloadItem::INTERRUPTED) {
-    ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_CRASH, item->GetLastReason());
-  }
-}
-
-TEST_F(DownloadItemTest, CancelWithDownloadSchedule) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kDownloadLater);
-
-  auto item = CreateDownloadItem(DownloadItem::DownloadState::INTERRUPTED,
-                                 DOWNLOAD_INTERRUPT_REASON_CRASH);
-  auto download_schedule = absl::make_optional<DownloadSchedule>(
-      false, base::Time::Now() + base::Days(10));
-  item->OnDownloadScheduleChanged(std::move(download_schedule));
-
-  EXPECT_EQ(item->GetState(), DownloadItem::DownloadState::INTERRUPTED);
-  EXPECT_TRUE(item->GetDownloadSchedule().has_value());
-  item->Cancel(true);
-  EXPECT_FALSE(item->GetDownloadSchedule().has_value());
-}
-
 TEST_F(DownloadItemTest, ExternalRenameHandler) {
   using ProgressUpdate = DownloadItemRenameProgressUpdate;
   using UpdateCallback = DownloadItemRenameHandler::ProgressUpdateCallback;
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc
index f89e5056..b3d6aded 100644
--- a/components/download/internal/common/in_progress_download_manager.cc
+++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -70,9 +70,8 @@
       in_progress_info->danger_type, in_progress_info->interrupt_reason,
       in_progress_info->paused, in_progress_info->metered, false, base::Time(),
       in_progress_info->transient, in_progress_info->received_slices,
-      in_progress_info->reroute_info, in_progress_info->download_schedule,
-      in_progress_info->range_request_from, in_progress_info->range_request_to,
-      std::move(download_entry));
+      in_progress_info->reroute_info, in_progress_info->range_request_from,
+      in_progress_info->range_request_to, std::move(download_entry));
 }
 
 void OnUrlDownloadHandlerCreated(
@@ -162,7 +161,6 @@
                     const InProgressDownloadManager::IntermediatePathCallback&
                         intermediate_path_cb,
                     const base::FilePath& forced_file_path,
-                    absl::optional<DownloadSchedule> download_schedule,
                     PathValidationResult result,
                     const base::FilePath& target_path) {
   base::FilePath intermediate_path;
@@ -184,7 +182,7 @@
   std::move(callback).Run(
       target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE, danger_type,
       mixed_content_status, intermediate_path, base::FilePath(),
-      std::string() /*mime_type*/, std::move(download_schedule),
+      std::string() /*mime_type*/,
       intermediate_path.empty() ? DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
                                 : DOWNLOAD_INTERRUPT_REASON_NONE);
 }
@@ -405,7 +403,7 @@
         target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
         download->GetDangerType(), download->GetMixedContentStatus(),
         target_path, base::FilePath(), std::string() /*mime_type*/,
-        download->GetDownloadSchedule(), DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
+        DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
     RecordBackgroundTargetDeterminationResult(
         BackgroudTargetDeterminationResultTypes::kTargetPathMissing);
     return;
@@ -418,7 +416,7 @@
         target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
         download->GetDangerType(), download->GetMixedContentStatus(),
         target_path, base::FilePath(), std::string() /*mime_type*/,
-        download->GetDownloadSchedule(), DOWNLOAD_INTERRUPT_REASON_NONE);
+        DOWNLOAD_INTERRUPT_REASON_NONE);
     RecordBackgroundTargetDeterminationResult(
         BackgroudTargetDeterminationResultTypes::kSuccess);
     return;
@@ -430,10 +428,10 @@
       download->GetForcedFilePath().empty()
           ? DownloadPathReservationTracker::UNIQUIFY
           : DownloadPathReservationTracker::OVERWRITE,
-      base::BindOnce(
-          &OnPathReserved, std::move(callback), download->GetDangerType(),
-          download->GetMixedContentStatus(), intermediate_path_cb_,
-          download->GetForcedFilePath(), download->GetDownloadSchedule()));
+      base::BindOnce(&OnPathReserved, std::move(callback),
+                     download->GetDangerType(),
+                     download->GetMixedContentStatus(), intermediate_path_cb_,
+                     download->GetForcedFilePath()));
 #else
   // For non-android, the code below is only used by tests.
   base::FilePath intermediate_path =
@@ -442,7 +440,7 @@
       target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
       download->GetDangerType(), download->GetMixedContentStatus(),
       intermediate_path, base::FilePath(), std::string() /*mime_type*/,
-      download->GetDownloadSchedule(), DOWNLOAD_INTERRUPT_REASON_NONE);
+      DOWNLOAD_INTERRUPT_REASON_NONE);
 #endif  // BUILDFLAG(IS_ANDROID)
 }
 
diff --git a/components/download/public/common/download_item_impl.h b/components/download/public/common/download_item_impl.h
index 185b14c..a15ca896 100644
--- a/components/download/public/common/download_item_impl.h
+++ b/components/download/public/common/download_item_impl.h
@@ -218,7 +218,6 @@
       bool transient,
       const std::vector<DownloadItem::ReceivedSlice>& received_slices,
       const DownloadItemRerouteInfo& reroute_info,
-      absl::optional<DownloadSchedule> download_schedule,
       int64_t range_request_from,
       int64_t range_request_to,
       std::unique_ptr<DownloadEntry> download_entry);
@@ -604,7 +603,6 @@
       const base::FilePath& intermediate_path,
       const base::FilePath& display_name,
       const std::string& mime_type,
-      absl::optional<DownloadSchedule> download_schedule,
       DownloadInterruptReason interrupt_reason);
 
   void OnDownloadRenamedToIntermediateName(DownloadInterruptReason reason,
diff --git a/components/download/public/common/download_item_impl_delegate.h b/components/download/public/common/download_item_impl_delegate.h
index 99b631c..331c0f4 100644
--- a/components/download/public/common/download_item_impl_delegate.h
+++ b/components/download/public/common/download_item_impl_delegate.h
@@ -14,7 +14,6 @@
 #include "components/download/public/common/download_export.h"
 #include "components/download/public/common/download_item.h"
 #include "components/download/public/common/download_item_rename_handler.h"
-#include "components/download/public/common/download_schedule.h"
 #include "components/download/public/common/download_url_parameters.h"
 #include "components/download/public/common/quarantine_connection.h"
 #include "components/services/quarantine/public/mojom/quarantine.mojom.h"
@@ -54,7 +53,6 @@
       const base::FilePath& intermediate_path,
       const base::FilePath& display_name,
       const std::string& mime_type,
-      absl::optional<DownloadSchedule> download_schedule,
       DownloadInterruptReason interrupt_reason)>;
   // Request determination of the download target from the delegate.
   virtual void DetermineDownloadTarget(DownloadItemImpl* download,
diff --git a/components/download/public/common/mock_download_item_impl.cc b/components/download/public/common/mock_download_item_impl.cc
index f929a37f..eabcb33 100644
--- a/components/download/public/common/mock_download_item_impl.cc
+++ b/components/download/public/common/mock_download_item_impl.cc
@@ -38,7 +38,6 @@
                        true,
                        DownloadItem::ReceivedSlices(),
                        DownloadItemRerouteInfo(),
-                       absl::nullopt /*download_schedule*/,
                        kInvalidRange,
                        kInvalidRange,
                        nullptr /* download_entry */) {}
diff --git a/components/download/public/common/mock_download_item_impl.h b/components/download/public/common/mock_download_item_impl.h
index ace02f3..83f5d38 100644
--- a/components/download/public/common/mock_download_item_impl.h
+++ b/components/download/public/common/mock_download_item_impl.h
@@ -27,7 +27,7 @@
   explicit MockDownloadItemImpl(DownloadItemImplDelegate* delegate);
   ~MockDownloadItemImpl() override;
 
-  MOCK_METHOD9(OnDownloadTargetDetermined,
+  MOCK_METHOD8(OnDownloadTargetDetermined,
                void(const base::FilePath&,
                     TargetDisposition,
                     DownloadDangerType,
@@ -35,7 +35,6 @@
                     const base::FilePath&,
                     const base::FilePath&,
                     const std::string&,
-                    absl::optional<DownloadSchedule>,
                     DownloadInterruptReason));
   MOCK_METHOD1(AddObserver, void(DownloadItem::Observer*));
   MOCK_METHOD1(RemoveObserver, void(DownloadItem::Observer*));
diff --git a/components/embedder_support/user_agent_utils.cc b/components/embedder_support/user_agent_utils.cc
index acd6038..5ceb4b3 100644
--- a/components/embedder_support/user_agent_utils.cc
+++ b/components/embedder_support/user_agent_utils.cc
@@ -361,6 +361,21 @@
   }
 }
 
+// Internal function to handle return the full or "reduced" user agent string,
+// depending on the UserAgentReduction enterprise policy.
+std::string GetUserAgentInternal(
+    ForceMajorVersionToMinorPosition force_major_to_minor,
+    UserAgentReductionEnterprisePolicyState user_agent_reduction) {
+  std::string product =
+      GetProductAndVersion(force_major_to_minor, user_agent_reduction);
+#if BUILDFLAG(IS_ANDROID)
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kUseMobileUserAgent))
+    product += " Mobile";
+#endif
+  return content::BuildUserAgentFromProduct(product);
+}
+
 std::string GetUserAgent(
     ForceMajorVersionToMinorPosition force_major_to_minor,
     UserAgentReductionEnterprisePolicyState user_agent_reduction) {
@@ -373,12 +388,12 @@
   }
 
   if (base::FeatureList::IsEnabled(blink::features::kFullUserAgent))
-    return GetFullUserAgent();
+    return GetFullUserAgent(force_major_to_minor);
 
   if (base::FeatureList::IsEnabled(blink::features::kReduceUserAgent))
     return GetReducedUserAgent(force_major_to_minor);
 
-  return GetFullUserAgent(force_major_to_minor, user_agent_reduction);
+  return GetUserAgentInternal(force_major_to_minor, user_agent_reduction);
 }
 
 std::string GetReducedUserAgent(
@@ -390,16 +405,10 @@
 }
 
 std::string GetFullUserAgent(
-    ForceMajorVersionToMinorPosition force_major_to_minor,
-    UserAgentReductionEnterprisePolicyState user_agent_reduction) {
-  std::string product =
-      GetProductAndVersion(force_major_to_minor, user_agent_reduction);
-#if BUILDFLAG(IS_ANDROID)
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kUseMobileUserAgent))
-    product += " Mobile";
-#endif
-  return content::BuildUserAgentFromProduct(product);
+    ForceMajorVersionToMinorPosition force_major_to_minor) {
+  return GetUserAgentInternal(
+      force_major_to_minor,
+      UserAgentReductionEnterprisePolicyState::kForceDisabled);
 }
 
 // Generate a pseudo-random permutation of the following brand/version pairs:
diff --git a/components/embedder_support/user_agent_utils.h b/components/embedder_support/user_agent_utils.h
index bf6db619..791fdd72 100644
--- a/components/embedder_support/user_agent_utils.h
+++ b/components/embedder_support/user_agent_utils.h
@@ -54,13 +54,11 @@
     UserAgentReductionEnterprisePolicyState user_agent_reduction =
         UserAgentReductionEnterprisePolicyState::kDefault);
 
-// Returns the user agent string for Chrome.
+// Returns the full user agent string for Chrome.
 // TODO(crbug.com/1291612): modify to accept an optional PrefService*.
 std::string GetFullUserAgent(
     ForceMajorVersionToMinorPosition force_major_to_minor =
-        ForceMajorVersionToMinorPosition::kDefault,
-    UserAgentReductionEnterprisePolicyState user_agent_reduction =
-        UserAgentReductionEnterprisePolicyState::kDefault);
+        ForceMajorVersionToMinorPosition::kDefault);
 
 // Returns the reduced user agent string for Chrome.
 // TODO(crbug.com/1291612): modify to accept an optional PrefService*.
@@ -68,8 +66,10 @@
     ForceMajorVersionToMinorPosition force_major_to_minor =
         ForceMajorVersionToMinorPosition::kDefault);
 
-// Returns the full or "reduced" user agent string, depending on the
-// UserAgentReduction enterprise policy and blink::features::kReduceUserAgent
+// Returns the full or "reduced" user agent string, depending on the following:
+// 1) UserAgentReduction enterprise policy.
+// 2) blink::features::kReduceUserAgent: reduced-user-agent about flag.
+// 3) blink::features::kFullUserAgent: full-user-agent about flag.
 // TODO(crbug.com/1291612): modify to accept an optional PrefService*.
 std::string GetUserAgent(
     ForceMajorVersionToMinorPosition force_major_to_minor =
diff --git a/components/embedder_support/user_agent_utils_unittest.cc b/components/embedder_support/user_agent_utils_unittest.cc
index d8e0413..9e01bc7 100644
--- a/components/embedder_support/user_agent_utils_unittest.cc
+++ b/components/embedder_support/user_agent_utils_unittest.cc
@@ -325,6 +325,15 @@
 class UserAgentUtilsTest : public testing::Test,
                            public testing::WithParamInterface<bool> {
  public:
+  // The minor version in the reduced UA string is always "0.0.0".
+  static constexpr char kReducedMinorVersion[] = "0.0.0";
+  // The minor version in the ReduceUserAgentMinorVersion experiment is always
+  // "0.X.0", where X is the frozen build version.
+  const std::string kReduceUserAgentMinorVersion =
+      "0." +
+      std::string(blink::features::kUserAgentFrozenBuildVersion.Get().data()) +
+      ".0";
+
   std::string MajorToMinorVersionNumber() {
     const base::Version version = version_info::GetVersion();
     std::string version_str;
@@ -342,6 +351,46 @@
     return version_str;
   }
 
+  std::string GetUserAgentMinorVersion(const std::string& user_agent_value) {
+    // A regular expression that matches Chrome/{major_version}.{minor_version}
+    // in the User-Agent string, where the {minor_version} is captured.
+    static constexpr char kChromeVersionRegex[] =
+        "Chrome/[0-9]+\\.([0-9]+\\.[0-9]+\\.[0-9]+)";
+    std::string minor_version;
+    EXPECT_TRUE(re2::RE2::PartialMatch(user_agent_value, kChromeVersionRegex,
+                                       &minor_version));
+    return minor_version;
+  }
+
+  void VerifyFullUserAgent() {
+    EXPECT_EQ(
+        GetUserAgent(ForceMajorVersionToMinorPosition::kForceEnabled),
+        GetFullUserAgent(ForceMajorVersionToMinorPosition::kForceEnabled));
+    EXPECT_EQ(
+        GetUserAgent(ForceMajorVersionToMinorPosition::kForceDisabled),
+        GetFullUserAgent(ForceMajorVersionToMinorPosition::kForceDisabled));
+    EXPECT_EQ(GetUserAgent(), GetFullUserAgent());
+    EXPECT_NE(GetUserAgentMinorVersion(GetFullUserAgent()),
+              kReducedMinorVersion);
+  }
+
+  void VerifyGetUserAgentFunctions() {
+    // 1) GetUserAgent should return user agent depends on
+    // kReduceUserAgentMinorVersion feature.
+    // 2) GetReducedUserAgent should return reduced user agent.
+    // 3) GetFullUserAgent should return full user agent.
+    if (base::FeatureList::IsEnabled(
+            blink::features::kReduceUserAgentMinorVersion)) {
+      EXPECT_EQ(GetUserAgentMinorVersion(GetUserAgent()), kReducedMinorVersion);
+    } else {
+      EXPECT_NE(GetUserAgentMinorVersion(GetUserAgent()), kReducedMinorVersion);
+    }
+    EXPECT_EQ(GetUserAgentMinorVersion(GetReducedUserAgent()),
+              kReducedMinorVersion);
+    EXPECT_NE(GetUserAgentMinorVersion(GetFullUserAgent()),
+              kReducedMinorVersion);
+  }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
 };
@@ -489,7 +538,7 @@
       {blink::features::kFullUserAgent,
        blink::features::kForceMajorVersionInMinorPositionInUserAgent},
       {});
-  { EXPECT_EQ(GetUserAgent(), GetFullUserAgent()); }
+  { VerifyFullUserAgent(); }
 
   // Verify that the full user agent string when both reduced and full UA
   // feature enabled respects
@@ -499,7 +548,36 @@
       {blink::features::kFullUserAgent, blink::features::kReduceUserAgent,
        blink::features::kForceMajorVersionInMinorPositionInUserAgent},
       {});
-  { EXPECT_EQ(GetUserAgent(), GetFullUserAgent()); }
+  { VerifyFullUserAgent(); }
+
+  // Verify that the full user agent string still returns the full user agent
+  // even turns on kReduceUserAgentMinorVersion
+  scoped_feature_list.Reset();
+  scoped_feature_list.InitWithFeatures(
+      {blink::features::kFullUserAgent,
+       blink::features::kReduceUserAgentMinorVersion},
+      {});
+  { VerifyFullUserAgent(); }
+
+  // Verify that three user agent functions return the correct user agent string
+  // when kReduceUserAgentMinorVersion turns on.
+  scoped_feature_list.Reset();
+  scoped_feature_list.InitWithFeatures(
+      {blink::features::kReduceUserAgentMinorVersion}, {});
+  { VerifyGetUserAgentFunctions(); }
+
+  // Verify that three user agent functions return the correct user agent
+  // when kReduceUserAgentMinorVersion turns off.
+  scoped_feature_list.Reset();
+  scoped_feature_list.InitWithFeatures(
+      {}, {blink::features::kReduceUserAgentMinorVersion});
+  { VerifyGetUserAgentFunctions(); }
+
+  // Verify that three user agent functions return the correct user agent
+  // without explicit features turn on.
+  scoped_feature_list.Reset();
+  scoped_feature_list.InitWithFeatures({}, {});
+  { VerifyGetUserAgentFunctions(); }
 }
 
 TEST_F(UserAgentUtilsTest, UserAgentMetadata) {
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index e7bf750e..804b7f8 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -30,8 +30,6 @@
     "buffer.h",
     "capabilities.cc",
     "capabilities.h",
-    "common_utils.cc",
-    "common_utils.h",
     "data_device.cc",
     "data_device.h",
     "data_device_delegate.h",
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc
index 3a52741b..ec4b4b7 100644
--- a/components/exo/buffer.cc
+++ b/components/exo/buffer.cc
@@ -508,6 +508,8 @@
                                                   sync_token, texture_target_);
     resource->is_overlay_candidate = is_overlay_candidate_;
     resource->format = viz::GetResourceFormat(gpu_memory_buffer_->GetFormat());
+    resource->synchronization_type =
+        viz::TransferableResource::SynchronizationType::kReleaseFence;
 
     // The contents texture will be released when no longer used by the
     // compositor.
diff --git a/components/exo/common_utils.cc b/components/exo/common_utils.cc
deleted file mode 100644
index 48dcfc7..0000000
--- a/components/exo/common_utils.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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/exo/common_utils.h"
-
-#include "base/logging.h"
-
-#if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_platform.h"
-#endif
-
-namespace exo {
-
-bool IsDrmAtomicAvailable() {
-#if defined(USE_OZONE)
-  auto& host_properties =
-      ui::OzonePlatform::GetInstance()->GetPlatformRuntimeProperties();
-  return host_properties.supports_overlays;
-#else
-  LOG(WARNING) << "Ozone disabled, cannot determine whether DrmAtomic is "
-                  "present. Assuming it is not";
-  return false;
-#endif
-}
-
-}  // namespace exo
diff --git a/components/exo/common_utils.h b/components/exo/common_utils.h
deleted file mode 100644
index 175b69b..0000000
--- a/components/exo/common_utils.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// 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_EXO_COMMON_UTILS_H_
-#define COMPONENTS_EXO_COMMON_UTILS_H_
-
-namespace exo {
-
-bool IsDrmAtomicAvailable();
-
-}  // namespace exo
-
-#endif  // COMPONENTS_EXO_COMMON_UTILS_H_
diff --git a/components/exo/layer_tree_frame_sink_holder.cc b/components/exo/layer_tree_frame_sink_holder.cc
index 4d0e604..11f20135 100644
--- a/components/exo/layer_tree_frame_sink_holder.cc
+++ b/components/exo/layer_tree_frame_sink_holder.cc
@@ -4,7 +4,6 @@
 
 #include "components/exo/layer_tree_frame_sink_holder.h"
 
-#include "base/bind.h"
 #include "base/containers/contains.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/trees/layer_tree_frame_sink.h"
@@ -12,9 +11,6 @@
 #include "components/viz/common/frame_timing_details.h"
 #include "components/viz/common/hit_test/hit_test_region_list.h"
 #include "components/viz/common/resources/returned_resource.h"
-#include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "ui/gfx/gpu_fence.h"
 
 namespace exo {
 
@@ -23,13 +19,9 @@
 
 LayerTreeFrameSinkHolder::LayerTreeFrameSinkHolder(
     SurfaceTreeHost* surface_tree_host,
-    std::unique_ptr<cc::LayerTreeFrameSink> frame_sink,
-    scoped_refptr<viz::ContextProvider> context_provider)
+    std::unique_ptr<cc::LayerTreeFrameSink> frame_sink)
     : surface_tree_host_(surface_tree_host),
-      frame_sink_(std::move(frame_sink)),
-      context_provider_(context_provider),
-      use_gpu_fence_(
-          context_provider_->ContextCapabilities().chromium_gpu_fence) {
+      frame_sink_(std::move(frame_sink)) {
   frame_sink_->BindToClient(this);
 }
 
@@ -118,19 +110,17 @@
 
 void LayerTreeFrameSinkHolder::ReclaimResources(
     std::vector<viz::ReturnedResource> resources) {
-  if (!use_gpu_fence_) {
-    ReclaimResourcesInternal(std::move(resources), nullptr);
-    return;
+  for (auto& resource : resources) {
+    // Skip resources that are also in last frame. This can happen if
+    // the frame sink id changed.
+    if (base::Contains(last_frame_resources_, resource.id)) {
+      continue;
+    }
+    resource_manager_.ReclaimResource(std::move(resource));
   }
 
-  // See the comment at ReclaimResourcesInternal's declaration.
-  gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
-  auto gpu_fence_id = gles2->CreateGpuFenceCHROMIUM();
-  context_provider_->ContextSupport()->GetGpuFence(
-      gpu_fence_id,
-      base::BindOnce(&LayerTreeFrameSinkHolder::ReclaimResourcesInternal,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(resources)));
-  gles2->DestroyGpuFenceCHROMIUM(gpu_fence_id);
+  if (lifetime_manager_ && resource_manager_.HasNoCallbacks())
+    ScheduleDelete();
 }
 
 void LayerTreeFrameSinkHolder::DidReceiveCompositorFrameAck() {
@@ -176,24 +166,4 @@
   ScheduleDelete();
 }
 
-void LayerTreeFrameSinkHolder::ReclaimResourcesInternal(
-    std::vector<viz::ReturnedResource> resources,
-    std::unique_ptr<gfx::GpuFence> release_fence) {
-  for (auto& resource : resources) {
-    // Skip resources that are also in last frame. This can happen if
-    // the frame sink id changed.
-    if (base::Contains(last_frame_resources_, resource.id)) {
-      continue;
-    }
-
-    if (resource.release_fence.is_null() && release_fence)
-      resource.release_fence = release_fence->GetGpuFenceHandle().Clone();
-
-    resource_manager_.ReclaimResource(std::move(resource));
-  }
-
-  if (lifetime_manager_ && resource_manager_.HasNoCallbacks())
-    ScheduleDelete();
-}
-
 }  // namespace exo
diff --git a/components/exo/layer_tree_frame_sink_holder.h b/components/exo/layer_tree_frame_sink_holder.h
index 0c16a62f..7f260f56 100644
--- a/components/exo/layer_tree_frame_sink_holder.h
+++ b/components/exo/layer_tree_frame_sink_holder.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/memory/weak_ptr.h"
 #include "cc/trees/layer_tree_frame_sink_client.h"
 #include "components/exo/frame_sink_resource_manager.h"
 #include "components/exo/wm_helper.h"
@@ -15,14 +14,9 @@
 #include "components/viz/common/resources/release_callback.h"
 
 namespace viz {
-class ContextProvider;
 struct FrameTimingDetails;
 }
 
-namespace gfx {
-class GpuFence;
-}
-
 namespace cc {
 class LayerTreeFrameSink;
 }
@@ -36,10 +30,8 @@
 class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient,
                                  public WMHelper::LifetimeManager::Observer {
  public:
-  LayerTreeFrameSinkHolder(
-      SurfaceTreeHost* surface_tree_host,
-      std::unique_ptr<cc::LayerTreeFrameSink> frame_sink,
-      scoped_refptr<viz::ContextProvider> context_provider);
+  LayerTreeFrameSinkHolder(SurfaceTreeHost* surface_tree_host,
+                           std::unique_ptr<cc::LayerTreeFrameSink> frame_sink);
 
   LayerTreeFrameSinkHolder(const LayerTreeFrameSinkHolder&) = delete;
   LayerTreeFrameSinkHolder& operator=(const LayerTreeFrameSinkHolder&) = delete;
@@ -86,17 +78,8 @@
   // WMHelper::LifetimeManager::Observer:
   void OnDestroyed() override;
 
-  // |release_fence| is a fence that is created when ReclaimResources call comes
-  // and that is used for those resources that do not have fences. That
-  // happens when resources are not overlaid, but rather composited.
-  // TODO(crbug.com/1310136): this should be managed by SkiaRenderer instead.
-  void ReclaimResourcesInternal(std::vector<viz::ReturnedResource> resources,
-                                std::unique_ptr<gfx::GpuFence> release_fence);
-
   SurfaceTreeHost* surface_tree_host_;
   std::unique_ptr<cc::LayerTreeFrameSink> frame_sink_;
-  scoped_refptr<viz::ContextProvider> context_provider_;
-  const bool use_gpu_fence_;
 
   FrameSinkResourceManager resource_manager_;
 
@@ -109,8 +92,6 @@
   bool delete_pending_ = false;
 
   WMHelper::LifetimeManager* lifetime_manager_ = nullptr;
-
-  base::WeakPtrFactory<LayerTreeFrameSinkHolder> weak_ptr_factory_{this};
 };
 
 }  // namespace exo
diff --git a/components/exo/surface_tree_host.cc b/components/exo/surface_tree_host.cc
index 1693ba9..8348b7f 100644
--- a/components/exo/surface_tree_host.cc
+++ b/components/exo/surface_tree_host.cc
@@ -108,14 +108,13 @@
   host_window_->SetEventTargetingPolicy(
       aura::EventTargetingPolicy::kDescendantsOnly);
   host_window_->SetEventTargeter(std::make_unique<CustomWindowTargeter>(this));
-
+  layer_tree_frame_sink_holder_ = std::make_unique<LayerTreeFrameSinkHolder>(
+      this, host_window_->CreateLayerTreeFrameSink());
   context_provider_ = aura::Env::GetInstance()
                           ->context_factory()
                           ->SharedMainThreadContextProvider();
   DCHECK(context_provider_);
   context_provider_->AddObserver(this);
-  layer_tree_frame_sink_holder_ = std::make_unique<LayerTreeFrameSinkHolder>(
-      this, host_window_->CreateLayerTreeFrameSink(), context_provider_);
 }
 
 SurfaceTreeHost::~SurfaceTreeHost() {
@@ -379,7 +378,7 @@
     // We can immediately delete the old LayerTreeFrameSinkHolder because all of
     // it's resources are lost anyways.
     layer_tree_frame_sink_holder_ = std::make_unique<LayerTreeFrameSinkHolder>(
-        this, host_window_->CreateLayerTreeFrameSink(), context_provider_);
+        this, host_window_->CreateLayerTreeFrameSink());
   }
 
   viz::CompositorFrame frame;
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 2e6270a..9e1b4223 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -53,7 +53,6 @@
 #include "build/chromeos_buildflags.h"
 #include "components/exo/buildflags.h"
 #include "components/exo/capabilities.h"
-#include "components/exo/common_utils.h"
 #include "components/exo/display.h"
 #include "components/exo/wayland/overlay_prioritizer.h"
 #include "components/exo/wayland/serial_tracker.h"
@@ -143,6 +142,18 @@
 constexpr base::FilePath::CharType kCustomServerDir[] =
     FILE_PATH_LITERAL("wayland");
 
+bool IsDrmAtomicAvailable() {
+#if defined(USE_OZONE)
+  auto& host_properties =
+      ui::OzonePlatform::GetInstance()->GetPlatformRuntimeProperties();
+  return host_properties.supports_overlays;
+#else
+  LOG(WARNING) << "Ozone disabled, cannot determine whether DrmAtomic is "
+                  "present. Assuming it is not";
+  return false;
+#endif
+}
+
 void wayland_log(const char* fmt, va_list argp) {
   LOG(WARNING) << "libwayland: " << base::StringPrintV(fmt, argp);
 }
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
index 893436c6..15606e1e 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -47,6 +47,7 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.task.PostTask;
+import org.chromium.build.BuildConfig;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.components.embedder_support.util.UrlUtilitiesJni;
@@ -156,7 +157,7 @@
     }
 
     // A Supplier that only evaluates when needed then caches the value.
-    protected abstract static class LazySupplier<T> implements Supplier<T> {
+    protected static class LazySupplier<T> implements Supplier<T> {
         private T mValue;
         private Supplier<T> mInnerSupplier;
 
@@ -184,16 +185,63 @@
         }
     }
 
-    // Used to ensure we only call queryIntentActivities when we really need to.
-    protected class QueryIntentActivitiesSupplier extends LazySupplier<List<ResolveInfo>> {
-        public QueryIntentActivitiesSupplier(Intent intent) {
-            super(() -> queryIntentActivities(intent));
+    private static class IntentBasedSupplier<T> extends LazySupplier<T> {
+        protected final Intent mIntent;
+        private Intent mIntentCopy;
+
+        public IntentBasedSupplier(Intent intent, Supplier<T> innerSupplier) {
+            super(innerSupplier);
+            mIntent = intent;
+        }
+
+        protected void assertIntentMatches() {
+            // If the intent filter changes the previously supplied result will no longer be valid.
+            if (BuildConfig.ENABLE_ASSERTS) {
+                if (mIntentCopy != null) {
+                    assert intentResolutionMatches(mIntent, mIntentCopy);
+                } else {
+                    mIntentCopy = new Intent(mIntent);
+                }
+            }
+        }
+
+        @Nullable
+        @Override
+        public T get() {
+            assertIntentMatches();
+            return super.get();
         }
     }
 
-    protected static class ResolveActivitySupplier extends LazySupplier<ResolveInfo> {
+    // Used to ensure we only call queryIntentActivities when we really need to.
+    protected class QueryIntentActivitiesSupplier extends IntentBasedSupplier<List<ResolveInfo>> {
+        // We need the query to include non-default intent filters, but should not return
+        // them for clients that don't explicitly need to check non-default filters.
+        private class QueryNonDefaultSupplier extends LazySupplier<List<ResolveInfo>> {
+            public QueryNonDefaultSupplier(Intent intent) {
+                super(()
+                                -> PackageManagerUtils.queryIntentActivities(
+                                        intent, PackageManager.GET_RESOLVED_FILTER));
+            }
+        }
+
+        final QueryNonDefaultSupplier mNonDefaultSupplier;
+
+        public QueryIntentActivitiesSupplier(Intent intent) {
+            super(intent, () -> queryIntentActivities(intent));
+            mNonDefaultSupplier = new QueryNonDefaultSupplier(intent);
+        }
+
+        public List<ResolveInfo> getIncludingNonDefaultResolveInfos() {
+            assertIntentMatches();
+            return mNonDefaultSupplier.get();
+        }
+    }
+
+    protected static class ResolveActivitySupplier extends IntentBasedSupplier<ResolveInfo> {
         public ResolveActivitySupplier(Intent intent) {
-            super(()
+            super(intent,
+                    ()
                             -> PackageManagerUtils.resolveActivity(
                                     intent, PackageManager.MATCH_DEFAULT_ONLY));
         }
@@ -390,9 +438,10 @@
                     Intent intent =
                             Intent.parseUri(browserFallbackUrl.getSpec(), Intent.URI_INTENT_SCHEME);
                     sanitizeQueryIntentActivitiesIntent(intent);
-                    List<ResolveInfo> resolvingInfos = queryIntentActivities(intent);
-                    if (!isAlreadyInTargetWebApk(resolvingInfos, params)
-                            && launchWebApkIfSoleIntentHandler(resolvingInfos, intent)) {
+                    QueryIntentActivitiesSupplier supplier =
+                            new QueryIntentActivitiesSupplier(intent);
+                    if (!isAlreadyInTargetWebApk(supplier, params)
+                            && launchWebApkIfSoleIntentHandler(supplier, intent, params)) {
                         return OverrideUrlLoadingResult.forExternalIntent();
                     }
                 } catch (Exception e) {
@@ -653,23 +702,36 @@
         return false;
     }
 
+    // https://crbug.com/1232514: On Android S, since WebAPKs aren't verified apps they are
+    // never launched as the result of a suitable Intent, the user's default browser will be
+    // opened instead. As a temporary solution, have Chrome launch the WebAPK.
+    //
+    // Note that we also need to query for non-default handlers as WebApks being non-default
+    // Web Intent handlers is the cause of the issue.
+    private boolean intentMatchesNonDefaultWebApk(
+            ExternalNavigationParams params, QueryIntentActivitiesSupplier resolvingInfos) {
+        if (params.isFromIntent() && mDelegate.shouldLaunchWebApksOnInitialIntent()) {
+            String packageName = pickWebApkIfSoleIntentHandler(params, resolvingInfos);
+            if (packageName != null) {
+                if (DEBUG) Log.i(TAG, "Matches possibly non-default WebApk");
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * http://crbug.com/149218: We want to show the intent picker for ordinary links, providing
      * the link is not an incoming intent from another application, unless it's a redirect.
      */
     private boolean preferToShowIntentPicker(ExternalNavigationParams params,
             boolean isExternalProtocol, boolean incomingIntentRedirect,
-            QueryIntentActivitiesSupplier resolveInfos) {
+            boolean intentMatchesNonDefaultWebApk) {
         int pageTransitionCore = params.getPageTransition() & PageTransition.CORE_MASK;
         boolean isFormSubmit = pageTransitionCore == PageTransition.FORM_SUBMIT;
 
-        // https://crbug.com/1232514: On Android S, since WebAPKs aren't verified apps they are
-        // never launched as the result of a suitable Intent, the user's default browser will be
-        // opened instead. As a temporary solution, have Chrome launch the WebAPK.
-        if (params.isFromIntent() && mDelegate.shouldLaunchWebApksOnInitialIntent()) {
-            boolean suitableWebApk = pickWebApkIfSoleIntentHandler(resolveInfos.get()) != null;
-            if (suitableWebApk) return true;
-        }
+        // Allow initial Intent to leave Chrome if it matched a non-Default WebApk.
+        if (intentMatchesNonDefaultWebApk) return true;
 
         // http://crbug.com/169549 : If you type in a URL that then redirects in server side to a
         // link that cannot be rendered by the browser, we want to show the intent picker.
@@ -1228,10 +1290,10 @@
      * are currently showing the WebAPK (params#nativeClientPackageName()) that we will redirect to.
      */
     private boolean isAlreadyInTargetWebApk(
-            List<ResolveInfo> resolveInfos, ExternalNavigationParams params) {
+            QueryIntentActivitiesSupplier resolvingInfos, ExternalNavigationParams params) {
         String currentName = params.nativeClientPackageName();
         if (currentName == null) return false;
-        for (ResolveInfo resolveInfo : resolveInfos) {
+        for (ResolveInfo resolveInfo : getResolveInfosForWebApks(params, resolvingInfos)) {
             ActivityInfo info = resolveInfo.activityInfo;
             if (info != null && currentName.equals(info.packageName)) {
                 if (DEBUG) Log.i(TAG, "Already in WebAPK");
@@ -1379,11 +1441,13 @@
             return OverrideUrlLoadingResult.forNoOverride();
         }
 
-        Intent debugIntent = new Intent(targetIntent);
         QueryIntentActivitiesSupplier resolvingInfos =
                 new QueryIntentActivitiesSupplier(targetIntent);
-        if (!preferToShowIntentPicker(
-                    params, isExternalProtocol, incomingIntentRedirect, resolvingInfos)) {
+
+        boolean intentMatchesNonDefaultWebApk =
+                intentMatchesNonDefaultWebApk(params, resolvingInfos);
+        if (!preferToShowIntentPicker(params, isExternalProtocol, incomingIntentRedirect,
+                    intentMatchesNonDefaultWebApk)) {
             return OverrideUrlLoadingResult.forNoOverride();
         }
 
@@ -1402,7 +1466,7 @@
         if (!browserFallbackUrl.isEmpty()) targetIntent.removeExtra(EXTRA_BROWSER_FALLBACK_URL);
 
         boolean hasSpecializedHandler = countSpecializedHandlers(resolvingInfos.get()) > 0;
-        if (!isExternalProtocol && !hasSpecializedHandler) {
+        if (!isExternalProtocol && !hasSpecializedHandler && !intentMatchesNonDefaultWebApk) {
             if (fallBackToHandlingWithInstantApp(params, incomingIntentRedirect)) {
                 return OverrideUrlLoadingResult.forExternalIntent();
             }
@@ -1420,9 +1484,6 @@
                 && isIntentToInstantApp(targetIntent) && isSerpReferrer();
         prepareExternalIntent(
                 targetIntent, params, resolvingInfos.get(), shouldProxyForInstantApps);
-        // As long as our intent resolution hasn't changed, resolvingInfos won't need to be
-        // re-computed as it won't have changed.
-        assert intentResolutionMatches(debugIntent, targetIntent);
 
         if (params.isIncognito()) {
             return handleIncognitoIntent(params, targetIntent, intentDataUrl, resolvingInfos.get(),
@@ -1434,9 +1495,9 @@
             return OverrideUrlLoadingResult.forNoOverride();
         }
 
-        if (isAlreadyInTargetWebApk(resolvingInfos.get(), params)) {
+        if (isAlreadyInTargetWebApk(resolvingInfos, params)) {
             return OverrideUrlLoadingResult.forNoOverride();
-        } else if (launchWebApkIfSoleIntentHandler(resolvingInfos.get(), targetIntent)) {
+        } else if (launchWebApkIfSoleIntentHandler(resolvingInfos, targetIntent, params)) {
             return OverrideUrlLoadingResult.forExternalIntent();
         }
 
@@ -1453,7 +1514,7 @@
         }
 
         return startActivity(targetIntent, shouldProxyForInstantApps, requiresIntentChooser,
-                resolvingInfos.get(), resolveActivity, browserFallbackUrl, intentDataUrl,
+                resolvingInfos, resolveActivity, browserFallbackUrl, intentDataUrl,
                 params.getReferrerUrl());
     }
 
@@ -1635,9 +1696,9 @@
      * Launches WebAPK if the WebAPK is the sole non-browser handler for the given intent.
      * @return Whether a WebAPK was launched.
      */
-    private boolean launchWebApkIfSoleIntentHandler(
-            List<ResolveInfo> resolvingInfos, Intent targetIntent) {
-        String packageName = pickWebApkIfSoleIntentHandler(resolvingInfos);
+    private boolean launchWebApkIfSoleIntentHandler(QueryIntentActivitiesSupplier resolvingInfos,
+            Intent targetIntent, ExternalNavigationParams params) {
+        String packageName = pickWebApkIfSoleIntentHandler(params, resolvingInfos);
         if (packageName == null) return false;
 
         Intent webApkIntent = new Intent(targetIntent);
@@ -1654,9 +1715,20 @@
         }
     }
 
+    // https://crbug.com/1232514. See #intentMatchesNonDefaultWebApk.
+    private List<ResolveInfo> getResolveInfosForWebApks(
+            ExternalNavigationParams params, QueryIntentActivitiesSupplier resolvingInfos) {
+        if (params.isFromIntent() && mDelegate.shouldLaunchWebApksOnInitialIntent()) {
+            return resolvingInfos.getIncludingNonDefaultResolveInfos();
+        }
+        return resolvingInfos.get();
+    }
+
     @Nullable
-    private String pickWebApkIfSoleIntentHandler(List<ResolveInfo> resolvingInfos) {
-        ArrayList<String> packages = getSpecializedHandlers(resolvingInfos);
+    private String pickWebApkIfSoleIntentHandler(
+            ExternalNavigationParams params, QueryIntentActivitiesSupplier resolvingInfos) {
+        ArrayList<String> packages =
+                getSpecializedHandlers(getResolveInfosForWebApks(params, resolvingInfos));
         if (packages.size() != 1 || !isValidWebApk(packages.get(0))) return null;
         return packages.get(0);
     }
@@ -1800,7 +1872,7 @@
      * @returns The OverrideUrlLoadingResult for starting (or not starting) the Activity.
      */
     protected OverrideUrlLoadingResult startActivity(Intent intent, boolean proxy,
-            boolean requiresIntentChooser, List<ResolveInfo> resolvingInfos,
+            boolean requiresIntentChooser, QueryIntentActivitiesSupplier resolvingInfos,
             ResolveActivitySupplier resolveActivity, GURL browserFallbackUrl, GURL intentDataUrl,
             GURL referrerUrl) {
         // Only touches disk on Kitkat. See http://crbug.com/617725 for more context.
@@ -1852,7 +1924,7 @@
 
     @SuppressWarnings("UseCompatLoadingForDrawables")
     private OverrideUrlLoadingResult startActivityWithChooser(final Intent intent,
-            List<ResolveInfo> resolvingInfos, ResolveActivitySupplier resolveActivity,
+            QueryIntentActivitiesSupplier resolvingInfos, ResolveActivitySupplier resolveActivity,
             GURL browserFallbackUrl, GURL intentDataUrl, GURL referrerUrl, Context context) {
         ResolveInfo intentResolveInfo = resolveActivity.get();
         // If this is null, then the intent was only previously matching
@@ -1864,7 +1936,7 @@
         // will already get the option to choose the target app (as there will be multiple options)
         // and we don't need to do anything. Otherwise we have to make a fake option in the chooser
         // dialog that loads the URL in the embedding app.
-        if (!resolversSubsetOf(Arrays.asList(intentResolveInfo), resolvingInfos)) {
+        if (!resolversSubsetOf(Arrays.asList(intentResolveInfo), resolvingInfos.get())) {
             return doStartActivity(intent, context);
         }
 
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
index e3ad817e..d6bfbf3 100644
--- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
+++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -2669,7 +2669,8 @@
 
         @Override
         protected OverrideUrlLoadingResult startActivity(Intent intent, boolean proxy,
-                boolean requiresIntentChooser, List<ResolveInfo> resolvingInfos,
+                boolean requiresIntentChooser,
+                ExternalNavigationHandler.QueryIntentActivitiesSupplier resolvingInfos,
                 ResolveActivitySupplier resolveActivity, GURL browserFallbackUrl,
                 GURL intentDataUrl, GURL referrerUrl) {
             mStartActivityIntent = intent;
@@ -3181,7 +3182,6 @@
 
         @Override
         public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
-            Assert.assertTrue((flags & PackageManager.MATCH_DEFAULT_ONLY) > 0);
             return mDelegate.queryIntentActivities(intent);
         }
 
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
index 87d6500..232bc11 100644
--- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
+++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
@@ -17,7 +17,6 @@
         FeatureConstants.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_SHARE_FEATURE,
         FeatureConstants.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_VOICE_SEARCH_FEATURE,
         FeatureConstants.ADD_TO_HOMESCREEN_MESSAGE_FEATURE,
-        FeatureConstants.ADD_TO_HOMESCREEN_TEXT_BUBBLE_FEATURE,
         FeatureConstants.AUTO_DARK_OPT_OUT_FEATURE,
         FeatureConstants.AUTO_DARK_USER_EDUCATION_MESSAGE_FEATURE,
         FeatureConstants.AUTO_DARK_USER_EDUCATION_MESSAGE_OPT_IN_FEATURE,
@@ -94,7 +93,6 @@
     String ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_VOICE_SEARCH_FEATURE =
             "IPH_AdaptiveButtonInTopToolbarCustomization_VoiceSearch";
     String ADD_TO_HOMESCREEN_MESSAGE_FEATURE = "IPH_AddToHomescreenMessage";
-    String ADD_TO_HOMESCREEN_TEXT_BUBBLE_FEATURE = "IPH_AddToHomescreenTextBubble";
     String AUTO_DARK_OPT_OUT_FEATURE = "IPH_AutoDarkOptOut";
     String AUTO_DARK_USER_EDUCATION_MESSAGE_FEATURE = "IPH_AutoDarkUserEducationMessage";
     String AUTO_DARK_USER_EDUCATION_MESSAGE_OPT_IN_FEATURE =
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc
index 22047f8..99b2ecad 100644
--- a/components/feature_engagement/public/feature_configurations.cc
+++ b/components/feature_engagement/public/feature_configurations.cc
@@ -247,23 +247,6 @@
         "add_to_homescreen_message_iph_trigger", Comparator(EQUAL, 0), 15, 90));
     return config;
   }
-  if (kIPHAddToHomescreenTextBubbleFeature.name == feature->name) {
-    // A config that allows the Add to homescreen text bubble IPH to be shown:
-    // * Once per 15 days
-    // * Up to 2 times but only if unused in the last 15 days.
-    absl::optional<FeatureConfig> config = FeatureConfig();
-    config->valid = true;
-    config->availability = Comparator(ANY, 0);
-    config->session_rate = Comparator(EQUAL, 0);
-    config->trigger = EventConfig("add_to_homescreen_text_bubble_iph_trigger",
-                                  Comparator(LESS_THAN, 2), 90, 90);
-    config->used = EventConfig("add_to_homescreen_dialog_shown",
-                               Comparator(EQUAL, 0), 90, 90);
-    config->event_configs.insert(
-        EventConfig("add_to_homescreen_text_bubble_iph_trigger",
-                    Comparator(EQUAL, 0), 15, 90));
-    return config;
-  }
 
   // Feature notification guide help UI promos that are shown in response to a
   // notification click.
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc
index 80b22a16..8988eca 100644
--- a/components/feature_engagement/public/feature_constants.cc
+++ b/components/feature_engagement/public/feature_constants.cc
@@ -76,8 +76,6 @@
         base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kIPHAddToHomescreenMessageFeature{
     "IPH_AddToHomescreenMessage", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kIPHAddToHomescreenTextBubbleFeature{
-    "IPH_AddToHomescreenTextBubble", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kIPHAutoDarkOptOutFeature{"IPH_AutoDarkOptOut",
                                               base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kIPHAutoDarkUserEducationMessageFeature{
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h
index 366fdc4b..8ce5c31 100644
--- a/components/feature_engagement/public/feature_constants.h
+++ b/components/feature_engagement/public/feature_constants.h
@@ -65,7 +65,6 @@
 extern const base::Feature
     kIPHAdaptiveButtonInTopToolbarCustomizationVoiceSearchFeature;
 extern const base::Feature kIPHAddToHomescreenMessageFeature;
-extern const base::Feature kIPHAddToHomescreenTextBubbleFeature;
 extern const base::Feature kIPHAutoDarkOptOutFeature;
 extern const base::Feature kIPHAutoDarkUserEducationMessageFeature;
 extern const base::Feature kIPHAutoDarkUserEducationMessageOptInFeature;
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc
index 6415aa2..ec02fc1b 100644
--- a/components/feature_engagement/public/feature_list.cc
+++ b/components/feature_engagement/public/feature_list.cc
@@ -20,7 +20,6 @@
     &kIPHAdaptiveButtonInTopToolbarCustomizationShareFeature,
     &kIPHAdaptiveButtonInTopToolbarCustomizationVoiceSearchFeature,
     &kIPHAddToHomescreenMessageFeature,
-    &kIPHAddToHomescreenTextBubbleFeature,
     &kIPHAutoDarkOptOutFeature,
     &kIPHAutoDarkUserEducationMessageFeature,
     &kIPHAutoDarkUserEducationMessageOptInFeature,
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h
index 78d306c8..449f2dd6 100644
--- a/components/feature_engagement/public/feature_list.h
+++ b/components/feature_engagement/public/feature_list.h
@@ -54,8 +54,6 @@
     "IPH_AdaptiveButtonInTopToolbarCustomization_VoiceSearch");
 DEFINE_VARIATION_PARAM(kIPHAddToHomescreenMessageFeature,
                        "IPH_AddToHomescreenMessage");
-DEFINE_VARIATION_PARAM(kIPHAddToHomescreenTextBubbleFeature,
-                       "IPH_AddToHomescreenTextBubble");
 DEFINE_VARIATION_PARAM(kIPHAutoDarkOptOutFeature, "IPH_AutoDarkOptOut");
 DEFINE_VARIATION_PARAM(kIPHAutoDarkUserEducationMessageFeature,
                        "IPH_AutoDarkUserEducationMessage");
@@ -277,7 +275,6 @@
         VARIATION_ENTRY(
             kIPHAdaptiveButtonInTopToolbarCustomizationVoiceSearchFeature),
         VARIATION_ENTRY(kIPHAddToHomescreenMessageFeature),
-        VARIATION_ENTRY(kIPHAddToHomescreenTextBubbleFeature),
         VARIATION_ENTRY(kIPHAutoDarkOptOutFeature),
         VARIATION_ENTRY(kIPHAutoDarkUserEducationMessageFeature),
         VARIATION_ENTRY(kIPHAutoDarkUserEducationMessageOptInFeature),
diff --git a/components/feed/core/v2/BUILD.gn b/components/feed/core/v2/BUILD.gn
index 35b95f1..2364a15 100644
--- a/components/feed/core/v2/BUILD.gn
+++ b/components/feed/core/v2/BUILD.gn
@@ -14,6 +14,7 @@
     "public/feed_service.h",
     "public/feed_stream_surface.h",
     "public/logging_parameters.h",
+    "public/ntp_feed_content_fetcher.h",
     "public/persistent_key_value_store.h",
     "public/persistent_key_value_store.h",
     "public/refresh_task_scheduler.h",
@@ -64,6 +65,8 @@
     "public/feed_service.cc",
     "public/feed_stream_surface.cc",
     "public/logging_parameters.cc",
+    "public/ntp_feed_content_fetcher.cc",
+    "public/ntp_feed_content_fetcher.h",
     "public/persistent_key_value_store.cc",
     "public/public_types.cc",
     "public/stream_type.cc",
@@ -213,6 +216,7 @@
     "protocol_translator_unittest.cc",
     "public/feed_service_unittest.cc",
     "public/logging_parameters_unittest.cc",
+    "public/ntp_feed_content_fetcher_unittest.cc",
     "public/public_types_unittest.cc",
     "request_throttler_unittest.cc",
     "scheduling_unittest.cc",
diff --git a/components/feed/core/v2/public/ntp_feed_content_fetcher.cc b/components/feed/core/v2/public/ntp_feed_content_fetcher.cc
new file mode 100644
index 0000000..aaaa370a0
--- /dev/null
+++ b/components/feed/core/v2/public/ntp_feed_content_fetcher.cc
@@ -0,0 +1,128 @@
+// 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/feed/core/v2/public/ntp_feed_content_fetcher.h"
+
+#include <memory>
+#include "components/feed/core/proto/v2/wire/client_info.pb.h"
+#include "components/feed/core/proto/v2/wire/stream_structure.pb.h"
+#include "components/feed/core/v2/feed_network_impl.h"
+#include "components/feed/core/v2/proto_util.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+
+namespace feed {
+namespace {
+
+constexpr int kTargetArticleCount = 3;
+
+void HandleWebFeedListContentsResponse(
+    base::OnceCallback<void(std::vector<NtpFeedContentFetcher::Article>)>
+        callback,
+    FeedNetwork::ApiResult<feedwire::Response> response) {
+  std::vector<NtpFeedContentFetcher::Article> result;
+  if (!response.response_body) {
+    DLOG(ERROR) << "Failed to fetch content for feed NTP module. Status: "
+                << response.response_info.status_code;
+    return std::move(callback).Run(std::move(result));
+  }
+
+  // Get the first several articles from the response. No attempt is made
+  // to show a variety of publishers.
+  for (const feedwire::DataOperation& data_operation :
+       response.response_body->feed_response().data_operation()) {
+    if (data_operation.operation() !=
+            feedwire::DataOperation::UPDATE_OR_APPEND ||
+        !data_operation.has_feature() ||
+        !data_operation.feature().has_content()) {
+      continue;
+    }
+
+    for (const feedwire::PrefetchMetadata& prefetch_metadata :
+         data_operation.feature().content().prefetch_metadata()) {
+      auto& article = result.emplace_back();
+      article.title = prefetch_metadata.title();
+      article.publisher = prefetch_metadata.publisher();
+      article.url = GURL(prefetch_metadata.uri());
+      article.thumbnail_url = GURL(prefetch_metadata.image_url());
+      article.favicon_url = GURL(prefetch_metadata.favicon_url());
+      if (result.size() >= kTargetArticleCount)
+        return std::move(callback).Run(std::move(result));
+    }
+  }
+  DLOG_IF(ERROR, result.size() < kTargetArticleCount)
+      << "Request for content for the feed NTP module succeeded but the "
+         "response contained fewer than "
+      << kTargetArticleCount << " articles.";
+  std::move(callback).Run(std::move(result));
+}
+
+}  // namespace
+
+NtpFeedContentFetcher::NtpFeedContentFetcher(
+    signin::IdentityManager* identity_manager,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+    const std::string& api_key,
+    PrefService* pref_service)
+    : feed_network_delegate_(identity_manager) {
+  feed_network_ = std::make_unique<FeedNetworkImpl>(
+      &feed_network_delegate_, identity_manager, api_key, url_loader_factory,
+      pref_service);
+}
+
+NtpFeedContentFetcher::~NtpFeedContentFetcher() = default;
+
+NtpFeedContentFetcher::Article::Article() = default;
+NtpFeedContentFetcher::Article::Article(const Article&) = default;
+NtpFeedContentFetcher::Article::~Article() = default;
+
+void NtpFeedContentFetcher::FetchFollowingFeedArticles(
+    base::OnceCallback<void(std::vector<NtpFeedContentFetcher::Article>)>
+        callback) {
+  feedwire::Request request = CreateFeedQueryRefreshRequest(
+      StreamType(StreamKind::kFollowing),
+      feedwire::FeedQuery::INTERACTIVE_WEB_FEED, RequestMetadata(),
+      /*consistency_token=*/std::string());
+
+  feedwire::ClientInfo* client_info =
+      request.mutable_feed_request()->mutable_client_info();
+  // TODO(https://crbug.com/1328951): For the desktop feed prototype we call the
+  // Android endpoint and need to pretend we are an Android client. This won't
+  // be the case for the launch.
+  client_info->set_platform_type(feedwire::ClientInfo::ANDROID_ID);
+  client_info->set_app_type(feedwire::ClientInfo::CHROME_ANDROID);
+
+  // For the prototype, it's okay if the request fails or the user is signed
+  // out; the module will be empty.
+  feed_network_->SendApiRequest<WebFeedListContentsDiscoverApi>(
+      request, feed_network_delegate_.GetAccountInfo(), RequestMetadata(),
+      base::BindOnce(&HandleWebFeedListContentsResponse, std::move(callback)));
+}
+
+void NtpFeedContentFetcher::SetFeedNetworkForTesting(
+    std::unique_ptr<FeedNetwork> feed_network) {
+  feed_network_ = std::move(feed_network);
+}
+
+NtpFeedContentFetcher::NetworkDelegate::NetworkDelegate(
+    signin::IdentityManager* identity_manager)
+    : identity_manager_(identity_manager) {}
+
+std::string NtpFeedContentFetcher::NetworkDelegate::GetLanguageTag() {
+  // TODO(https://crbug.com/1328951): Change this for the final implementation.
+  return std::string();
+}
+
+AccountInfo NtpFeedContentFetcher::NetworkDelegate::GetAccountInfo() {
+  return AccountInfo(
+      identity_manager_->GetPrimaryAccountInfo(signin::ConsentLevel::kSync));
+}
+
+bool NtpFeedContentFetcher::NetworkDelegate::IsOffline() {
+  // TODO(https://crbug.com/1328951): Change this for the final implementation.
+  return false;
+}
+
+}  // namespace feed
\ No newline at end of file
diff --git a/components/feed/core/v2/public/ntp_feed_content_fetcher.h b/components/feed/core/v2/public/ntp_feed_content_fetcher.h
new file mode 100644
index 0000000..5e1624d
--- /dev/null
+++ b/components/feed/core/v2/public/ntp_feed_content_fetcher.h
@@ -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.
+
+#ifndef COMPONENTS_FEED_CORE_V2_PUBLIC_NTP_FEED_CONTENT_FETCHER_H_
+#define COMPONENTS_FEED_CORE_V2_PUBLIC_NTP_FEED_CONTENT_FETCHER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/memory/raw_ptr.h"
+#include "components/feed/core/v2/feed_network.h"
+#include "components/feed/core/v2/feed_network_impl.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "url/gurl.h"
+
+namespace feed {
+
+/** Supports fetching feed content for the desktop NTP module. */
+class NtpFeedContentFetcher {
+ public:
+  NtpFeedContentFetcher(
+      signin::IdentityManager* identity_manager,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const std::string& api_key,
+      PrefService* pref_service);
+  ~NtpFeedContentFetcher();
+
+  /** Semantic article info based on PrefetchMetadata. */
+  struct Article {
+    std::string title;
+    std::string publisher;
+    GURL url;
+    GURL thumbnail_url;
+    GURL favicon_url;
+
+    Article();
+    Article(const Article&);
+    ~Article();
+  };
+
+  /**
+   * Fetch following feed articles, build a vector of Articles based
+   * on their PrefetchMetadata, and pass them along to the callback.
+   * @param callback Callback that is called with the fetch result.
+   */
+  void FetchFollowingFeedArticles(
+      base::OnceCallback<void(std::vector<Article>)>);
+
+  void SetFeedNetworkForTesting(std::unique_ptr<FeedNetwork> feed_network);
+
+ private:
+  class NetworkDelegate : public FeedNetworkImpl::Delegate {
+   public:
+    explicit NetworkDelegate(signin::IdentityManager* identity_manager);
+    ~NetworkDelegate() override = default;
+    std::string GetLanguageTag() override;
+    AccountInfo GetAccountInfo() override;
+    bool IsOffline() override;
+
+   private:
+    // identity_manager_ is unowned and will outlive NtpFeedContentFetcher.
+    raw_ptr<signin::IdentityManager> identity_manager_;
+  };
+
+  NetworkDelegate feed_network_delegate_;
+  std::unique_ptr<FeedNetwork> feed_network_;
+};
+
+}  // namespace feed
+
+#endif  // COMPONENTS_FEED_CORE_V2_PUBLIC_NTP_FEED_CONTENT_FETCHER_H_
\ No newline at end of file
diff --git a/components/feed/core/v2/public/ntp_feed_content_fetcher_unittest.cc b/components/feed/core/v2/public/ntp_feed_content_fetcher_unittest.cc
new file mode 100644
index 0000000..787ee750
--- /dev/null
+++ b/components/feed/core/v2/public/ntp_feed_content_fetcher_unittest.cc
@@ -0,0 +1,136 @@
+// 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/feed/core/v2/public/ntp_feed_content_fetcher.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
+#include "components/feed/core/proto/v2/wire/data_operation.pb.h"
+#include "components/feed/core/proto/v2/wire/feed_response.pb.h"
+#include "components/feed/core/proto/v2/wire/payload_metadata.pb.h"
+#include "components/feed/core/proto/v2/wire/response.pb.h"
+#include "components/feed/core/proto/v2/wire/stream_structure.pb.h"
+#include "components/feed/core/v2/api_test/feed_api_test.h"
+#include "components/signin/public/base/consent_level.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace feed::test {
+namespace {
+
+const char* kExampleUrl = "http://example.com/";
+const char* kEmail = "user@example.com";
+
+feedwire::Response MakeFeedResponse(int count) {
+  feedwire::Response response;
+  response.set_response_version(feedwire::Response::FEED_RESPONSE);
+  feedwire::FeedResponse* feed_response = response.mutable_feed_response();
+  for (int i = 0; i < count; ++i) {
+    feedwire::DataOperation* op = feed_response->add_data_operation();
+    op->set_operation(feedwire::DataOperation::UPDATE_OR_APPEND);
+    feedwire::PrefetchMetadata* metadata =
+        op->mutable_feature()->mutable_content()->add_prefetch_metadata();
+    std::string number = base::NumberToString(i);
+    metadata->set_uri(base::StrCat({kExampleUrl, number}));
+    metadata->set_title(base::StrCat({"Article ", number}));
+    metadata->set_favicon_url(
+        base::StrCat({kExampleUrl, number, "/favicon.ico"}));
+    metadata->set_image_url(
+        base::StrCat({kExampleUrl, number, "/thumbnail.jpg"}));
+    metadata->set_publisher(base::StrCat({"Publisher ", number}));
+  }
+  return response;
+}
+
+}  // namespace
+
+class NtpFeedContentFetcherTest : public testing::Test {
+ public:
+  NtpFeedContentFetcherTest() {
+    identity_test_env_.SetPrimaryAccount(kEmail, signin::ConsentLevel::kSync);
+  }
+  NtpFeedContentFetcherTest(NtpFeedContentFetcherTest&) = delete;
+  NtpFeedContentFetcherTest& operator=(const NtpFeedContentFetcherTest&) =
+      delete;
+  ~NtpFeedContentFetcherTest() override = default;
+
+  void SetUp() override {
+    testing::Test::SetUp();
+    feed::RegisterProfilePrefs(profile_prefs_.registry());
+    shared_url_loader_factory_ =
+        base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+            &test_factory_);
+    ntp_feed_content_fetcher_ = std::make_unique<NtpFeedContentFetcher>(
+        identity_test_env_.identity_manager(), shared_url_loader_factory_,
+        "dummy_api_key", &profile_prefs_);
+
+    auto feed_network = std::make_unique<TestFeedNetwork>();
+    feed_network->SendResponsesOnCommand(false);
+    feed_network_ = feed_network.get();
+    ntp_feed_content_fetcher_->SetFeedNetworkForTesting(
+        std::move(feed_network));
+  }
+
+  void TearDown() override { ntp_feed_content_fetcher_.reset(); }
+
+ protected:
+  base::test::TaskEnvironment task_environment_{
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+  std::unique_ptr<NtpFeedContentFetcher> ntp_feed_content_fetcher_;
+  signin::IdentityTestEnvironment identity_test_env_;
+  TestFeedNetwork* feed_network_;
+  network::TestURLLoaderFactory test_factory_;
+  scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
+  TestingPrefServiceSimple profile_prefs_;
+};
+
+TEST_F(NtpFeedContentFetcherTest, FetchFollowingFeedArticles) {
+  std::vector<NtpFeedContentFetcher::Article> actual_articles;
+  base::MockOnceCallback<void(std::vector<NtpFeedContentFetcher::Article>)>
+      callback;
+
+  EXPECT_CALL(callback, Run(testing::_))
+      .Times(1)
+      .WillOnce(testing::Invoke(
+          [&](std::vector<NtpFeedContentFetcher::Article> articles) {
+            actual_articles = std::move(articles);
+          }));
+
+  // Inject a response of 5 articles. We should only get 3.
+  feed_network_->InjectApiResponse<WebFeedListContentsDiscoverApi>(
+      MakeFeedResponse(5));
+  ntp_feed_content_fetcher_->FetchFollowingFeedArticles(callback.Get());
+
+  EXPECT_EQ(kEmail, feed_network_->last_account_info.email);
+  absl::optional<feedwire::Request> sent_request =
+      feed_network_->GetApiRequestSent<WebFeedListContentsDiscoverApi>();
+  ASSERT_TRUE(sent_request.has_value());
+  // TODO(https://crbug.com/1328951): Add a Chrome Desktop client type.
+  EXPECT_EQ(feedwire::ClientInfo::ANDROID_ID,
+            sent_request->feed_request().client_info().platform_type());
+  EXPECT_EQ(feedwire::ClientInfo::CHROME_ANDROID,
+            sent_request->feed_request().client_info().app_type());
+
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_EQ(3ul, actual_articles.size());
+  auto& article = actual_articles.front();
+  EXPECT_EQ("http://example.com/0", article.url);
+  EXPECT_EQ("Article 0", article.title);
+  EXPECT_EQ("Publisher 0", article.publisher);
+  EXPECT_EQ("http://example.com/0/favicon.ico", article.favicon_url);
+  EXPECT_EQ("http://example.com/0/thumbnail.jpg", article.thumbnail_url);
+}
+
+}  // namespace feed::test
\ No newline at end of file
diff --git a/components/feed/core/v2/types.h b/components/feed/core/v2/types.h
index ac9791d9..3a58f3d 100644
--- a/components/feed/core/v2/types.h
+++ b/components/feed/core/v2/types.h
@@ -50,11 +50,11 @@
 
   feedwire::ClientInfo ToClientInfo() const;
 
-  ChromeInfo chrome_info;
+  ChromeInfo chrome_info{};
   std::string language_tag;
   std::string client_instance_id;
   std::string session_id;
-  DisplayMetrics display_metrics;
+  DisplayMetrics display_metrics{};
   ContentOrder content_order = ContentOrder::kUnspecified;
   bool notice_card_acknowledged = false;
   bool autoplay_enabled = false;
diff --git a/components/guest_os/guest_os_engagement_metrics_unittest.cc b/components/guest_os/guest_os_engagement_metrics_unittest.cc
index 4023ae9..fc5159c 100644
--- a/components/guest_os/guest_os_engagement_metrics_unittest.cc
+++ b/components/guest_os/guest_os_engagement_metrics_unittest.cc
@@ -42,7 +42,7 @@
 
   void SetUp() override {
     chromeos::PowerManagerClient::InitializeFake();
-    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    ash::SessionManagerClient::InitializeFakeInMemory();
     pref_service_ = std::make_unique<TestingPrefServiceSimple>();
 
     matched_window_.reset(aura::test::CreateTestWindowWithId(0, nullptr));
@@ -63,7 +63,7 @@
     non_matched_window_.reset();
     matched_window_.reset();
     pref_service_.reset();
-    chromeos::SessionManagerClient::Shutdown();
+    ash::SessionManagerClient::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
   }
 
diff --git a/components/guest_view/browser/guest_view_message_handler.cc b/components/guest_view/browser/guest_view_message_handler.cc
index caf901e..ff68f8a 100644
--- a/components/guest_view/browser/guest_view_message_handler.cc
+++ b/components/guest_view/browser/guest_view_message_handler.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/metrics/histogram_functions.h"
 #include "components/guest_view/browser/bad_message.h"
 #include "components/guest_view/browser/guest_view_base.h"
 #include "components/guest_view/browser/guest_view_manager.h"
@@ -115,6 +116,13 @@
                        guest_instance_id,
                        base::Value::AsDictionaryValue(params));
 
+  const bool changed_owner_web_contents =
+      owner_web_contents !=
+      content::WebContents::FromRenderFrameHost(embedder_frame);
+  base::UmaHistogramBoolean(
+      "Extensions.GuestView.ChangeOwnerWebContentsOnAttach",
+      changed_owner_web_contents);
+
   guest->AttachToOuterWebContentsFrame(embedder_frame, element_instance_id,
                                        false /* is_full_page_plugin */,
                                        std::move(callback));
diff --git a/components/history/core/browser/BUILD.gn b/components/history/core/browser/BUILD.gn
index 5680177..2b9774f 100644
--- a/components/history/core/browser/BUILD.gn
+++ b/components/history/core/browser/BUILD.gn
@@ -195,6 +195,7 @@
     "//components/test/data/history/history.53.sql",
     "//components/test/data/history/history.54.sql",
     "//components/test/data/history/history.55.sql",
+    "//components/test/data/history/history.56.sql",
     "//components/test/data/history/thumbnail_wild/Favicons.corrupt_meta.disable",
     "//components/test/data/history/thumbnail_wild/Favicons.v2.init.sql",
     "//components/test/data/history/thumbnail_wild/Favicons.v3.init.sql",
diff --git a/components/history/core/browser/history_backend_db_unittest.cc b/components/history/core/browser/history_backend_db_unittest.cc
index 478d2789..2ed38f9 100644
--- a/components/history/core/browser/history_backend_db_unittest.cc
+++ b/components/history/core/browser/history_backend_db_unittest.cc
@@ -2669,6 +2669,60 @@
   }
 }
 
+TEST_F(HistoryBackendDBTest,
+       MigrateVisitsAddOriginatorFromVisitAndOpenerVisitColumns) {
+  ASSERT_NO_FATAL_FAILURE(CreateDBVersion(55));
+
+  constexpr VisitID visit_id = 1;
+  constexpr URLID url_id = 2;
+  const base::Time visit_time = base::Time::Now();
+
+  // Open the db for manual manipulation.
+  {
+    sql::Database sql_db;
+    ASSERT_TRUE(sql_db.Open(history_dir_.Append(kHistoryFilename)));
+
+    ASSERT_FALSE(sql_db.DoesColumnExist("visits", "originator_from_visit"));
+    ASSERT_FALSE(sql_db.DoesColumnExist("visits", "originator_opener_visit"));
+
+    const char kInsertVisitStatement[] =
+        "INSERT INTO visits "
+        "(id, url, visit_time) VALUES (?, ?, ?)";
+
+    // Add a row to `visits` table.
+    sql::Statement s(sql_db.GetUniqueStatement(kInsertVisitStatement));
+    s.BindInt64(0, visit_id);
+    s.BindInt64(1, url_id);
+    s.BindTime(2, visit_time);
+    ASSERT_TRUE(s.Run());
+  }
+
+  // Re-open the db, triggering migration.
+  CreateBackendAndDatabase();
+
+  // The previously-added visit should still exist, with the new columns being
+  // empty (equal to 0).
+  {
+    VisitRow visit;
+    db_->GetRowForVisit(visit_id, &visit);
+    EXPECT_EQ(visit.url_id, url_id);
+    EXPECT_EQ(visit.visit_time, visit_time);
+    EXPECT_EQ(visit.originator_referring_visit, 0);
+    EXPECT_EQ(visit.originator_opener_visit, 0);
+  }
+
+  DeleteBackend();
+
+  // Open the db manually again and make sure the new columns exist.
+  {
+    sql::Database sql_db;
+    ASSERT_TRUE(sql_db.Open(history_dir_.Append(kHistoryFilename)));
+
+    EXPECT_TRUE(sql_db.DoesColumnExist("visits", "originator_from_visit"));
+    EXPECT_TRUE(sql_db.DoesColumnExist("visits", "originator_opener_visit"));
+  }
+}
+
 bool FilterURL(const GURL& url) {
   return url.SchemeIsHTTPOrHTTPS();
 }
diff --git a/components/history/core/browser/history_database.cc b/components/history/core/browser/history_database.cc
index 5eb4b0f3..611e0ff 100644
--- a/components/history/core/browser/history_database.cc
+++ b/components/history/core/browser/history_database.cc
@@ -39,7 +39,7 @@
 // Current version number. We write databases at the "current" version number,
 // but any previous version that can read the "compatible" one can make do with
 // our database without *too* many bad effects.
-const int kCurrentVersionNumber = 55;
+const int kCurrentVersionNumber = 56;
 const int kCompatibleVersionNumber = 16;
 const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
 
@@ -708,6 +708,13 @@
     meta_table_.SetVersionNumber(cur_version);
   }
 
+  if (cur_version == 55) {
+    if (!MigrateVisitsAddOriginatorFromVisitAndOpenerVisitColumns())
+      return LogMigrationFailure(55);
+    cur_version++;
+    meta_table_.SetVersionNumber(cur_version);
+  }
+
   // =========================       ^^ new migration code goes here ^^
   // ADDING NEW MIGRATION CODE
   // =========================
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h
index 28dcf21f..faee96eb 100644
--- a/components/history/core/browser/history_types.h
+++ b/components/history/core/browser/history_types.h
@@ -86,8 +86,9 @@
 
   base::Time visit_time;
 
-  // Indicates another visit that was the referring page for this one.
-  // 0 indicates no referrer.
+  // Indicates another visit that was the redirecting or referring page for this
+  // one. 0 indicates no referrer/redirect.
+  // Note that this corresponds to the "from_visit" column in the visit DB.
   VisitID referring_visit = 0;
 
   // A combination of bits from PageTransition.
@@ -123,6 +124,13 @@
   // called a "cache" just to match Chrome Sync's terminology.
   std::string originator_cache_guid;
   VisitID originator_visit_id = 0;
+  // `originator_referring_visit` and `originator_opener_visit` are similar to
+  // the non-"originator" versions, but their contents refer to originator visit
+  // IDs rather than to local ones.
+  // Note that `originator_referring_visit` corresponds to the
+  // "originator_from_visit" column in the visit DB.
+  VisitID originator_referring_visit = 0;
+  VisitID originator_opener_visit = 0;
 
   // We allow the implicit copy constructor and operator=.
 };
diff --git a/components/history/core/browser/visit_annotations_database.cc b/components/history/core/browser/visit_annotations_database.cc
index a6846554..d552c397 100644
--- a/components/history/core/browser/visit_annotations_database.cc
+++ b/components/history/core/browser/visit_annotations_database.cc
@@ -447,6 +447,25 @@
   }
 }
 
+std::vector<int64_t> VisitAnnotationsDatabase::GetRecentClusterIds(
+    base::Time minimum_time) {
+  // Using `EXISTS` instead of `IN` would result in a full scan of
+  // `clusters_and_visits`. Using `JOIN` would produce an equivalent query plan.
+  sql::Statement statement(
+      GetDB().GetCachedStatement(SQL_FROM_HERE,
+                                 "SELECT DISTINCT cluster_id "
+                                 "FROM clusters_and_visits "
+                                 "WHERE visit_id IN("
+                                 "SELECT id FROM visits WHERE visit_time>=?)"
+                                 "ORDER BY cluster_id DESC"));
+  statement.BindTime(0, minimum_time);
+
+  std::vector<int64_t> cluster_ids;
+  while (statement.Step())
+    cluster_ids.push_back(statement.ColumnInt64(0));
+  return cluster_ids;
+}
+
 std::vector<int64_t> VisitAnnotationsDatabase::GetMostRecentClusterIds(
     base::Time inclusive_min_time,
     base::Time exclusive_max_time,
diff --git a/components/history/core/browser/visit_annotations_database.h b/components/history/core/browser/visit_annotations_database.h
index 2c2e3dbe..40d79ed 100644
--- a/components/history/core/browser/visit_annotations_database.h
+++ b/components/history/core/browser/visit_annotations_database.h
@@ -76,6 +76,9 @@
   // entries for any `Cluster` that it failed to add.
   void AddClusters(const std::vector<Cluster>& clusters);
 
+  // Get recent `Cluster`s' IDs newer than `minimum_time`.
+  std::vector<int64_t> GetRecentClusterIds(base::Time minimum_time);
+
   // Get the most recent clusters within the constraints. The most recent visit
   // of a cluster represents the cluster's time.
   std::vector<int64_t> GetMostRecentClusterIds(base::Time inclusive_min_time,
diff --git a/components/history/core/browser/visit_annotations_database_unittest.cc b/components/history/core/browser/visit_annotations_database_unittest.cc
index d2894ad..704b4d8 100644
--- a/components/history/core/browser/visit_annotations_database_unittest.cc
+++ b/components/history/core/browser/visit_annotations_database_unittest.cc
@@ -215,6 +215,15 @@
   EXPECT_EQ(final.alternative_title, "New alternative title");
 }
 
+TEST_F(VisitAnnotationsDatabaseTest, GetRecentClusterIds) {
+  AddCluster(
+      {AddVisitWithTime(IntToTime(11)), AddVisitWithTime(IntToTime(12))});
+
+  EXPECT_EQ(GetRecentClusterIds(IntToTime(13)), std::vector<int64_t>({}));
+  EXPECT_EQ(GetRecentClusterIds(IntToTime(12)), std::vector<int64_t>({1}));
+  EXPECT_EQ(GetRecentClusterIds(IntToTime(10)), std::vector<int64_t>({1}));
+}
+
 TEST_F(VisitAnnotationsDatabaseTest, GetMostRecentClusterIds) {
   AddCluster(
       {AddVisitWithTime(IntToTime(11)), AddVisitWithTime(IntToTime(12))});
diff --git a/components/history/core/browser/visit_database.cc b/components/history/core/browser/visit_database.cc
index 5d90a1fc..26c242d 100644
--- a/components/history/core/browser/visit_database.cc
+++ b/components/history/core/browser/visit_database.cc
@@ -128,7 +128,7 @@
             "visit_duration INTEGER DEFAULT 0 NOT NULL,"
             "incremented_omnibox_typed_score BOOLEAN DEFAULT FALSE NOT NULL,"
             "opener_visit INTEGER,"
-            // These two fields are non-null only for remote visits synced to
+            // These four fields are non-null only for remote visits synced to
             // the local machine. The `originator_cache_guid` is the unique
             // identifier for the originator machine the visit was originally
             // made on, and `originator_visit_id` is the `id` of the visit row
@@ -136,7 +136,9 @@
             // The tuple of (`originator_cache_guid`, `origin_visit_id`) is
             // globally unique.
             "originator_cache_guid TEXT,"
-            "originator_visit_id INTEGER)"))
+            "originator_visit_id INTEGER,"
+            "originator_from_visit INTEGER,"
+            "originator_opener_visit INTEGER)"))
       return false;
   }
 
@@ -192,6 +194,8 @@
   visit->opener_visit = statement.ColumnInt64(8);
   visit->originator_cache_guid = statement.ColumnString(9);
   visit->originator_visit_id = statement.ColumnInt64(10);
+  visit->originator_referring_visit = statement.ColumnInt64(11);
+  visit->originator_opener_visit = statement.ColumnInt64(12);
 }
 
 // static
@@ -252,8 +256,9 @@
       "INSERT INTO visits "
       "(url, visit_time, from_visit, transition, segment_id, "
       "visit_duration, incremented_omnibox_typed_score, opener_visit,"
-      "originator_cache_guid,originator_visit_id) "
-      "VALUES (?,?,?,?,?,?,?,?,?,?)"));
+      "originator_cache_guid,originator_visit_id,originator_from_visit,"
+      "originator_opener_visit) "
+      "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"));
   statement.BindInt64(0, visit->url_id);
   statement.BindInt64(1, visit->visit_time.ToInternalValue());
   statement.BindInt64(2, visit->referring_visit);
@@ -264,6 +269,8 @@
   statement.BindInt64(7, visit->opener_visit);
   statement.BindString(8, visit->originator_cache_guid);
   statement.BindInt64(9, visit->originator_visit_id);
+  statement.BindInt64(10, visit->originator_referring_visit);
+  statement.BindInt64(11, visit->originator_opener_visit);
 
   if (!statement.Run()) {
     DVLOG(0) << "Failed to execute visit insert statement:  "
@@ -1123,6 +1130,30 @@
          transaction.Commit();
 }
 
+bool VisitDatabase::MigrateVisitsAddOriginatorFromVisitAndOpenerVisitColumns() {
+  if (!GetDB().DoesTableExist("visits")) {
+    NOTREACHED() << " Visits table should exist before migration";
+    return false;
+  }
+
+  // Old versions don't have the originator_from_visit or
+  // originator_opener_visit columns; modify the table to add those.
+  if (!GetDB().DoesColumnExist("visits", "originator_from_visit")) {
+    if (!GetDB().Execute("ALTER TABLE visits "
+                         "ADD COLUMN originator_from_visit INTEGER")) {
+      return false;
+    }
+  }
+  if (!GetDB().DoesColumnExist("visits", "originator_opener_visit")) {
+    if (!GetDB().Execute("ALTER TABLE visits "
+                         "ADD COLUMN originator_opener_visit INTEGER")) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 bool VisitDatabase::VisitTableContainsAutoincrement() {
   // sqlite_schema has columns:
   //   type - "index" or "table".
diff --git a/components/history/core/browser/visit_database.h b/components/history/core/browser/visit_database.h
index 5db4fba..3d5e4cd 100644
--- a/components/history/core/browser/visit_database.h
+++ b/components/history/core/browser/visit_database.h
@@ -283,6 +283,11 @@
   // `originator_visit_id` columns.
   bool MigrateVisitsAutoincrementIdAndAddOriginatorColumns();
 
+  // Called by the derived classes to migrate the older visits table which
+  // doesn't have the `originator_from_visit` and `originator_opener_visit`
+  // columns.
+  bool MigrateVisitsAddOriginatorFromVisitAndOpenerVisitColumns();
+
   // Return true if the visits table's schema contains "AUTOINCREMENT".
   // false if table do not contain AUTOINCREMENT, or the table is not created.
   bool VisitTableContainsAutoincrement();
@@ -296,7 +301,7 @@
 #define HISTORY_VISIT_ROW_FIELDS                                        \
   " id,url,visit_time,from_visit,transition,segment_id,visit_duration," \
   "incremented_omnibox_typed_score,opener_visit,originator_cache_guid," \
-  "originator_visit_id "
+  "originator_visit_id,originator_from_visit,originator_opener_visit "
 
 }  // namespace history
 
diff --git a/components/history_clusters/core/history_clusters_db_tasks.cc b/components/history_clusters/core/history_clusters_db_tasks.cc
index 656d360..473dbd9 100644
--- a/components/history_clusters/core/history_clusters_db_tasks.cc
+++ b/components/history_clusters/core/history_clusters_db_tasks.cc
@@ -274,7 +274,8 @@
 }
 
 void GetAnnotatedVisitsToCluster::DoneRunOnMainThread() {
-  std::move(callback_).Run(annotated_visits_, continuation_params_);
+  std::move(callback_).Run(cluster_ids_, annotated_visits_,
+                           continuation_params_);
 }
 
 }  // namespace history_clusters
diff --git a/components/history_clusters/core/history_clusters_db_tasks.h b/components/history_clusters/core/history_clusters_db_tasks.h
index d1a8e18..6cd0d6f 100644
--- a/components/history_clusters/core/history_clusters_db_tasks.h
+++ b/components/history_clusters/core/history_clusters_db_tasks.h
@@ -26,8 +26,10 @@
 //   to invoke `GetRedirectChainStart()`.
 class GetAnnotatedVisitsToCluster : public history::HistoryDBTask {
  public:
-  using Callback = base::OnceCallback<void(std::vector<history::AnnotatedVisit>,
-                                           QueryClustersContinuationParams)>;
+  using Callback = base::OnceCallback<void(
+      std::vector<int64_t> cluster_ids,
+      std::vector<history::AnnotatedVisit> annotated_visits,
+      QueryClustersContinuationParams continuation_params)>;
 
   // For a given `end_time`, this returns an appropriate beginning time
   // designed to avoid breaking up internet browsing sessions. Before 4PM, it
@@ -97,6 +99,13 @@
   // visits, or vice versa.
   bool recent_first_ = true;
 
+  // Persisted clusters that contain visits in `annotated_visits_`. Not all
+  // annotated visits will be clustered and therefore represented
+  // in`cluster_ids_`. All annotated visits that are clustered will be
+  // represented. Retrieved from the history DB thread and returned through the
+  // callback on the main thread.
+  std::vector<int64_t> cluster_ids_;
+
   // Persisted visits retrieved from the history DB thread and returned through
   // the callback on the main thread.
   std::vector<history::AnnotatedVisit> annotated_visits_;
diff --git a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.cc b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.cc
index f5fe8df..fa002da 100644
--- a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.cc
+++ b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.cc
@@ -75,6 +75,8 @@
 
 void HistoryClustersServiceTaskGetMostRecentClusters::
     OnGotAnnotatedVisitsToCluster(
+        // Unused because clusters aren't persisted in this flow.
+        std::vector<int64_t> old_clusters_unused,
         std::vector<history::AnnotatedVisit> annotated_visits,
         QueryClustersContinuationParams continuation_params) {
   DCHECK(backend_);
diff --git a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.h b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.h
index b1eadbec..2de874c1 100644
--- a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.h
+++ b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.h
@@ -42,6 +42,8 @@
   // Invoked after `Start()` asyncly fetches annotated visits. Will asyncly
   // request clusters from `ClusteringBackend`.
   void OnGotAnnotatedVisitsToCluster(
+      // Unused because clusters aren't persisted in this flow.
+      std::vector<int64_t> old_clusters_unused,
       std::vector<history::AnnotatedVisit> annotated_visits,
       QueryClustersContinuationParams continuation_params);
 
diff --git a/components/history_clusters/core/history_clusters_service_unittest.cc b/components/history_clusters/core/history_clusters_service_unittest.cc
index 16730ee..96848c0 100644
--- a/components/history_clusters/core/history_clusters_service_unittest.cc
+++ b/components/history_clusters/core/history_clusters_service_unittest.cc
@@ -980,7 +980,8 @@
         std::make_unique<GetAnnotatedVisitsToCluster>(
             IncompleteVisitMap{}, base::Time(), continuation_params, false,
             base::BindLambdaForTesting(
-                [&](std::vector<history::AnnotatedVisit> visits_temp,
+                [&](std::vector<int64_t> old_clusters,
+                    std::vector<history::AnnotatedVisit> visits_temp,
                     QueryClustersContinuationParams continuation_params_temp) {
                   visits = visits_temp;
                   continuation_params = continuation_params_temp;
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn
index d78a53c7..9bca00da 100644
--- a/components/metrics/BUILD.gn
+++ b/components/metrics/BUILD.gn
@@ -531,8 +531,8 @@
 
   if (is_chromeos_ash) {
     deps += [
+      "//chromeos/ash/components/network:test_support",
       "//chromeos/dbus:test_support",
-      "//chromeos/network:test_support",
     ]
   }
 
diff --git a/components/metrics/clean_exit_beacon_unittest.cc b/components/metrics/clean_exit_beacon_unittest.cc
index 2d8c089e..d5c6d7ab 100644
--- a/components/metrics/clean_exit_beacon_unittest.cc
+++ b/components/metrics/clean_exit_beacon_unittest.cc
@@ -414,30 +414,14 @@
       "Variations.ExtendedSafeMode.BeaconFileWrite", 1, 1);
 }
 
-// Verify that attempting to write synchronously DCHECKs for clients that do not
-// belong to the SignalAndWriteViaFileUtil experiment group.
-TEST_F(CleanExitBeaconTest,
-       WriteBeaconValue_SynchronousWriteDcheck_ControlGroup) {
-  SetUpExtendedSafeModeExperiment(variations::kControlGroup);
-  ASSERT_EQ(variations::kControlGroup, base::FieldTrialList::FindFullName(
-                                           variations::kExtendedSafeModeTrial));
-
-  TestCleanExitBeacon clean_exit_beacon(&prefs_, user_data_dir_.GetPath());
-  EXPECT_DCHECK_DEATH(
-      clean_exit_beacon.WriteBeaconValue(/*exited_cleanly=*/false,
-                                         /*is_extended_safe_mode=*/true));
-
-  // Verify metrics.
-  histogram_tester_.ExpectTotalCount(
-      "Variations.ExtendedSafeMode.BeaconFileWrite", 0);
-}
-
 // Verify that there's a DCHECK when an Extended Variations Safe Mode client
 // attempts to write a clean beacon with |is_extended_safe_mode| set to true.
 // |is_extended_safe_mode| should only be set to true in one call site:
 // VariationsFieldTrialCreator::MaybeExtendVariationsSafeMode().
+//
+// TODO(crbug/1241702): Re-enable this test once the FieldTrial is cleaned up.
 TEST_F(CleanExitBeaconTest,
-       WriteBeaconValue_SynchronousWriteDcheck_ExperimentGroup) {
+       DISABLED_WriteBeaconValue_SynchronousWriteDcheck_ExperimentGroup) {
   SetUpExtendedSafeModeExperiment(variations::kEnabledGroup);
   ASSERT_EQ(variations::kEnabledGroup, base::FieldTrialList::FindFullName(
                                            variations::kExtendedSafeModeTrial));
diff --git a/components/metrics/metrics_pref_names.cc b/components/metrics/metrics_pref_names.cc
index b5e39cb..b0f9d3c 100644
--- a/components/metrics/metrics_pref_names.cc
+++ b/components/metrics/metrics_pref_names.cc
@@ -169,11 +169,6 @@
 const char kStabilityGmsCoreVersion[] =
     "user_experience_metrics.stability.gms_core_version";
 
-// Number of times a gpu process crashed since the last report. Currently only
-// recorded on Android.
-const char kStabilityGpuCrashCount[] =
-    "user_experience_metrics.stability.gpu_crash_count";
-
 #if BUILDFLAG(IS_ANDROID)
 // Number of times the application was launched since last report. Used on
 // Android platforms as WebView may still be interested in this metric.
diff --git a/components/metrics/metrics_pref_names.h b/components/metrics/metrics_pref_names.h
index ec9bbe74..26ad695 100644
--- a/components/metrics/metrics_pref_names.h
+++ b/components/metrics/metrics_pref_names.h
@@ -56,7 +56,6 @@
 extern const char kStabilityFileMetricsUnsentSamplesCount[];
 extern const char kStabilityFileMetricsUnsentFilesCount[];
 extern const char kStabilityGmsCoreVersion[];
-extern const char kStabilityGpuCrashCount[];
 #if BUILDFLAG(IS_ANDROID)
 extern const char kStabilityLaunchCount[];
 extern const char kStabilityRendererLaunchCount[];
diff --git a/components/metrics/net/DEPS b/components/metrics/net/DEPS
index eacfe8fa..06c832ae 100644
--- a/components/metrics/net/DEPS
+++ b/components/metrics/net/DEPS
@@ -1,6 +1,6 @@
 include_rules = [
+  "+chromeos/ash/components/network",
   "+chromeos/dbus",
-  "+chromeos/network",
   "+components/encrypted_messages",
   "+components/variations",
   "+content/public/test/browser_task_environment.h",
diff --git a/components/metrics/net/network_metrics_provider_unittest.cc b/components/metrics/net/network_metrics_provider_unittest.cc
index bd6b6fda..9c0ac055 100644
--- a/components/metrics/net/network_metrics_provider_unittest.cc
+++ b/components/metrics/net/network_metrics_provider_unittest.cc
@@ -17,7 +17,7 @@
 #include "third_party/metrics_proto/system_profile.pb.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chromeos/network/network_handler_test_helper.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(IS_IOS)
diff --git a/components/metrics/stability_metrics_helper.cc b/components/metrics/stability_metrics_helper.cc
index 0222e88..e9ca1fe 100644
--- a/components/metrics/stability_metrics_helper.cc
+++ b/components/metrics/stability_metrics_helper.cc
@@ -86,12 +86,6 @@
     local_state_->SetInteger(prefs::kStabilityPageLoadCount, 0);
   }
 
-  count = local_state_->GetInteger(prefs::kStabilityGpuCrashCount);
-  if (count) {
-    stability_proto->set_gpu_crash_count(count);
-    local_state_->SetInteger(prefs::kStabilityGpuCrashCount, 0);
-  }
-
   count = local_state_->GetInteger(prefs::kStabilityRendererCrashCount);
   if (count) {
     stability_proto->set_renderer_crash_count(count);
@@ -117,7 +111,6 @@
 void StabilityMetricsHelper::ClearSavedStabilityMetrics() {
   // Clear all the prefs used in this class in UMA reports.
   local_state_->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
-  local_state_->SetInteger(prefs::kStabilityGpuCrashCount, 0);
   local_state_->SetInteger(prefs::kStabilityPageLoadCount, 0);
   local_state_->SetInteger(prefs::kStabilityRendererCrashCount, 0);
 #if BUILDFLAG(IS_ANDROID)
@@ -129,7 +122,6 @@
 void StabilityMetricsHelper::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterIntegerPref(prefs::kStabilityExtensionRendererCrashCount,
                                 0);
-  registry->RegisterIntegerPref(prefs::kStabilityGpuCrashCount, 0);
   registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0);
   registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
 #if BUILDFLAG(IS_ANDROID)
@@ -143,7 +135,6 @@
 }
 
 void StabilityMetricsHelper::IncreaseGpuCrashCount() {
-  IncrementPrefValue(prefs::kStabilityGpuCrashCount);
   RecordStabilityEvent(StabilityEventType::kGpuCrash);
 }
 
diff --git a/components/mirroring/browser/single_client_video_capture_host.cc b/components/mirroring/browser/single_client_video_capture_host.cc
index 98b8507..610961c 100644
--- a/components/mirroring/browser/single_client_video_capture_host.cc
+++ b/components/mirroring/browser/single_client_video_capture_host.cc
@@ -186,6 +186,11 @@
   // Ignore this call.
 }
 
+void SingleClientVideoCaptureHost::OnNewCropVersion(uint32_t crop_version) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // Ignore this call.
+}
+
 void SingleClientVideoCaptureHost::OnFrameWithEmptyRegionCapture() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Ignore this call.
diff --git a/components/mirroring/browser/single_client_video_capture_host.h b/components/mirroring/browser/single_client_video_capture_host.h
index 72835340..c2d737b1 100644
--- a/components/mirroring/browser/single_client_video_capture_host.h
+++ b/components/mirroring/browser/single_client_video_capture_host.h
@@ -89,6 +89,7 @@
   void OnBufferRetired(int buffer_id) override;
   void OnError(media::VideoCaptureError error) override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnLog(const std::string& message) override;
   void OnStarted() override;
diff --git a/components/mirroring/browser/single_client_video_capture_host_unittest.cc b/components/mirroring/browser/single_client_video_capture_host_unittest.cc
index a19cc4df..18d1b16 100644
--- a/components/mirroring/browser/single_client_video_capture_host_unittest.cc
+++ b/components/mirroring/browser/single_client_video_capture_host_unittest.cc
@@ -157,6 +157,8 @@
     OnBufferDestroyedCall(buffer_id);
   }
 
+  MOCK_METHOD1(OnNewCropVersion, void(uint32_t crop_version));
+
   MOCK_METHOD1(OnStateChangedCall, void(media::mojom::VideoCaptureState state));
   MOCK_METHOD1(OnVideoCaptureErrorCall, void(media::VideoCaptureError error));
   void OnStateChanged(media::mojom::VideoCaptureResultPtr result) override {
diff --git a/components/mirroring/service/video_capture_client.cc b/components/mirroring/service/video_capture_client.cc
index f1ac09d..12a88b5 100644
--- a/components/mirroring/service/video_capture_client.cc
+++ b/components/mirroring/service/video_capture_client.cc
@@ -290,6 +290,8 @@
     client_buffers_.erase(buffer_iter);
 }
 
+void VideoCaptureClient::OnNewCropVersion(uint32_t crop_version) {}
+
 void VideoCaptureClient::OnClientBufferFinished(int buffer_id,
                                                 MappingKeepAlive mapping) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/mirroring/service/video_capture_client.h b/components/mirroring/service/video_capture_client.h
index ea83708..eb20500 100644
--- a/components/mirroring/service/video_capture_client.h
+++ b/components/mirroring/service/video_capture_client.h
@@ -68,6 +68,7 @@
       media::mojom::ReadyBufferPtr buffer,
       std::vector<media::mojom::ReadyBufferPtr> scaled_buffers) override;
   void OnBufferDestroyed(int32_t buffer_id) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
 
  private:
   using BufferFinishedCallback = base::OnceCallback<void()>;
diff --git a/components/ntp_tiles/custom_links_store.cc b/components/ntp_tiles/custom_links_store.cc
index 1e21fa3..124da86 100644
--- a/components/ntp_tiles/custom_links_store.cc
+++ b/components/ntp_tiles/custom_links_store.cc
@@ -34,10 +34,10 @@
 std::vector<CustomLinksManager::Link> CustomLinksStore::RetrieveLinks() {
   std::vector<CustomLinksManager::Link> links;
 
-  const base::Value::List* stored_links =
+  const base::Value::List& stored_links =
       prefs_->GetValueList(prefs::kCustomLinksList);
 
-  for (const base::Value& link : *stored_links) {
+  for (const base::Value& link : stored_links) {
     const std::string* url_string =
         link.GetDict().FindString(kDictionaryKeyUrl);
     const std::string* title_string =
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index 93a7e1b2a..1200653 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -765,11 +765,9 @@
 
 // static
 bool MostVisitedSites::WasNtpAppMigratedToWebApp(PrefService* prefs, GURL url) {
-  const base::Value::List* migrated_apps =
+  const base::Value::List& migrated_apps =
       prefs->GetValueList(webapps::kWebAppsMigratedPreinstalledApps);
-  if (!migrated_apps)
-    return false;
-  for (const auto& val : *migrated_apps) {
+  for (const auto& val : migrated_apps) {
     if (val.is_string() && val.GetString() == url.host())
       return true;
   }
diff --git a/components/ntp_tiles/popular_sites_impl.cc b/components/ntp_tiles/popular_sites_impl.cc
index 21cf92f..5b5b9d67 100644
--- a/components/ntp_tiles/popular_sites_impl.cc
+++ b/components/ntp_tiles/popular_sites_impl.cc
@@ -275,7 +275,7 @@
       url_loader_factory_(std::move(url_loader_factory)),
       is_fallback_(false),
       sections_(
-          ParseSites(*prefs->GetValueList(prefs::kPopularSitesJsonPref),
+          ParseSites(prefs->GetValueList(prefs::kPopularSitesJsonPref),
                      prefs_->GetInteger(prefs::kPopularSitesVersionPref))) {}
 
 PopularSitesImpl::~PopularSitesImpl() {}
diff --git a/components/omnibox/browser/autocomplete_provider.h b/components/omnibox/browser/autocomplete_provider.h
index 24c8e6a2..98cdedf 100644
--- a/components/omnibox/browser/autocomplete_provider.h
+++ b/components/omnibox/browser/autocomplete_provider.h
@@ -277,7 +277,14 @@
   // Returns the set of matches for the current query.
   const ACMatches& matches() const { return matches_; }
 
-  // Returns whether the provider is done processing the query.
+  // Returns whether the provider is done processing the last `Start()` request.
+  // Should not be set true for `StartPrefetch()` requests in order to remain
+  // consistent with `AutocompleteController::done()`; i.e., if `done_` is false
+  // for any provider, then the `AutocompleteController::done_` must also be
+  // false. This ensures the controller can determine when each provider
+  // finishes processing async requests. Should be true after either `Stop()` or
+  // `Start()` with `AutocompleteInput.want_asynchronous_matches` set to false
+  // are called.
   bool done() const { return done_; }
 
   // Returns this provider's type.
diff --git a/components/omnibox/browser/remote_suggestions_service.cc b/components/omnibox/browser/remote_suggestions_service.cc
index 2e3b2798..dec745f 100644
--- a/components/omnibox/browser/remote_suggestions_service.cc
+++ b/components/omnibox/browser/remote_suggestions_service.cc
@@ -66,10 +66,10 @@
                                                     search_terms_data));
 }
 
-void RemoteSuggestionsService::CreateSuggestionsRequest(
+std::unique_ptr<network::SimpleURLLoader>
+RemoteSuggestionsService::StartSuggestionsRequest(
     const TemplateURLRef::SearchTermsArgs& search_terms_args,
     const TemplateURLService* template_url_service,
-    StartCallback start_callback,
     CompletionCallback completion_callback) {
   const GURL suggest_url = EndpointUrl(search_terms_args, template_url_service);
   DCHECK(suggest_url.is_valid());
@@ -113,25 +113,12 @@
   // Try to attach cookies for signed in user.
   request->site_for_cookies = net::SiteForCookies::FromUrl(suggest_url);
   AddVariationHeaders(request.get());
-  StartDownloadAndTransferLoader(std::move(request), std::string(),
-                                 traffic_annotation, std::move(start_callback),
-                                 std::move(completion_callback));
-}
 
-void RemoteSuggestionsService::StartDownloadAndTransferLoader(
-    std::unique_ptr<network::ResourceRequest> request,
-    std::string request_body,
-    net::NetworkTrafficAnnotationTag traffic_annotation,
-    StartCallback start_callback,
-    CompletionCallback completion_callback) {
+  // Make loader and start download.
   std::unique_ptr<network::SimpleURLLoader> loader =
       network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
-  if (!request_body.empty()) {
-    loader->AttachStringForUpload(request_body, "application/json");
-  }
   loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
       url_loader_factory_.get(),
       base::BindOnce(std::move(completion_callback), loader.get()));
-
-  std::move(start_callback).Run(std::move(loader));
+  return loader;
 }
diff --git a/components/omnibox/browser/remote_suggestions_service.h b/components/omnibox/browser/remote_suggestions_service.h
index 0ab7f63..0d4aa27b 100644
--- a/components/omnibox/browser/remote_suggestions_service.h
+++ b/components/omnibox/browser/remote_suggestions_service.h
@@ -17,7 +17,6 @@
 #include "url/gurl.h"
 
 namespace network {
-struct ResourceRequest;
 class SharedURLLoaderFactory;
 class SimpleURLLoader;
 }  // namespace network
@@ -46,9 +45,6 @@
   RemoteSuggestionsService(const RemoteSuggestionsService&) = delete;
   RemoteSuggestionsService& operator=(const RemoteSuggestionsService&) = delete;
 
-  using StartCallback = base::OnceCallback<void(
-      std::unique_ptr<network::SimpleURLLoader> loader)>;
-
   using CompletionCallback =
       base::OnceCallback<void(const network::SimpleURLLoader* source,
                               std::unique_ptr<std::string> response_body)>;
@@ -69,10 +65,9 @@
   static GURL EndpointUrl(TemplateURLRef::SearchTermsArgs search_terms_args,
                           const TemplateURLService* template_url_service);
 
-  // Creates a loader for remote suggestions for |search_terms_args| and passes
-  // the loader to |start_callback|. It uses a number of signals to create the
-  // loader, including field trial / experimental parameters, and it may
-  // pass a nullptr to |start_callback| (see below for details).
+  // Creates and returns a loader for remote suggestions for |search_terms_args|
+  // and passes the loader to |start_callback|. It uses a number of signals to
+  // create the loader, including field trial / experimental parameters.
   //
   // |search_terms_args| encapsulates the arguments sent to the remote service.
   // If |search_terms_args.current_page_url| is empty, the system will never use
@@ -81,25 +76,10 @@
   //
   // |template_url_service| may be null, but some services may be disabled.
   //
-  // |start_callback| is called to transfer ownership of the created loader to
-  //  whatever function/class receives the callback.
-  //
   // |completion_callback| will be invoked when the transfer is done.
-  void CreateSuggestionsRequest(
+  std::unique_ptr<network::SimpleURLLoader> StartSuggestionsRequest(
       const TemplateURLRef::SearchTermsArgs& search_terms_args,
       const TemplateURLService* template_url_service,
-      StartCallback start_callback,
-      CompletionCallback completion_callback);
-
- private:
-  // Activates a loader for |request|, wiring it up to |completion_callback|,
-  // and calls |start_callback|.  If |request_body| isn't empty, it will be
-  // attached as upload bytes.
-  void StartDownloadAndTransferLoader(
-      std::unique_ptr<network::ResourceRequest> request,
-      std::string request_body,
-      net::NetworkTrafficAnnotationTag traffic_annotation,
-      StartCallback start_callback,
       CompletionCallback completion_callback);
 
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
diff --git a/components/omnibox/browser/remote_suggestions_service_unittest.cc b/components/omnibox/browser/remote_suggestions_service_unittest.cc
index 138877a..546e31f 100644
--- a/components/omnibox/browser/remote_suggestions_service_unittest.cc
+++ b/components/omnibox/browser/remote_suggestions_service_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/test/bind.h"
 #include "base/test/test_mock_time_task_runner.h"
-#include "components/omnibox/common/omnibox_features.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/variations/scoped_variations_ids_provider.h"
 #include "net/base/load_flags.h"
@@ -36,8 +35,6 @@
 
   void RunAndWait() { mock_task_runner_->FastForwardUntilNoTasksRemain(); }
 
-  void OnRequestStart(std::unique_ptr<network::SimpleURLLoader> loader) {}
-
   void OnRequestComplete(const network::SimpleURLLoader* source,
                          std::unique_ptr<std::string> response_body) {}
 
@@ -59,10 +56,8 @@
   TemplateURLService template_url_service(nullptr, 0);
   TemplateURLRef::SearchTermsArgs search_terms_args;
   search_terms_args.current_page_url = "https://www.google.com/";
-  service.CreateSuggestionsRequest(
+  service.StartSuggestionsRequest(
       search_terms_args, &template_url_service,
-      base::BindOnce(&RemoteSuggestionsServiceTest::OnRequestStart,
-                     base::Unretained(this)),
       base::BindOnce(&RemoteSuggestionsServiceTest::OnRequestComplete,
                      base::Unretained(this)));
 
@@ -87,10 +82,8 @@
   TemplateURLRef::SearchTermsArgs search_terms_args;
   search_terms_args.current_page_url = "https://www.google.com/";
   search_terms_args.bypass_cache = true;
-  service.CreateSuggestionsRequest(
+  service.StartSuggestionsRequest(
       search_terms_args, &template_url_service,
-      base::BindOnce(&RemoteSuggestionsServiceTest::OnRequestStart,
-                     base::Unretained(this)),
       base::BindOnce(&RemoteSuggestionsServiceTest::OnRequestComplete,
                      base::Unretained(this)));
 
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc
index 0e359e0..e1747c74 100644
--- a/components/omnibox/browser/zero_suggest_provider.cc
+++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -207,34 +207,40 @@
   if (result_type_running_ == NONE)
     return;
 
-  done_ = false;
+  if (is_prefetch)
+    prefetch_done_ = false;
+  else
+    done_ = false;
 
   const std::string original_response = MaybeUseStoredResponse();
 
   search_terms_args.current_page_url =
       result_type_running_ == REMOTE_SEND_URL ? current_query_ : std::string();
-  client()
-      ->GetRemoteSuggestionsService(/*create_if_necessary=*/true)
-      ->CreateSuggestionsRequest(
-          search_terms_args, client()->GetTemplateURLService(),
-          base::BindOnce(
-              &ZeroSuggestProvider::OnRemoteSuggestionsLoaderAvailable,
-              weak_ptr_factory_.GetWeakPtr(), is_prefetch),
-          base::BindOnce(&ZeroSuggestProvider::OnURLLoadComplete,
-                         weak_ptr_factory_.GetWeakPtr(), client()->GetWeakPtr(),
-                         search_terms_args, is_prefetch, original_response,
-                         base::TimeTicks::Now()));
+  // Grab ownership of the loader until results come in to
+  // `OnURLLoadComplete()`.
+  loader_ = client()
+                ->GetRemoteSuggestionsService(/*create_if_necessary=*/true)
+                ->StartSuggestionsRequest(
+                    search_terms_args, client()->GetTemplateURLService(),
+                    base::BindOnce(&ZeroSuggestProvider::OnURLLoadComplete,
+                                   weak_ptr_factory_.GetWeakPtr(),
+                                   client()->GetWeakPtr(), search_terms_args,
+                                   is_prefetch, original_response,
+                                   base::TimeTicks::Now()));
+
+  LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT,
+                               /*is_prefetch=*/!prefetch_done_);
 }
 
 void ZeroSuggestProvider::Stop(bool clear_cached_results,
                                bool due_to_user_inactivity) {
   if (loader_) {
     LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED,
-                                 /*is_prefetch=*/is_prefetch_loader_);
+                                 /*is_prefetch=*/!prefetch_done_);
   }
   loader_.reset();
-  is_prefetch_loader_ = false;
   counterfactual_loader_.reset();
+  prefetch_done_ = true;
   done_ = true;
   result_type_running_ = NONE;
 
@@ -332,7 +338,7 @@
     base::TimeTicks request_time,
     const network::SimpleURLLoader* source,
     std::unique_ptr<std::string> response_body) {
-  DCHECK(!done_);
+  DCHECK(!done_ || !prefetch_done_);
   DCHECK_EQ(loader_.get(), source);
 
   LogOmniboxZeroSuggestRequestRoundTripTime(
@@ -350,16 +356,14 @@
     // Make sure the request is not cacheable.
     search_terms_args.zero_suggest_cache_duration_sec = 0;
 
-    client->GetRemoteSuggestionsService(/*create_if_necessary=*/true)
-        ->CreateSuggestionsRequest(
-            search_terms_args, client->GetTemplateURLService(),
-            base::BindOnce(&ZeroSuggestProvider::
-                               OnRemoteSuggestionsCounterfactualLoaderAvailable,
-                           weak_ptr_factory_.GetWeakPtr()),
-            base::BindOnce(
-                &ZeroSuggestProvider::OnCounterfactualURLLoadComplete,
-                weak_ptr_factory_.GetWeakPtr(), is_prefetch,
-                original_response));
+    counterfactual_loader_ =
+        client->GetRemoteSuggestionsService(/*create_if_necessary=*/true)
+            ->StartSuggestionsRequest(
+                search_terms_args, client->GetTemplateURLService(),
+                base::BindOnce(
+                    &ZeroSuggestProvider::OnCounterfactualURLLoadComplete,
+                    weak_ptr_factory_.GetWeakPtr(), is_prefetch,
+                    original_response));
   }
 
   const bool response_received =
@@ -371,7 +375,7 @@
       UpdateResults(SearchSuggestionParser::ExtractJsonData(
           source, std::move(response_body)));
   loader_.reset();
-  is_prefetch_loader_ = false;
+  prefetch_done_ = true;
   done_ = true;
   result_type_running_ = NONE;
 
@@ -453,22 +457,6 @@
   return match;
 }
 
-void ZeroSuggestProvider::OnRemoteSuggestionsLoaderAvailable(
-    bool is_prefetch,
-    std::unique_ptr<network::SimpleURLLoader> loader) {
-  // RemoteSuggestionsService has already started |loader|, so here it's
-  // only necessary to grab its ownership until results come in to
-  // OnURLLoadComplete().
-  loader_ = std::move(loader);
-  is_prefetch_loader_ = is_prefetch;
-  LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT, is_prefetch);
-}
-
-void ZeroSuggestProvider::OnRemoteSuggestionsCounterfactualLoaderAvailable(
-    std::unique_ptr<network::SimpleURLLoader> loader) {
-  counterfactual_loader_ = std::move(loader);
-}
-
 void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() {
   matches_.clear();
 
diff --git a/components/omnibox/browser/zero_suggest_provider.h b/components/omnibox/browser/zero_suggest_provider.h
index fb1e0cf..e43d0bc 100644
--- a/components/omnibox/browser/zero_suggest_provider.h
+++ b/components/omnibox/browser/zero_suggest_provider.h
@@ -176,19 +176,6 @@
   // page.
   AutocompleteMatch MatchForCurrentText();
 
-  // Called when RemoteSuggestionsService starts `loader` for the provider to
-  // take over its ownership. `is_prefetch` is bound to this callback and
-  // indicates if the request is a prefetch one. The value of `is_prefetch` is
-  // stored in `is_prefetch_loader_` for the duration of the loader's lifetime.
-  void OnRemoteSuggestionsLoaderAvailable(
-      bool is_prefetch,
-      std::unique_ptr<network::SimpleURLLoader> loader);
-
-  // Serves the same purpose as OnRemoteSuggestionsLoaderAvailable for the
-  // counterfactual requests.
-  void OnRemoteSuggestionsCounterfactualLoaderAvailable(
-      std::unique_ptr<network::SimpleURLLoader> loader);
-
   // Whether zero suggest suggestions are allowed in the given context.
   // Invoked early, confirms all the external conditions for ZeroSuggest are
   // met.
@@ -234,9 +221,10 @@
   // Loader used to retrieve results.
   std::unique_ptr<network::SimpleURLLoader> loader_;
 
-  // Indicate whether `loader_` is retrieving prefetch results. Used for metrics
-  // when the provider is stopped.
-  bool is_prefetch_loader_;
+  // Like `AutocompleteProvider::done_`, but for prefetch requests. Used for
+  // metrics when the provider is stopped. `done_` and `prefetch_done_` should
+  // never both be true, a `Start()` request stops ongoing requests.
+  bool prefetch_done_;
 
   // Loader used to retrieve counterfactual results.
   std::unique_ptr<network::SimpleURLLoader> counterfactual_loader_;
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index 971a9049..ff833501 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -256,7 +256,6 @@
     "ui/password_check_referrer.h",
     "ui/password_undo_helper.cc",
     "ui/password_undo_helper.h",
-    "ui/plaintext_reason.h",
     "ui/post_save_compromised_helper.cc",
     "ui/post_save_compromised_helper.h",
     "ui/saved_passwords_presenter.cc",
diff --git a/components/password_manager/core/browser/password_ui_utils.cc b/components/password_manager/core/browser/password_ui_utils.cc
index 465d896..2df53647 100644
--- a/components/password_manager/core/browser/password_ui_utils.cc
+++ b/components/password_manager/core/browser/password_ui_utils.cc
@@ -17,6 +17,7 @@
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/password_form_metrics_recorder.h"
+#include "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #include "components/url_formatter/elide_url.h"
 
 namespace password_manager {
@@ -29,6 +30,26 @@
 constexpr char kPlayStoreAppPrefix[] =
     "https://play.google.com/store/apps/details?id=";
 
+std::string GetShownOrigin(const FacetURI& facet_uri,
+                           const std::string& app_display_name,
+                           const GURL& url) {
+  if (facet_uri.IsValidAndroidFacetURI()) {
+    return app_display_name.empty()
+               ? SplitByDotAndReverse(facet_uri.android_package_name())
+               : app_display_name;
+  } else {
+    return password_manager::GetShownOrigin(url::Origin::Create(url));
+  }
+}
+
+GURL GetShownURL(const FacetURI& facet_uri, const GURL& url) {
+  if (facet_uri.IsValidAndroidFacetURI()) {
+    return GURL(kPlayStoreAppPrefix + facet_uri.android_package_name());
+  } else {
+    return url;
+  }
+}
+
 }  // namespace
 
 std::string SplitByDotAndReverse(base::StringPiece host) {
@@ -40,22 +61,23 @@
 
 std::pair<std::string, GURL> GetShownOriginAndLinkUrl(
     const PasswordForm& password_form) {
-  std::string shown_origin;
-  GURL link_url;
-
   FacetURI facet_uri =
       FacetURI::FromPotentiallyInvalidSpec(password_form.signon_realm);
-  if (facet_uri.IsValidAndroidFacetURI()) {
-    shown_origin = password_form.app_display_name.empty()
-                       ? SplitByDotAndReverse(facet_uri.android_package_name())
-                       : password_form.app_display_name;
-    link_url = GURL(kPlayStoreAppPrefix + facet_uri.android_package_name());
-  } else {
-    shown_origin = GetShownOrigin(url::Origin::Create(password_form.url));
-    link_url = password_form.url;
-  }
+  return {GetShownOrigin(facet_uri, password_form.app_display_name,
+                         password_form.url),
+          GetShownURL(facet_uri, password_form.url)};
+}
 
-  return {std::move(shown_origin), std::move(link_url)};
+std::string GetShownOrigin(const CredentialUIEntry& credential) {
+  FacetURI facet_uri =
+      FacetURI::FromPotentiallyInvalidSpec(credential.signon_realm);
+  return GetShownOrigin(facet_uri, credential.app_display_name, credential.url);
+}
+
+GURL GetShownUrl(const CredentialUIEntry& credential) {
+  FacetURI facet_uri =
+      FacetURI::FromPotentiallyInvalidSpec(credential.signon_realm);
+  return GetShownURL(facet_uri, credential.url);
 }
 
 std::string GetShownOrigin(const url::Origin& origin) {
diff --git a/components/password_manager/core/browser/password_ui_utils.h b/components/password_manager/core/browser/password_ui_utils.h
index a0a2a33..5a8621b 100644
--- a/components/password_manager/core/browser/password_ui_utils.h
+++ b/components/password_manager/core/browser/password_ui_utils.h
@@ -18,6 +18,7 @@
 
 class PasswordFormManagerForUI;
 struct PasswordForm;
+struct CredentialUIEntry;
 
 // Reverses order of labels in hostname.
 std::string SplitByDotAndReverse(base::StringPiece host);
@@ -32,9 +33,15 @@
 //  For Android credentials the returned origin is set to the Play Store name
 //  if available, otherwise it is the reversed package name (e.g.
 //  com.example.android gets transformed to android.example.com).
+// TODO(crbug.com/1330906) Replace the usage with GetShownOrigin and GetShownUrl
 std::pair<std::string, GURL> GetShownOriginAndLinkUrl(
     const PasswordForm& password_form);
 
+// Together have the same result as |GetShownOriginAndLinkUrl| but works with
+// |CredentialUIEntry|.
+std::string GetShownOrigin(const CredentialUIEntry& credential);
+GURL GetShownUrl(const CredentialUIEntry& credential);
+
 // Returns a string suitable for security display to the user (just like
 // |FormatUrlForSecurityDisplay| with OMIT_HTTP_AND_HTTPS) based on origin of
 // |password_form|) and without prefixes "m.", "mobile." or "www.".
diff --git a/components/password_manager/core/browser/ui/plaintext_reason.h b/components/password_manager/core/browser/ui/plaintext_reason.h
deleted file mode 100644
index fa0a533..0000000
--- a/components/password_manager/core/browser/ui/plaintext_reason.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2020 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_PASSWORD_MANAGER_CORE_BROWSER_UI_PLAINTEXT_REASON_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_PLAINTEXT_REASON_H_
-
-namespace password_manager {
-
-// Possible reasons why a plaintext password was requested.
-enum class PlaintextReason {
-  kView,
-  kCopy,
-  kEdit,
-};
-
-}  // namespace password_manager
-
-#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_PLAINTEXT_REASON_H_
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
index 4f08cae..782ac14e 100644
--- a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
+++ b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
@@ -18,7 +18,6 @@
 #include "components/password_manager/core/browser/password_list_sorter.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/ui/credential_ui_entry.h"
 #include "components/password_manager/core/browser/ui/password_undo_helper.h"
 #include "url/gurl.h"
 
@@ -202,13 +201,8 @@
 
 bool SavedPasswordsPresenter::EditSavedCredentials(
     const CredentialUIEntry& credential) {
-  const auto range =
-      sort_key_to_password_forms_.equal_range(credential.key().value());
-  std::vector<PasswordForm> forms_to_change;
-  base::ranges::transform(range.first, range.second,
-                          std::back_inserter(forms_to_change),
-                          [](const auto& pair) { return pair.second; });
-
+  std::vector<PasswordForm> forms_to_change =
+      GetCorrespondingPasswordForms(credential.key());
   if (forms_to_change.empty())
     return false;
 
@@ -351,6 +345,16 @@
   return credentials;
 }
 
+std::vector<PasswordForm>
+SavedPasswordsPresenter::GetCorrespondingPasswordForms(
+    const CredentialKey& key) const {
+  const auto range = sort_key_to_password_forms_.equal_range(key.value());
+  std::vector<PasswordForm> forms;
+  base::ranges::transform(range.first, range.second, std::back_inserter(forms),
+                          [](const auto& pair) { return pair.second; });
+  return forms;
+}
+
 void SavedPasswordsPresenter::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
 }
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter.h b/components/password_manager/core/browser/ui/saved_passwords_presenter.h
index 08b65b2..5495dc10 100644
--- a/components/password_manager/core/browser/ui/saved_passwords_presenter.h
+++ b/components/password_manager/core/browser/ui/saved_passwords_presenter.h
@@ -15,11 +15,10 @@
 #include "base/strings/string_piece_forward.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
+#include "components/password_manager/core/browser/ui/credential_ui_entry.h"
 
 namespace password_manager {
 
-struct PasswordForm;
-struct CredentialUIEntry;
 class PasswordUndoHelper;
 
 // This interface provides a way for clients to obtain a list of all saved
@@ -126,6 +125,10 @@
   std::vector<PasswordForm> GetUniquePasswordForms() const;
   std::vector<CredentialUIEntry> GetSavedCredentials() const;
 
+  // Returns PasswordForms corresponding to |key|.
+  std::vector<PasswordForm> GetCorrespondingPasswordForms(
+      const CredentialKey& key) const;
+
   // Allows clients and register and de-register themselves.
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn
index 1f590635..f1df16fe 100644
--- a/components/policy/core/common/BUILD.gn
+++ b/components/policy/core/common/BUILD.gn
@@ -237,8 +237,6 @@
       "management/platform_management_status_provider_win.h",
       "policy_loader_win.cc",
       "policy_loader_win.h",
-      "registry_watcher_win.cc",
-      "registry_watcher_win.h",
     ]
     libs = [
       "netapi32.lib",
@@ -562,10 +560,7 @@
     data = [ "//chrome/test/data/policy/" ]
   }
   if (is_win) {
-    sources += [
-      "policy_loader_win_unittest.cc",
-      "registry_watcher_win_unittest.cc",
-    ]
+    sources += [ "policy_loader_win_unittest.cc" ]
   }
   if (is_chromeos_lacros) {
     sources += [ "policy_loader_lacros_unittest.cc" ]
diff --git a/components/policy/core/common/policy_loader_win.cc b/components/policy/core/common/policy_loader_win.cc
index 82dcfeb..fe063a3 100644
--- a/components/policy/core/common/policy_loader_win.cc
+++ b/components/policy/core/common/policy_loader_win.cc
@@ -223,8 +223,7 @@
 PolicyLoaderWin::PolicyLoaderWin(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     ManagementService* management_service,
-    const std::wstring& chrome_policy_key,
-    bool is_dev_registry_key_supported)
+    const std::wstring& chrome_policy_key)
     : AsyncPolicyLoader(task_runner,
                         management_service,
                         /*periodic_updates=*/true),
@@ -237,10 +236,7 @@
           base::WaitableEvent::ResetPolicy::AUTOMATIC,
           base::WaitableEvent::InitialState::NOT_SIGNALED),
       user_policy_watcher_failed_(false),
-      machine_policy_watcher_failed_(false),
-      registry_watcher_(
-          RegistryWatcherWin::MaybeCreate(chrome_policy_key,
-                                          is_dev_registry_key_supported)) {
+      machine_policy_watcher_failed_(false) {
   if (!::RegisterGPNotification(user_policy_changed_event_.handle(), false)) {
     DPLOG(WARNING) << "Failed to register user group policy notification";
     user_policy_watcher_failed_ = true;
@@ -273,11 +269,9 @@
 std::unique_ptr<PolicyLoaderWin> PolicyLoaderWin::Create(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     ManagementService* management_service,
-    const std::wstring& chrome_policy_key,
-    bool is_dev_registry_key_supported) {
+    const std::wstring& chrome_policy_key) {
   return std::make_unique<PolicyLoaderWin>(task_runner, management_service,
-                                           chrome_policy_key,
-                                           is_dev_registry_key_supported);
+                                           chrome_policy_key);
 }
 
 void PolicyLoaderWin::InitOnBackgroundThread() {
@@ -414,11 +408,6 @@
     DLOG(WARNING) << "Failed to start watch for machine policy change event";
     machine_policy_watcher_failed_ = true;
   }
-
-  if (registry_watcher_) {
-    registry_watcher_->StartWatching(base::BindRepeating(
-        &PolicyLoaderWin::Reload, base::Unretained(this), false /* force */));
-  }
 }
 
 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) {
diff --git a/components/policy/core/common/policy_loader_win.h b/components/policy/core/common/policy_loader_win.h
index 3f698a56..d48c6c2 100644
--- a/components/policy/core/common/policy_loader_win.h
+++ b/components/policy/core/common/policy_loader_win.h
@@ -13,7 +13,6 @@
 #include "base/win/object_watcher.h"
 #include "components/policy/core/common/async_policy_loader.h"
 #include "components/policy/core/common/policy_types.h"
-#include "components/policy/core/common/registry_watcher_win.h"
 #include "components/policy/policy_export.h"
 
 namespace base {
@@ -33,8 +32,7 @@
  public:
   PolicyLoaderWin(scoped_refptr<base::SequencedTaskRunner> task_runner,
                   ManagementService* management_service,
-                  const std::wstring& chrome_policy_key,
-                  bool is_dev_registry_key_supported);
+                  const std::wstring& chrome_policy_key);
   PolicyLoaderWin(const PolicyLoaderWin&) = delete;
   PolicyLoaderWin& operator=(const PolicyLoaderWin&) = delete;
   ~PolicyLoaderWin() override;
@@ -43,8 +41,7 @@
   static std::unique_ptr<PolicyLoaderWin> Create(
       scoped_refptr<base::SequencedTaskRunner> task_runner,
       ManagementService* management_service,
-      const std::wstring& chrome_policy_key,
-      bool is_dev_registry_key_supported);
+      const std::wstring& chrome_policy_key);
 
   // AsyncPolicyLoader implementation.
   void InitOnBackgroundThread() override;
@@ -78,7 +75,6 @@
   base::win::ObjectWatcher machine_policy_watcher_;
   bool user_policy_watcher_failed_;
   bool machine_policy_watcher_failed_;
-  absl::optional<RegistryWatcherWin> registry_watcher_;
 };
 
 }  // namespace policy
diff --git a/components/policy/core/common/policy_loader_win_unittest.cc b/components/policy/core/common/policy_loader_win_unittest.cc
index b5a92583..3fc088f 100644
--- a/components/policy/core/common/policy_loader_win_unittest.cc
+++ b/components/policy/core/common/policy_loader_win_unittest.cc
@@ -279,8 +279,7 @@
     scoped_refptr<base::SequencedTaskRunner> task_runner) {
   base::win::ScopedDomainStateForTesting scoped_domain(true);
   std::unique_ptr<AsyncPolicyLoader> loader(new PolicyLoaderWin(
-      task_runner, PlatformManagementService::GetInstance(), kTestPolicyKey,
-      true /* is_dev_registry_key_supported */));
+      task_runner, PlatformManagementService::GetInstance(), kTestPolicyKey));
   return new AsyncPolicyProvider(registry, std::move(loader));
 }
 
@@ -411,8 +410,7 @@
   bool Matches(const PolicyBundle& expected) {
     PolicyLoaderWin loader(task_environment_.GetMainThreadTaskRunner(),
                            PlatformManagementService::GetInstance(),
-                           kTestPolicyKey,
-                           true /* is_dev_registry_key_supported */);
+                           kTestPolicyKey);
     std::unique_ptr<PolicyBundle> loaded(
         loader.InitialLoad(schema_registry_.schema_map()));
     return loaded->Equals(expected);
diff --git a/components/policy/core/common/registry_watcher_win.cc b/components/policy/core/common/registry_watcher_win.cc
deleted file mode 100644
index b6a4344..0000000
--- a/components/policy/core/common/registry_watcher_win.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// 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/policy/core/common/registry_watcher_win.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/win/registry.h"
-
-namespace policy {
-
-const wchar_t kKeyRegistryDynamicRefreshEnabled[] =
-    L"RegistryDynamicRefreshEnabled";
-
-namespace {
-
-// Returns true if the dynamic refresh of policies from the Registry should be
-// blocked.
-bool ShouldBlockDynamicRefreshFromRegistry(
-    const std::wstring& key_path_str_to_watch,
-    bool is_dev_registry_key_supported) {
-  // This registry key is only for development.
-  if (!is_dev_registry_key_supported)
-    return false;
-
-  base::win::RegKey key;
-  if (key.Open(HKEY_LOCAL_MACHINE, key_path_str_to_watch.c_str(),
-               KEY_QUERY_VALUE) != ERROR_SUCCESS) {
-    return false;
-  }
-  DWORD value = 0;
-  if (key.ReadValueDW(kKeyRegistryDynamicRefreshEnabled, &value) !=
-      ERROR_SUCCESS) {
-    return false;
-  }
-  return value == 0;
-}
-
-}  // namespace
-
-// static
-absl::optional<RegistryWatcherWin> RegistryWatcherWin::MaybeCreate(
-    const std::wstring& key_path_str_to_watch,
-    bool is_dev_registry_key_supported) {
-  if (ShouldBlockDynamicRefreshFromRegistry(key_path_str_to_watch,
-                                            is_dev_registry_key_supported)) {
-    return absl::nullopt;
-  }
-  return absl::optional<RegistryWatcherWin>(key_path_str_to_watch);
-}
-
-RegistryWatcherWin::RegistryWatcherWin(
-    const std::wstring& key_path_str_to_watch)
-    : key_path_str_to_watch_(key_path_str_to_watch) {}
-
-RegistryWatcherWin::~RegistryWatcherWin() = default;
-
-void RegistryWatcherWin::StartWatching(base::RepeatingClosure callback) {
-  // No-op if already initialized.
-  if (!keys_to_watch_.empty())
-    return;
-
-  callback_ = std::move(callback);
-
-  static const HKEY kHives[] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
-  for (HKEY hive : kHives)
-    AddKeyToWatchList(hive, key_path_str_to_watch_);
-}
-
-void RegistryWatcherWin::AddKeyToWatchList(HKEY rootkey,
-                                           const std::wstring& subkey) {
-  auto key = std::make_unique<base::win::RegKey>();
-  if (key->Open(rootkey, subkey.c_str(), KEY_NOTIFY) != ERROR_SUCCESS)
-    return;
-
-  if (!key->StartWatching(base::BindOnce(&RegistryWatcherWin::OnRegistryChanged,
-                                         base::Unretained(this),
-                                         base::Unretained(key.get())))) {
-    DLOG(WARNING) << "Failed to start watch for registry change event";
-    return;
-  }
-
-  keys_to_watch_.push_back(std::move(key));
-}
-
-void RegistryWatcherWin::OnRegistryChanged(base::win::RegKey* key) {
-  // Keep watching the registry key.
-  if (!key->StartWatching(base::BindOnce(&RegistryWatcherWin::OnRegistryChanged,
-                                         base::Unretained(this),
-                                         base::Unretained(key)))) {
-    DLOG(WARNING) << "Failed to keep watching for registry change event";
-    keys_to_watch_.erase(
-        std::remove_if(keys_to_watch_.begin(), keys_to_watch_.end(),
-                       [key](const std::unique_ptr<base::win::RegKey>& ptr) {
-                         return ptr.get() == key;
-                       }));
-  }
-  callback_.Run();
-}
-
-}  // namespace policy
diff --git a/components/policy/core/common/registry_watcher_win.h b/components/policy/core/common/registry_watcher_win.h
deleted file mode 100644
index e9977ff..0000000
--- a/components/policy/core/common/registry_watcher_win.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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_POLICY_CORE_COMMON_REGISTRY_WATCHER_WIN_H_
-#define COMPONENTS_POLICY_CORE_COMMON_REGISTRY_WATCHER_WIN_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "components/policy/policy_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-namespace base {
-namespace win {
-class RegKey;
-}
-}  // namespace base
-
-namespace policy {
-
-// This class monitors registry subkeys below both HKEY_LOCAL_MACHINE and
-// HKEY_CURRENT_USER to detect if any of its values have changed.
-class POLICY_EXPORT RegistryWatcherWin {
- public:
-  // May returns null if the dynamic refresh of policies from the Registry is
-  // blocked. If not null, this instance will observe changes of
-  // |key_path_str_to_watch| in both HKLM and HKCU.
-  static absl::optional<RegistryWatcherWin> MaybeCreate(
-      const std::wstring& key_path_str_to_watch,
-      bool is_dev_registry_key_supported);
-
-  explicit RegistryWatcherWin(const std::wstring& key_path_str_to_watch);
-  RegistryWatcherWin(const RegistryWatcherWin&) = delete;
-  RegistryWatcherWin& operator=(const RegistryWatcherWin&) = delete;
-  ~RegistryWatcherWin();
-
-  // Installs the watchers for the Registry value changes.
-  void StartWatching(base::RepeatingClosure callback);
-
- private:
-  // Creates a new key and appends it to |keys_to_watch_|. If the key fails to
-  // be created, it is not appended to the list.
-  void AddKeyToWatchList(HKEY rootkey, const std::wstring& subkey);
-
-  // Called when the Registry value of |key| is changed.
-  void OnRegistryChanged(base::win::RegKey* key);
-
-  const std::wstring key_path_str_to_watch_;
-  base::RepeatingClosure callback_;
-  std::vector<std::unique_ptr<base::win::RegKey>> keys_to_watch_;
-};
-
-// Exposed for testing.
-extern const POLICY_EXPORT wchar_t kKeyRegistryDynamicRefreshEnabled[];
-
-}  // namespace policy
-
-#endif  // COMPONENTS_POLICY_CORE_COMMON_REGISTRY_WATCHER_WIN_H_
diff --git a/components/policy/core/common/registry_watcher_win_unittest.cc b/components/policy/core/common/registry_watcher_win_unittest.cc
deleted file mode 100644
index 8d17bc585..0000000
--- a/components/policy/core/common/registry_watcher_win_unittest.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// 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/policy/core/common/registry_watcher_win.h"
-
-#include "base/run_loop.h"
-#include "base/test/task_environment.h"
-#include "base/test/test_reg_util_win.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-constexpr wchar_t kSubKeyToWatch[] = L"SOFTWARE\\Policies\\Chromium";
-constexpr wchar_t kFieldName[] = L"ShowHomeButton";
-
-class RegistryWatcherWinTest
-    : public testing::TestWithParam<testing::tuple<bool, bool>> {
- public:
-  RegistryWatcherWinTest(const RegistryWatcherWinTest&) = delete;
-  RegistryWatcherWinTest& operator=(const RegistryWatcherWinTest&) = delete;
-
-  void OnRegistryChanged() { std::move(run_loop_quit_closure_).Run(); }
-
- protected:
-  RegistryWatcherWinTest() = default;
-  ~RegistryWatcherWinTest() override = default;
-
-  void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(
-        registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE));
-    ASSERT_NO_FATAL_FAILURE(
-        registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
-  }
-
-  // Creates a registry key.
-  static base::win::RegKey CreateKey(HKEY rootkey, const wchar_t* subkey) {
-    return base::win::RegKey(rootkey, subkey, KEY_SET_VALUE);
-  }
-
-  // Write a value in a registry key.
-  static bool WriteValue(HKEY rootkey,
-                         const wchar_t* subkey,
-                         const wchar_t* name,
-                         DWORD in_value) {
-    return CreateKey(rootkey, subkey).WriteValue(name, in_value) ==
-           ERROR_SUCCESS;
-  }
-
-  void set_run_loop_quit_closure(base::OnceClosure closure) {
-    run_loop_quit_closure_ = std::move(closure);
-  }
-
- private:
-  base::test::TaskEnvironment task_environment_;
-  registry_util::RegistryOverrideManager registry_override_manager_;
-  base::OnceClosure run_loop_quit_closure_;
-};
-
-// A test condition is that the policy keys in both HKLM and HKCU exist. A
-// callback should be called when a value in any keys is changed.
-TEST_F(RegistryWatcherWinTest, DynamicRefresh) {
-  std::vector<base::win::RegKey> keys_to_watch;
-  static const HKEY kHives[] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
-  // Create existing keys to watch.
-  for (HKEY hive : kHives) {
-    base::win::RegKey key_to_watch = CreateKey(hive, kSubKeyToWatch);
-    ASSERT_TRUE(key_to_watch.Valid());
-    keys_to_watch.push_back(std::move(key_to_watch));
-  }
-
-  // Start watching the keys.
-  RegistryWatcherWin registry_key_watcher(kSubKeyToWatch);
-  registry_key_watcher.StartWatching(base::BindRepeating(
-      &RegistryWatcherWinTest::OnRegistryChanged, base::Unretained(this)));
-
-  // Write a value in a key and see if the callback is invoked.
-  for (auto& key : keys_to_watch) {
-    base::RunLoop run_loop;
-    set_run_loop_quit_closure(run_loop.QuitClosure());
-    // Writing a value in the key must invoke the quit closure of the RunLoop.
-    ASSERT_TRUE(key.WriteValue(kFieldName, 1) == ERROR_SUCCESS);
-    run_loop.Run();
-  }
-}
-
-// A test condition is that one of the policy keys, in HKLM or HKCU, is missing.
-// A callback should be called when a value in an existing key is changed.
-TEST_F(RegistryWatcherWinTest, DynamicRefreshWithSingleRootKey) {
-  static const HKEY kHives[] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
-  for (HKEY hive : kHives) {
-    base::win::RegKey key_to_watch = CreateKey(hive, kSubKeyToWatch);
-    ASSERT_TRUE(key_to_watch.Valid());
-
-    base::RunLoop run_loop;
-    RegistryWatcherWin registry_key_watcher(kSubKeyToWatch);
-    registry_key_watcher.StartWatching(run_loop.QuitClosure());
-
-    // Writing a value in the key must invoke the quit closure of the RunLoop.
-    ASSERT_TRUE(key_to_watch.WriteValue(kFieldName, 1) == ERROR_SUCCESS);
-    run_loop.Run();
-
-    key_to_watch.DeleteKey(L"");
-  }
-}
-
-INSTANTIATE_TEST_SUITE_P(MaybeCreateTest,
-                         RegistryWatcherWinTest,
-                         testing::Combine(testing::Bool(), testing::Bool()));
-
-TEST_P(RegistryWatcherWinTest, Create) {
-  const bool is_dev_registry_key_supported = testing::get<0>(GetParam());
-  const bool enable_registry_dynamic_refresh = testing::get<1>(GetParam());
-  const bool should_be_blocked =
-      is_dev_registry_key_supported && !enable_registry_dynamic_refresh;
-
-  if (!enable_registry_dynamic_refresh) {
-    ASSERT_TRUE(WriteValue(HKEY_LOCAL_MACHINE, kSubKeyToWatch,
-                           kKeyRegistryDynamicRefreshEnabled, 0));
-  }
-  // Null will be returned if the dynamic refresh of policies from the Registry
-  // is blocked.
-  auto registry_watcher = RegistryWatcherWin::MaybeCreate(
-      kSubKeyToWatch, is_dev_registry_key_supported);
-  EXPECT_EQ(should_be_blocked, !registry_watcher);
-}
-
-}  // namespace policy
diff --git a/components/policy/resources/policy_templates_es-419.xtb b/components/policy/resources/policy_templates_es-419.xtb
index fbec9336..e4a0a3670 100644
--- a/components/policy/resources/policy_templates_es-419.xtb
+++ b/components/policy/resources/policy_templates_es-419.xtb
@@ -147,6 +147,7 @@
 <translation id="1160939557934457296">Inhabilita continuar desde la página de advertencia de Navegación segura.</translation>
 <translation id="1163080558183062209">Inhabilita los tipos de impresoras incluidos en la lista de rechazo</translation>
 <translation id="117059611145966538">Servidores de impresión externos</translation>
+<translation id="117080706484659953">Permitir la detección del alcance de la política en <ph name="MAC_OS_NAME" /></translation>
 <translation id="1171785618439752042">Si estableces la política, se designarán los tipos de encriptación que estarán permitidos cuando se soliciten tickets de Kerberos desde un servidor de <ph name="MS_AD_NAME" />.
 
       Si estableces la política en los siguientes valores:
@@ -944,6 +945,17 @@
 <translation id="1962864958436828230">Establecer el límite de tamaño mínimo para los datos del portapapeles mediante la restricción destinada a evitar la filtración de datos</translation>
 <translation id="1964634611280150550">Modo incógnito inhabilitado</translation>
 <translation id="1964802606569741174">Esta política no tiene efecto en la app de YouTube de Android. Si se debe aplicar el modo de seguridad en YouTube, se debe inhabilitar la instalación de la app de YouTube de Android.</translation>
+<translation id="1965363065727209968">setTimeout(…, 0) se usa en general para desglosar tareas largas de JavaScript.
+          Si habilitas la política, los parámetros de setTimeout y setInterval con un intervalo inferior a 4 ms no se restringirán de forma tan agresiva.
+          Esto mejora el rendimiento a corto plazo, pero los sitios web que abusen de la API tendrán, con el tiempo, sus parámetros de setTimeout restringidos.
+
+          Es posible que esto cambie el orden de las tareas en una página web, lo que puede provocar un comportamiento inesperado en los sitios que de alguna manera dependen de un determinado orden.
+          También puede afectar a los sitios que tienen muchas funciones setTimeout() con un tiempo de espera de 0 ms de uso; p. ej., puede aumentar la carga de CPU.
+
+          Para los usuarios que no establezcan esta política, <ph name="PRODUCT_NAME" /> lanzará el cambio gradualmente en el canal estable.
+
+          Esta es una política temporal que se planea quitar en <ph name="PRODUCT_NAME" /> 107. Es posible que se extienda la fecha límite si las empresas lo necesitan.
+          </translation>
 <translation id="1967334955994230472">Inhabilitar Projector</translation>
 <translation id="1969212217917526199">Anula las políticas en compilaciones de depuración del host de acceso remoto.
 
@@ -1487,6 +1499,14 @@
 <translation id="2496180316473517155">Historial de navegación</translation>
 <translation id="2497751676088107779">Secuencia de comandos del usuario</translation>
 <translation id="2497965601277442929">No permitir que los usuarios habiliten el modo solo HTTPS</translation>
+<translation id="249798396824949930"> Controla si el navegador puede o no detectar el alcance obligatorio de la política en <ph name="MAC_OS_NAME" />.
+
+      Si habilitas la política o no la estableces, el alcance de cada política se determinará según el alcance del perfil administrado de <ph name="MAC_OS_NAME" />.
+      Si la inhabilitas, todas las políticas se reconocerán como políticas de alcance de la máquina.
+
+      Esta política es temporal a fin de facilitar la transición fluida a políticas con alcance adecuado en <ph name="MAC_OS_NAME" />. Se quitará en <ph name="PRODUCT_NAME" /> 107.
+
+      </translation>
 <translation id="2498238926436517902">Siempre ocultar automáticamente los archivos</translation>
 <translation id="250022556568924228">Si estableces la política, <ph name="PRODUCT_OS_NAME" /> descargará las Condiciones del Servicio y las presentará a los usuarios cada vez que se inicie la sesión local del dispositivo. Los usuarios solo podrán acceder a la sesión cuando acepten las Condiciones del Servicio.
 
@@ -2704,6 +2724,7 @@
 <translation id="3838094946886335701">Si estableces la política (solo como recomendada), podrás registrar una lista de controladores de protocolo, que se combinarán con los que registre el usuario; así, ambos conjuntos de controladores estarán en uso. Asigna a la propiedad "protocolo" el esquema (p. ej. mailto) y a la propiedad "URL" el patrón de URL de la aplicación que controla el esquema especificado en el campo "protocolo". El patrón puede incluir el marcador de posición "%s", que se reemplazará por la URL controlada.
 
       Los usuarios no podrán quitar un controlador de protocolo que haya registrado la política. Sin embargo, al instalar un nuevo controlador predeterminado, los usuarios podrán cambiar los controladores de protocolo que haya instalado la política.</translation>
+<translation id="3851443303439635700">Controlar el umbral de anidación antes de que la función de JavaScript setTimeout() comience a restringirse</translation>
 <translation id="3857816702027059082">Permite <ph name="CHROME_ENTERPRISE_PLATFORM_IDENTITY_CONNECTOR" /> para una lista de URL.
 
       Si estableces esta política, se especificará qué URL pueden formar parte del flujo de certificación para obtener el conjunto de señales de la máquina.
@@ -3235,6 +3256,7 @@
 <translation id="4472740647327683596">Ancho de la página (en micrómetros).</translation>
 <translation id="4474167089968829729">Habilitar el guardado de contraseñas en el administrador de contraseñas</translation>
 <translation id="4476769083125004742">Si esta política se establece como <ph name="BLOCK_GEOLOCATION_SETTING" />, las apps de Android no podrán acceder a la información de la ubicación. Si estableces esta política en cualquier valor o no la estableces, se le pedirá al usuario que autorice la app de Android que quiera acceder a la información de ubicación.</translation>
+<translation id="4478248026668918517">Bloquear la detección del alcance de la política</translation>
 <translation id="4479671363221255277">Si estableces la política, podrás definir una lista de patrones de URL donde se especifiquen los sitios que pueden pedir a los usuarios acceso de lectura a los archivos o directorios que se encuentren en el sistema de archivos del sistema operativo del host mediante la API de File System.
 
       Si no estableces la política, se aplicará <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> para todos los sitios, en caso de haberse establecido. De lo contrario se aplicará la configuración personal del usuario.
@@ -4845,6 +4867,7 @@
 <translation id="6282799760374509080">Permitir o rechazar la captura de audio</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
 <translation id="6287310684159482272">Configuración de cookies</translation>
+<translation id="6299147100249359151">Permitir la detección del alcance de la política</translation>
 <translation id="6300871921951390976">Los usuarios solo podrán cambiar el canal de versiones del dispositivo si estableces esta política como verdadera. Si la estableces como falsa o no la estableces, los usuarios no podrán cambiar el canal.
 
       <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> solo tiene efecto si estableces <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> como falsa.</translation>
diff --git a/components/policy/resources/policy_templates_es.xtb b/components/policy/resources/policy_templates_es.xtb
index 637dc22c..b1b127a 100644
--- a/components/policy/resources/policy_templates_es.xtb
+++ b/components/policy/resources/policy_templates_es.xtb
@@ -148,6 +148,7 @@
 <translation id="1160939557934457296">Inhabilitar seguir navegando desde la página de advertencia sobre Navegación segura</translation>
 <translation id="1163080558183062209">Inhabilitar tipos de impresora en la lista de denegación</translation>
 <translation id="117059611145966538">Servidores de impresión externos</translation>
+<translation id="117080706484659953">Permitir detección del nivel de las políticas en <ph name="MAC_OS_NAME" /></translation>
 <translation id="1171785618439752042">Si se establece esta política, se designará qué tipos de cifrado se admiten cuando se solicitan tickets de Kerberos de un servidor de <ph name="MS_AD_NAME" />.
 
       Estos son los efectos de cada valor:
@@ -947,6 +948,17 @@
 <translation id="1962864958436828230">Establecer un límite de tamaño mínimo para la restricción del portapapeles que previene la filtración de datos</translation>
 <translation id="1964634611280150550">Modo Incógnito inhabilitado</translation>
 <translation id="1964802606569741174">Esta política no influye en la aplicación YouTube para Android. Si se debe aplicar el modo Seguro en YouTube, deberás inhabilitar la descarga de la aplicación YouTube para Android.</translation>
+<translation id="1965363065727209968">setTimeout(…, 0) se suele usar para dividir tareas largas de JavaScript.
+          Si se habilita esta política, los valores de setTimeout y setInterval que tengan un intervalo inferior a 4 ms no se redondearán de forma tan agresiva.
+          Esto mejora el rendimiento a corto plazo. Sin embargo, en los sitios web que hagan un uso inadecuado de la API, se redondearán los valores de setTimeout de todos modos.
+
+          Es posible que esto cambie el orden de las tareas en una página web, lo que podría provocar un comportamiento inesperado en sitios que dependan, de algún modo, de un orden determinado.
+          También puede afectar a los sitios que usen mucho la función setTimeout() con un tiempo de espera de 0 ms (por ejemplo, podría aumentar la carga de la CPU).
+
+          Para los usuarios que no tengan esta política configurada, <ph name="PRODUCT_NAME" /> lanzará el cambio de forma gradual en el canal estable.
+
+          Se trata de una política temporal y se prevé que se elimine en la versión 107 de <ph name="PRODUCT_NAME" />. Este plazo puede ampliarse si lo necesitan las empresas.
+          </translation>
 <translation id="1967334955994230472">Inhabilitar Proyector</translation>
 <translation id="1969212217917526199">Anula las políticas de compilaciones de depuración del host de acceso remoto.
 
@@ -1492,6 +1504,14 @@
 <translation id="2496180316473517155">Historial de navegación</translation>
 <translation id="2497751676088107779">Secuencia de comandos de usuario</translation>
 <translation id="2497965601277442929">No permitir que los usuarios habiliten el modo solo‑HTTPS</translation>
+<translation id="249798396824949930"> Controla si el navegador puede detectar si el nivel de cada política es obligatorio en <ph name="MAC_OS_NAME" /> o no.
+
+      Si se habilita esta política o no se establece, el nivel de cada política lo determinará el nivel del perfil gestionado de <ph name="MAC_OS_NAME" />.
+      Si se inhabilita esta política, todas las políticas se reconocerán como políticas a nivel de equipo.
+
+      Esta política es temporal y sirve para facilitar la transición a políticas que se establezcan en el nivel adecuado en <ph name="MAC_OS_NAME" />. Se eliminará en la versión 107 de <ph name="PRODUCT_NAME" />.
+
+      </translation>
 <translation id="2498238926436517902">Ocultar siempre automáticamente los archivos</translation>
 <translation id="250022556568924228">Si se establece la política, <ph name="PRODUCT_OS_NAME" /> descargará los Términos del Servicio y se los mostrará a los usuarios siempre que se inicie sesión con una cuenta local del dispositivo. Para iniciar sesión, los usuarios deben aceptar los Términos del Servicio.
 
@@ -2717,6 +2737,7 @@
 <translation id="3838094946886335701">Si se establece esta política (solo según lo recomendado), podrás registrar una lista de controladores de protocolo, la cual se combinará con las listas que registre el usuario (se usarán ambos conjuntos). Establece la propiedad protocol según el esquema (por ejemplo, mailto) y la propiedad URL según el patrón de URL de la aplicación que controla el esquema especificado en el campo protocol. El patrón puede incluir un marcador de posición %s, que se sustituye por la URL controlada.
 
       Los usuarios no pueden quitar un controlador de protocolo registrado por la política. Sin embargo, si instalan un controlador predeterminado nuevo, podrán cambiar los controladores de protocolo instalados por la política.</translation>
+<translation id="3851443303439635700">Controlar el umbral de anidación antes del cual se empezará a redondear la función setTimeout() de JavaScript</translation>
 <translation id="3857816702027059082">Habilita <ph name="CHROME_ENTERPRISE_PLATFORM_IDENTITY_CONNECTOR" /> para obtener una lista de URLs.
 
       Si se establece esta política, se especificarán las URLs que podrán formar parte del flujo de atestación para obtener un conjunto de señales del equipo.
@@ -3248,6 +3269,7 @@
 <translation id="4472740647327683596">Ancho de la página en micrómetros</translation>
 <translation id="4474167089968829729">Habilitar el almacenamiento de contraseñas en el gestor de contraseñas</translation>
 <translation id="4476769083125004742">Si se asigna el valor <ph name="BLOCK_GEOLOCATION_SETTING" /> a esta política, las aplicaciones para Android no tendrán acceso a la información sobre la ubicación. Si se le asigna cualquier otro valor o no se configura, el usuario tendrá que dar su consentimiento cuando una aplicación para Android quiera acceder a los datos de ubicación.</translation>
+<translation id="4478248026668918517">Bloquea la detección del nivel de las políticas.</translation>
 <translation id="4479671363221255277">Si se establece esta política, podrás definir una lista de patrones de URL donde se especifique qué sitios pueden pedir a los usuarios que les concedan acceso de lectura a archivos o directorios del sistema de archivos del sistema operativo del host a través de la API File System.
 
       Si no se le asigna ningún valor a esta política, <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> se aplicará a todos los sitios, si se ha definido. Si no se ha definido, se aplicará la configuración personal del usuario.
@@ -4857,6 +4879,7 @@
 <translation id="6282799760374509080">Permitir o denegar captura de audio</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
 <translation id="6287310684159482272">Configuración de cookies</translation>
+<translation id="6299147100249359151">Permite la detección del nivel de las políticas.</translation>
 <translation id="6300871921951390976">Solo se permite que los usuarios cambien el canal de lanzamiento del dispositivo si se le asigna el valor "True" a esta política. Si se le asigna el valor "False" o no se le asigna ninguno, los usuarios no podrán cambiar el canal.
 
       Definir <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> solo tendrá efecto si se le asigna el valor "False" a <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" />.</translation>
diff --git a/components/policy/resources/policy_templates_fr.xtb b/components/policy/resources/policy_templates_fr.xtb
index 3c48803..75a1786 100644
--- a/components/policy/resources/policy_templates_fr.xtb
+++ b/components/policy/resources/policy_templates_fr.xtb
@@ -86,6 +86,7 @@
       Si elle est définie sur "True", les informations concernant le rétroéclairage de l'appareil sont transmises.</translation>
 <translation id="1076751984131277498">Liste d'autorisation des appareils USB amovibles</translation>
 <translation id="1077675271127011209">Désactiver la création de rapports sur l'utilisation et les plantages</translation>
+<translation id="1079120839835170592">API Event.path réactivée jusqu'à M115.</translation>
 <translation id="1079425471279127373">Si cette règle est configurée, certaines origines d'applis Web installées d'office sont autorisées à obtenir les attributs des appareils (ex. : numéro de série, nom d'hôte) à l'aide de l'API Device Attributes.
 
       Cette API est une liste d'API Web (voir https://wicg.github.io/WebApiDevice/device_attributes). Elles ne sont disponibles que pour les origines qui correspondent aux applis web installées d'office via la règle <ph name="WEB_APP_INSTALL_FORCE_LIST_POLICY_NAME" /> ou celle configurée dans la session Kiosque.</translation>
@@ -147,6 +148,7 @@
 <translation id="1160939557934457296">Désactiver l'accès au site lors de l'affichage de la page d'avertissement par le service de navigation sécurisée</translation>
 <translation id="1163080558183062209">Permet de désactiver les types d'imprimantes figurant sur la liste deny</translation>
 <translation id="117059611145966538">Serveurs d'impression externes</translation>
+<translation id="117080706484659953">Autorisez la détection du champ d'application des règles sur <ph name="MAC_OS_NAME" /></translation>
 <translation id="1171785618439752042">Cette règle permet de désigner les types de chiffrement autorisés lors de la demande de tickets Kerberos envoyés par un serveur <ph name="MS_AD_NAME" />.
 
       Configurations possibles :
@@ -259,6 +261,7 @@
       Si vous ne configurez pas cette règle, <ph name="CHROME_CLEANUP_NAME" /> peut, conformément à la règle définie par <ph name="SAFE_BROWSING_EXTENDED_REPORTING_ENABLED_POLICY_NAME" />, transmettre à Google les rapports d'analyse liés à la détection des logiciels indésirables. <ph name="CHROME_CLEANUP_NAME" /> demande aux utilisateurs s'ils souhaitent qu'un nettoyage soit effectué et que les résultats soient partagés avec Google pour améliorer la détection des logiciels indésirables. Ces résultats comprennent des métadonnées de fichiers, des extensions installées automatiquement et des clés de registre, tel que décrit dans le livre blanc sur la protection de la vie privée dans Google Chrome.
 
       Sous <ph name="MS_WIN_NAME" />, cette règle n'est disponible que sur les instances associées à un domaine <ph name="MS_AD_NAME" />, exécutées sous Windows 10 Pro ou qui bénéficient de la <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />.</translation>
+<translation id="1285819498003746288">L'API Event.path sera indisponible.</translation>
 <translation id="1290634681382861275">Contrôle divers paramètres de type USB, Bluetooth, actualisation des stratégies, mode développeur et plus encore.</translation>
 <translation id="1291880496936992484">Avertissement : RC4 sera intégralement supprimé de <ph name="PRODUCT_NAME" /> après la version 52 (autour de septembre 2016) et cette règle ne sera plus valable.
 
@@ -939,6 +942,17 @@
 <translation id="1962864958436828230">Définir la taille minimale liée à la restriction du presse-papiers pour prévenir les fuites de données</translation>
 <translation id="1964634611280150550">Mode navigation privée désactivé</translation>
 <translation id="1964802606569741174">Cette règle n'a aucun effet sur l'application YouTube pour Android. Vous ne devez pas autoriser son installation si le mode sécurisé de YouTube doit être appliqué.</translation>
+<translation id="1965363065727209968">setTimeout(…, 0) est souvent utilisé pour décomposer les longues tâches JavaScript.
+          Lorsque cette règle est activée, les fonctions setTimeouts et setIntervals ayant un intervalle inférieur à 4 ms ne sont pas limitées de façon aussi agressive.
+          Les performances à court terme sont alors meilleures, mais les fonctions setTimeouts des sites abusant de l'API seront finalement encore limitées.
+
+          Cela peut modifier l'ordre d'exécution des tâches sur une page Web et provoquer ainsi un comportement inattendu sur les sites qui dépendent de cet ordre.
+          Les sites qui emploient de nombreuses fonctions setTimeout() avec un délai d'expiration de 0 ms peuvent aussi être affectés (par exemple, ils peuvent davantage solliciter le processeur).
+
+          Le changement sera déployé graduellement sur la version stable de <ph name="PRODUCT_NAME" /> pour les utilisateurs chez qui cette règle n'est pas configurée.
+
+          Cette règle est temporaire et devrait être supprimée dans <ph name="PRODUCT_NAME" /> 107. Néanmoins, cette échéance peut être repoussée si des entreprises le requièrent.
+          </translation>
 <translation id="1967334955994230472">Désactiver Projector</translation>
 <translation id="1969212217917526199">Remplace des règles sur les versions de débogage de l'hôte d'accès à distance.
 
@@ -1483,6 +1497,14 @@
 <translation id="2496180316473517155">Historique de navigation</translation>
 <translation id="2497751676088107779">Script utilisateur</translation>
 <translation id="2497965601277442929">Ne pas autoriser les utilisateurs à activer le mode HTTPS uniquement</translation>
+<translation id="249798396824949930"> Détermine si le navigateur peut ou non détecter le champ d'application obligatoire des règles sur <ph name="MAC_OS_NAME" />.
+
+      Si cette règle est activée ou n'est pas configurée, la portée de chaque règle sera déterminée par la portée du profil <ph name="MAC_OS_NAME" /> géré.
+      Si elle est désactivée, toutes les règles sont considérées comme s'appliquant aux machines.
+
+      Cette règle est temporaire et vise à faciliter la transition vers une meilleure définition du champ d'application des règles sur <ph name="MAC_OS_NAME" />. Elle sera supprimée dans <ph name="PRODUCT_NAME" /> 107.
+
+      </translation>
 <translation id="2498238926436517902">Toujours masquer automatiquement l'étagère</translation>
 <translation id="250022556568924228">Si cette règle est activée, <ph name="PRODUCT_OS_NAME" /> télécharge les conditions d'utilisation et les présente aux utilisateurs dès qu'une session d'un compte local de l'appareil s'ouvre. Les utilisateurs ne peuvent se connecter à cette session qu'après avoir accepté lesdites conditions d'utilisation.
 
@@ -2528,6 +2550,7 @@
 <translation id="3652670852519271837">Autoriser les sites à demander aux utilisateurs l'accès en lecture aux fichiers et répertoires via l'API File System</translation>
 <translation id="3653237928288822292">Icône du moteur de recherche par défaut</translation>
 <translation id="3654906736796256792">Autoriser l'exécution en bac à sable du processus audio</translation>
+<translation id="3655885297177292093">L'API Event.path aura l'état par défaut disponible avant M109 et indisponible de M109 à 114.</translation>
 <translation id="3659542706175323490">Si cette règle est activée, le démarrage au branchement de l'alimentation CA l'est également si l'appareil le permet. Une fois le cordon d'alimentation branché, le système, qui était alors complètement éteint ou en veille prolongée, redémarre.
 
       Si cette règle est désactivée, le démarrage au branchement de l'alimentation CA l'est également.
@@ -2700,6 +2723,7 @@
 <translation id="3838094946886335701">Cette règle (recommandation uniquement) permet d'enregistrer une liste de gestionnaires de protocoles combinée à ceux enregistrés par l'utilisateur, afin que les deux ensembles s'appliquent. Définissez la propriété "protocole" sur le schéma (par exemple, "mailto") et la propriété "URL" sur le format d'URL de l'application qui gère le schéma spécifié dans le champ "protocole". Le schéma peut inclure un espace réservé "%s" remplacé par l'URL gérée.
 
       Les utilisateurs ne peuvent pas supprimer un gestionnaire de protocoles enregistré par une règle. Toutefois, l'installation d'un nouveau gestionnaire par défaut leur permet de modifier les gestionnaires de protocoles installés par une règle.</translation>
+<translation id="3851443303439635700">Contrôlez le seuil d'imbrication avant que la fonction JavaScript setTimeout() commence à être limitée</translation>
 <translation id="3857816702027059082">Activer <ph name="CHROME_ENTERPRISE_PLATFORM_IDENTITY_CONNECTOR" /> pour une liste d'URL.
 
       Cette règle indique quelles URL doivent être autorisées à faire partie du parcours d'attestation visant à obtenir l'ensemble de signaux auprès de la machine.
@@ -3218,6 +3242,7 @@
 <translation id="4472740647327683596">Largeur de la page en micromètres.</translation>
 <translation id="4474167089968829729">Activer l'enregistrement des mots de passe dans le gestionnaire de mots de passe</translation>
 <translation id="4476769083125004742">Si cette règle est définie sur "<ph name="BLOCK_GEOLOCATION_SETTING" />", les applications Android n'ont pas accès aux informations de localisation. Si vous la définissez sur une autre valeur ou si vous ne la modifiez pas, l'utilisateur est invité à donner son autorisation lorsqu'une application Android requiert ces informations.</translation>
+<translation id="4478248026668918517">Bloquez la détection du champ d'application des règles.</translation>
 <translation id="4479671363221255277">Permet de dresser la liste des formats d'URL pour lesquels les sites sont autorisés à demander aux utilisateurs l'accès en lecture aux fichiers ou répertoires figurant dans le système de fichiers du système d'exploitation hôte via l'API File System.
 
       Si cette règle n'est pas configurée, la règle <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> s'applique pour tous les sites, à condition qu'elle soit définie. Si ce n'est pas le cas, les paramètres spécifiés par les utilisateurs s'appliquent.
@@ -4057,6 +4082,7 @@
 
       Si cette règle n'est pas configurée, l'utilisateur peut contrôler l'affichage des fiches. Par défaut, les fiches sont affichées.
       </translation>
+<translation id="5449690328792750354">L'API Event.path sera disponible.</translation>
 <translation id="5455609857202311243">Ignorer l'approbation par la règle KDC lors de l'authentification HTTP</translation>
 <translation id="5455888515928026628">Lors de la connexion via l'écran de verrouillage, l'authentification dans <ph name="PRODUCT_OS_NAME" /> peut s'effectuer sur un serveur (en ligne) ou à l'aide d'un mot de passe en cache (hors connexion).
 
@@ -4810,6 +4836,7 @@
 <translation id="6282799760374509080">Autoriser ou interdire la capture audio</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
 <translation id="6287310684159482272">Paramètres des cookies</translation>
+<translation id="6299147100249359151">Autorisez la détection du champ d'application des règles.</translation>
 <translation id="6300871921951390976">Les utilisateurs ne sont autorisés à modifier la version de l'appareil que si cette règle est définie sur "True". Si elle est définie sur "False" ou si elle n'est pas configurée, les utilisateurs peuvent modifier la version.
 
       La configuration de la règle <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> n'est effective que si la règle <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> est définie sur "False".</translation>
@@ -6797,6 +6824,15 @@
 <translation id="8410477879938914253">Cette règle ne concerne que les sessions Invité gérées.
       Si elle est définie sur "True" ou si elle n'est pas configurée, une boîte de dialogue invitant l'utilisateur à confirmer ou à refuser la déconnexion s'affichera une fois la dernière fenêtre fermée.
       Si cette règle est définie sur "False", la boîte de dialogue ne pourra pas s'afficher et la fonctionnalité de déconnexion automatique une fois la dernière fenêtre fermée sera désactivée.</translation>
+<translation id="8411050083243181286"> À partir de M109, l'API non standard Event.path sera supprimée pour améliorer la compatibilité Web. Cette règle réactive l'API jusqu'à M115.
+
+      Si cette règle est activée, l'API Event.path sera disponible.
+
+      Si elle est désactivée, l'API Event.path sera indisponible.
+
+      Si cette règle n'est pas définie, l'API Event.path aura l'état par défaut disponible avant M109 et indisponible de M109 à 114.
+
+      Cette règle sera supprimée après Chrome 115.</translation>
 <translation id="8415953438346821074">Si vous activez cette règle, les paramètres stockés dans les profils <ph name="PRODUCT_NAME" />, comme les favoris, les données de saisie automatique et les mots de passe, entre autres, sont également enregistrés dans un fichier stocké dans le dossier des profils utilisateur itinérants ou à un emplacement défini par l'administrateur tel que spécifié dans la règle <ph name="ROAMING_PROFILE_LOCATION_POLICY_NAME" />. Si cette règle est activée, la synchronisation cloud est désactivée.
 
       Si cette règle est désactivée ou qu'elle n'est pas configurée, seuls les profils locaux standards sont utilisés.</translation>
diff --git a/components/policy/resources/policy_templates_id.xtb b/components/policy/resources/policy_templates_id.xtb
index 30f53f5..536be94 100644
--- a/components/policy/resources/policy_templates_id.xtb
+++ b/components/policy/resources/policy_templates_id.xtb
@@ -86,6 +86,7 @@
       Jika ditetapkan ke true, informasi lampu latar perangkat akan dilaporkan.</translation>
 <translation id="1076751984131277498">Daftar perangkat USB dapat dilepas yang diizinkan</translation>
 <translation id="1077675271127011209">Nonaktifkan pelaporan data penggunaan dan yang terkait error</translation>
+<translation id="1079120839835170592">Mengaktifkan kembali Event.path API hingga M115.</translation>
 <translation id="1079425471279127373">Jika kebijakan disetel, beberapa asal dari aplikasi web yang diinstal otomatis akan diizinkan mendapatkan atribut perangkat (misalnya, nomor seri, nama host) dengan menggunakan Device Attributes API.
 
       Device Attributes API adalah daftar API web; harap lihat https://wicg.github.io/WebApiDevice/device_attributes. API ini hanya tersedia untuk asal yang sesuai dengan aplikasi web yang diinstal otomatis melalui <ph name="WEB_APP_INSTALL_FORCE_LIST_POLICY_NAME" /> atau aplikasi web yang dikonfigurasi dalam sesi Kios.</translation>
@@ -265,6 +266,7 @@
       Jika kebijakan tidak disetel, <ph name="CHROME_CLEANUP_NAME" /> dapat melaporkan pemindaian deteksi software yang tidak diinginkan ke Google, sesuai dengan kebijakan yang disetel oleh <ph name="SAFE_BROWSING_EXTENDED_REPORTING_ENABLED_POLICY_NAME" />. <ph name="CHROME_CLEANUP_NAME" /> akan meminta izin pengguna untuk melakukan pembersihan dan membagikan hasilnya kepada Google guna membantu mendeteksi software yang tidak diinginkan di masa mendatang. Hasil ini berisi metadata file, ekstensi yang terinstal otomatis, dan kunci registry sebagaimana dijelaskan dalam Laporan Resmi Privasi Chrome.
 
       Di <ph name="MS_WIN_NAME" />, fungsi ini hanya tersedia di instance yang dihubungkan ke domain <ph name="MS_AD_NAME" />, dijalankan di Windows 10 Pro, atau didaftarkan di <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />.</translation>
+<translation id="1285819498003746288">Event.path API tidak akan tersedia.</translation>
 <translation id="1290634681382861275">Mengontrol berbagai setelan antara lain USB, bluetooth, pembaruan kebijakan, mode developer, dan lainnya.</translation>
 <translation id="1291880496936992484">Peringatan: RC4 akan dihapus sepenuhnya dari <ph name="PRODUCT_NAME" /> setelah versi 52 (sekitar September 2016) dan sejak saat itu kebijakan ini tidak akan berlaku lagi.
 
@@ -2559,6 +2561,7 @@
 <translation id="3652670852519271837">Izinkan situs meminta pengguna memberikan akses baca ke file dan direktori melalui File System API</translation>
 <translation id="3653237928288822292">Ikon penyedia penelusuran default</translation>
 <translation id="3654906736796256792">Mengizinkan sandbox audio berjalan</translation>
+<translation id="3655885297177292093">Event.path API akan berada dalam status default: tersedia sebelum M109, dan tidak tersedia di M109 hingga 114.</translation>
 <translation id="3659542706175323490">Jika kebijakan disetel ke Aktif, booting pada tegangan AC akan diaktifkan jika didukung di perangkat. Booting pada tegangan AC memungkinkan sistem memulai ulang dari status Nonaktif atau Hibernasi setelah kabel listrik dihubungkan.
 
       Jika kebijakan disetel ke Nonaktif, booting pada tegangan AC akan dinonaktifkan.
@@ -4110,6 +4113,7 @@
 
       Jika kebijakan tidak disetel, pengguna dapat mengontrol visibilitas kartu. Default-nya adalah kartu terlihat.
       </translation>
+<translation id="5449690328792750354">Event.path API akan tersedia.</translation>
 <translation id="5455609857202311243">Abaikan persetujuan kebijakan KDC selama autentikasi HTTP</translation>
 <translation id="5455888515928026628">Saat login melalui layar kunci, <ph name="PRODUCT_OS_NAME" /> dapat melakukan autentikasi terhadap server (online) atau menggunakan sandi yang tersimpan di cache (offline).
 
@@ -6871,6 +6875,15 @@
 <translation id="8410477879938914253">Kebijakan ini hanya berlaku untuk sesi tamu terkelola.
       Jika kebijakan disetel ke Benar (True) atau tidak disetel, dialog yang meminta pengguna untuk mengonfirmasi atau menolak logout saat jendela terakhir ditutup akan ditampilkan.
       Jika kebijakan disetel ke Salah (False), dialog tidak akan ditampilkan sehingga logout otomatis akan dinonaktifkan setelah jendela terakhir ditutup.</translation>
+<translation id="8411050083243181286"> Mulai M109, Event.path API non-standar akan dihapus untuk meningkatkan kompatibilitas web. Kebijakan ini akan mengaktifkan kembali API tersebut hingga M115.
+
+      Jika kebijakan ini disetel ke aktif, Event.path API akan tersedia.
+
+      Jika kebijakan ini disetel ke nonaktif, Event.path API tidak akan tersedia.
+
+      Jika kebijakan ini tidak disetel, Event.path API akan berada dalam status default: tersedia sebelum M109, dan tidak tersedia di M109 hingga 114.
+
+      Kebijakan ini akan dihapus setelah Chrome 115.</translation>
 <translation id="8415953438346821074">Jika Anda mengaktifkan setelan ini, setelan yang disimpan di profil <ph name="PRODUCT_NAME" /> seperti bookmark, data isi otomatis, sandi, dan informasi lainnya juga akan ditulis ke file yang disimpan di folder profil pengguna Roaming atau lokasi yang ditentukan oleh Administrator melalui kebijakan <ph name="ROAMING_PROFILE_LOCATION_POLICY_NAME" />. Mengaktifkan kebijakan ini akan menonaktifkan sinkronisasi cloud.
 
       Jika kebijakan ini dinonaktifkan atau tidak disetel, hanya profil lokal reguler yang akan digunakan.</translation>
diff --git a/components/policy/resources/policy_templates_ja.xtb b/components/policy/resources/policy_templates_ja.xtb
index bbc74f9a..42ca5693 100644
--- a/components/policy/resources/policy_templates_ja.xtb
+++ b/components/policy/resources/policy_templates_ja.xtb
@@ -82,6 +82,7 @@
       このポリシーを true に設定した場合、デバイスのバックライトに関する情報が報告されます。</translation>
 <translation id="1076751984131277498">取り外し可能な USB デバイスの許可リスト</translation>
 <translation id="1077675271127011209">使用状況とクラッシュ関連データのレポートを無効にする</translation>
+<translation id="1079120839835170592">M115 まで Event.path API を再度使用できるようにします。</translation>
 <translation id="1079425471279127373">このポリシーでは、自動インストールされたウェブ アプリケーションの一部のオリジンに Device Attributes API を使用したデバイス属性(シリアル番号、ホスト名など)の取得を許可するかどうかを設定します。
 
       Device Attributes API はウェブの API のリストです。詳しくは、https://wicg.github.io/WebApiDevice/device_attributes をご覧ください。これらの API は、<ph name="WEB_APP_INSTALL_FORCE_LIST_POLICY_NAME" /> に沿って自動インストールされたウェブ アプリケーションと一致するオリジンまたはキオスク セッションで設定されたオリジンに対してのみ使用できます。</translation>
@@ -253,6 +254,7 @@
       このポリシーを未設定のままにした場合、<ph name="SAFE_BROWSING_EXTENDED_REPORTING_ENABLED_POLICY_NAME" /> で設定されたポリシー値に沿って、<ph name="CHROME_CLEANUP_NAME" /> で望ましくないソフトウェアのスキャンに関するレポートが Google に送信可能となります。<ph name="CHROME_CLEANUP_NAME" /> でクリーンアップを行うかどうかと、望ましくないソフトウェアの検出精度を向上するために、結果を Google と共有するかどうかをユーザーに確認します。これらの結果には、Chrome のプライバシー ホワイトペーパーで説明されているとおり、ファイルのメタデータのほか自動インストールされた拡張機能とレジストリキーが含まれます。
 
       <ph name="MS_WIN_NAME" /> では、この機能は <ph name="MS_AD_NAME" /> ドメインに追加されたインスタンス、Windows 10 Pro で実行されているインスタンス、<ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" /> に登録されているインスタンスでのみ使用できます。</translation>
+<translation id="1285819498003746288">Event.path API を使用不可にする。</translation>
 <translation id="1290634681382861275">USB、Bluetooth、ポリシーの更新、デベロッパー モードなど、その他の設定を制御します。</translation>
 <translation id="1291880496936992484">警告: <ph name="PRODUCT_NAME" /> ではバージョン 52 で RC4 のサポートを完全に終了し(2016 年 9 月頃)、このポリシーも機能しなくなります。
 
@@ -2412,6 +2414,7 @@
 <translation id="3652670852519271837">サイトが File System API を経由したファイルとディレクトリへの読み取りアクセスをユーザーに要求することを許可する</translation>
 <translation id="3653237928288822292">デフォルトの検索プロバイダ アイコン</translation>
 <translation id="3654906736796256792">音声処理のサンドボックス化を許可する</translation>
+<translation id="3655885297177292093">Event.path API をデフォルトのステータスにする(M109 まで使用可能、M109〜114 では使用不可)。</translation>
 <translation id="3659542706175323490">このポリシーを有効に設定した場合、デバイスが対応していれば AC 電源接続時の起動が有効になります。AC 電源接続時の起動が有効な場合、電源コードをコンセントに差し込むと、オフまたは休止状態のシステムが起動するようになります。
 
       このポリシーを無効に設定した場合、AC 電源接続時の起動は無効になります。
@@ -3863,6 +3866,7 @@
 
       このポリシーを設定しなかった場合、カードを表示するかどうかはユーザーが制御できます。デフォルトでは、カードが表示されます。
       </translation>
+<translation id="5449690328792750354">Event.path API を使用可能にする。</translation>
 <translation id="5455609857202311243">HTTP 認証時に KDC ポリシーの承認を無視する</translation>
 <translation id="5455888515928026628"><ph name="PRODUCT_OS_NAME" /> では、ロック画面でのログイン時に、サーバーに対して(オンラインで)、またはキャッシュに保存されたパスワードを使用して(オフラインで)、認証を行うことができます。
 
@@ -6460,6 +6464,15 @@
 <translation id="8410477879938914253">このポリシーは、管理対象ゲスト セッションにのみ適用されます。
       このポリシーを True に設定するか未設定のままにした場合は、最後のウィンドウを閉じたときに、ログアウトするかどうかを確認するダイアログが表示されます。
       このポリシーを False に設定した場合、ダイアログは表示されず、最後のウィンドウを閉じた後の自動ログアウトも無効になります。</translation>
+<translation id="8411050083243181286"> M109 以降、非標準の Event.path API はウェブの互換性を向上させるため削除されます。このポリシーでは、Event.path API を M115 まで再度使用できるようにします。
+
+      このポリシーを有効に設定した場合、Event.path API が使用可能になります。
+
+      このポリシーを無効に設定した場合、Event.path API は使用できなくなります。
+
+      このポリシーを設定しない場合、Event.path API はデフォルトのステータスになります(M109 まで使用可能、M109〜114 では使用不可)。
+
+      このポリシーは、Chrome 115 以降で削除されます。</translation>
 <translation id="8415953438346821074">この設定を有効にした場合は、<ph name="PRODUCT_NAME" /> プロフィールに保存されている設定(ブックマーク、自動入力データ、パスワードなど)が、「ローミング」ユーザー プロフィール フォルダまたは管理者が <ph name="ROAMING_PROFILE_LOCATION_POLICY_NAME" /> ポリシーで指定した場所に保存されるファイルにも書き込まれます。このポリシーを有効にすると、クラウド同期は無効になります。
 
       このポリシーを無効にするか未設定のままにした場合は、通常のローカル プロフィールのみが使用されます。</translation>
diff --git a/components/policy/resources/policy_templates_ko.xtb b/components/policy/resources/policy_templates_ko.xtb
index 0bbb1238..f9bb69a 100644
--- a/components/policy/resources/policy_templates_ko.xtb
+++ b/components/policy/resources/policy_templates_ko.xtb
@@ -86,6 +86,7 @@
       True로 설정된 경우 기기의 백라이트 정보가 보고됩니다.</translation>
 <translation id="1076751984131277498">USB 분리 가능 기기 허용 목록</translation>
 <translation id="1077675271127011209">사용 및 비정상 종료 관련 데이터 보고 사용 안함</translation>
+<translation id="1079120839835170592">M115까지 Event.path API를 다시 사용 설정합니다.</translation>
 <translation id="1079425471279127373">정책을 설정하면 강제 설치된 웹 애플리케이션의 일부 원본이 Device Attributes API를 사용하여 기기 속성(예: 일련번호, 호스트 이름)을 가져올 수 있습니다.
 
       Device Attributes API는 웹 API 목록입니다. https://wicg.github.io/WebApiDevice/device_attributes 페이지를 참고하세요. <ph name="WEB_APP_INSTALL_FORCE_LIST_POLICY_NAME" /> 정책을 통해 강제 설치되었거나 키오스크 세션에서 구성된 웹 애플리케이션에 해당하는 원본에만 사용 가능합니다.</translation>
@@ -265,6 +266,7 @@
       정책을 설정하지 않으면 <ph name="CHROME_CLEANUP_NAME" />에서는 <ph name="SAFE_BROWSING_EXTENDED_REPORTING_ENABLED_POLICY_NAME" />에 의해 설정된 정책에 따라 Google에 원치 않는 소프트웨어 감지를 위한 스캔에 관해 보고할 수 있습니다. <ph name="CHROME_CLEANUP_NAME" />에서는 사용자에게 정리를 진행하고 향후 원치 않는 소프트웨어 감지를 지원할 수 있도록 Google과 결과를 공유할 것인지 물어봅니다. 이러한 결과에는 Chrome 개인정보 보호 백서에 명시된 대로 파일 메타데이터, 자동 설치된 확장 프로그램, 레지스트리 키가 포함됩니다.
 
       <ph name="MS_WIN_NAME" />의 경우 이 기능은 <ph name="MS_AD_NAME" /> 도메인에 연결된 인스턴스, Windows 10 Pro에서 실행되는 인스턴스 또는 <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />에 등록된 인스턴스에서만 사용할 수 있습니다.</translation>
+<translation id="1285819498003746288">Event.path API를 사용할 수 없습니다.</translation>
 <translation id="1290634681382861275">USB, 블루투스, 정책 새로고침, 개발자 모드 등을 포함하여 기타 설정을 제어합니다.</translation>
 <translation id="1291880496936992484">경고: 버전 52(2016년 9월경)부터 <ph name="PRODUCT_NAME" />에서 RC4가 완전히 제거되며, 이후 이 정책은 적용되지 않습니다.
 
@@ -2556,6 +2558,7 @@
 <translation id="3652670852519271837">사이트에서 사용자에게 File System API를 통해 파일 및 디렉터리 읽기 액세스 권한을 요청하도록 허용</translation>
 <translation id="3653237928288822292">기본 검색 공급자 아이콘</translation>
 <translation id="3654906736796256792">오디오 샌드박스 실행 허용</translation>
+<translation id="3655885297177292093">Event.path API가 M109 이전에서는 사용할 수 있고 M109~114에서는 사용할 수 없는 기본 상태로 설정됩니다.</translation>
 <translation id="3659542706175323490">정책을 사용 설정하면 기기에서 지원되는 경우 AC로 부팅이 사용 설정됩니다. AC로 부팅을 사용하면 유선 전원이 연결되어 있을 때 시스템이 꺼짐/최대 절전 상태에서 다시 시작될 수 있습니다.
 
       정책을 사용 중지하면 AC로 부팅이 사용 중지됩니다.
@@ -4103,6 +4106,7 @@
 
       설정되어 있지 않으면 사용자가 카드 표시 여부를 제어할 수 있습니다. 기본값은 표시입니다.
       </translation>
+<translation id="5449690328792750354">Event.path API를 사용할 수 있습니다.</translation>
 <translation id="5455609857202311243">HTTP 승인 중 KDC 정책 승인 무시</translation>
 <translation id="5455888515928026628">잠금 화면을 통해 로그인할 때 <ph name="PRODUCT_OS_NAME" />이(가) 서버(온라인) 또는 캐시된 비밀번호(오프라인)를 사용하여 인증할 수 있습니다.
 
@@ -6853,6 +6857,15 @@
 <translation id="8410477879938914253">이 정책은 관리되는 게스트 세션에만 적용됩니다.
       정책을 True로 설정하거나 설정하지 않으면 마지막 창이 종료될 때 사용자에게 로그아웃을 확인하거나 거부해 달라고 요청하는 대화상자가 표시됩니다.
       정책을 False로 설정하면 대화상자가 표시되지 않으며 이에 따라 마지막 창 종료 후의 자동 로그아웃이 사용 중지됩니다.</translation>
+<translation id="8411050083243181286"> M109부터 웹 호환성을 개선하기 위해 비표준 API Event.path가 삭제됩니다. 이 정책은 M115까지 API를 다시 사용 설정합니다.
+
+      정책을 사용으로 설정하면 Event.path API를 사용할 수 있습니다.
+
+      사용 안함으로 설정하면 Event.path API를 사용할 수 없습니다.
+
+      정책을 설정하지 않으면 Event.path API가 M109 이전에서는 사용할 수 있고 M109~114에서는 사용할 수 없는 기본 상태로 설정됩니다.
+
+      이 정책은 Chrome 115 이후 삭제됩니다.</translation>
 <translation id="8415953438346821074">이 설정을 사용으로 설정하면 북마크, 자동 완성 데이터, 비밀번호 등 <ph name="PRODUCT_NAME" /> 프로필에 저장된 설정이 로밍 사용자 프로필 폴더에 저장된 파일 또는 <ph name="ROAMING_PROFILE_LOCATION_POLICY_NAME" /> 정책을 통해 관리자가 지정한 위치에도 작성됩니다. 정책을 사용으로 설정하면 클라우드 동기화는 사용 중지됩니다.
 
       사용 안함으로 설정하거나 설정하지 않으면 일반 로컬 프로필만 사용됩니다.</translation>
diff --git a/components/policy/resources/policy_templates_pt-BR.xtb b/components/policy/resources/policy_templates_pt-BR.xtb
index 602409ba..7687b69 100644
--- a/components/policy/resources/policy_templates_pt-BR.xtb
+++ b/components/policy/resources/policy_templates_pt-BR.xtb
@@ -144,6 +144,7 @@
 <translation id="1160939557934457296">Desativa a continuação na página de aviso de "Navegação segura"</translation>
 <translation id="1163080558183062209">Desativar tipos de impressora na lista de proibições</translation>
 <translation id="117059611145966538">Servidores de impressão externos</translation>
+<translation id="117080706484659953">Permitir a detecção do escopo da política em <ph name="MAC_OS_NAME" />.</translation>
 <translation id="1171785618439752042">A definição da política designa quais tipos de criptografia têm permissão ao solicitar tickets do Kerberos de um servidor do <ph name="MS_AD_NAME" />.
 
       Se a política for definida como:
@@ -941,6 +942,17 @@
 <translation id="1962864958436828230">Definir o limite mínimo para a prevenção contra vazamento de dados de acordo com a restrição da área de transferência</translation>
 <translation id="1964634611280150550">Modo de navegação anônima desativado</translation>
 <translation id="1964802606569741174">Esta política não tem nenhum efeito sobre o app YouTube para Android. Se o modo de segurança do YouTube precisar ser aplicado, a instalação desse app será bloqueada.</translation>
+<translation id="1965363065727209968">setTimeout(…, 0) normalmente é usado para dividir tarefas longas de JavaScript.
+          Quando a política for ativada, as funções setTimeouts e setIntervals com um intervalo menor que 4ms não serão ajustadas de forma tão agressiva.
+          Isso melhora a performance no curto prazo, mas os sites que abusam da API ainda têm os setTimeouts ajustados.
+
+          É possível que a ordem das tarefas em uma página da Web mude, levando a um comportamento inesperado em sites que dependem de uma ordem específica.
+          Também é possível que isso afete sites com muitas funções setTimeout() com um tempo limite de uso de 0ms, por exemplo, aumentando a carga da CPU.
+
+          Para usuários em que essa política não está definida, o <ph name="PRODUCT_NAME" /> vai lançar a mudança gradualmente no Canal Stable.
+
+          Essa é uma política temporária e tem remoção planejada para a versão 107 do <ph name="PRODUCT_NAME" />. Esse prazo pode ser prorrogado caso as empresas precisem de mais tempo.
+          </translation>
 <translation id="1967334955994230472">Desativar Projector</translation>
 <translation id="1969212217917526199">Modifica as políticas sobre versões de depuração do host de acesso remoto.
 
@@ -1485,6 +1497,14 @@
 <translation id="2496180316473517155">Histórico de navegação</translation>
 <translation id="2497751676088107779">Script de usuário</translation>
 <translation id="2497965601277442929">Não permitir que os usuários ativem o HTTPS-Only Mode</translation>
+<translation id="249798396824949930"> Controla se o navegador pode detectar o escopo obrigatório da política em <ph name="MAC_OS_NAME" /> ou não.
+
+      Se a política for ativada ou se não for definida, o escopo será determinado pelo escopo do perfil gerenciado de <ph name="MAC_OS_NAME" />.
+      Se for desativada, todas as políticas serão reconhecidas como a política de escopo da máquina.
+
+      Essa política é temporária e tem como objetivo facilitar a transição para políticas com escopo definido no <ph name="MAC_OS_NAME" />. Ela será removida na versão 107 do <ph name="PRODUCT_NAME" />.
+
+      </translation>
 <translation id="2498238926436517902">Sempre ocultar automaticamente a estante</translation>
 <translation id="250022556568924228">A definição desta política significa que o <ph name="PRODUCT_OS_NAME" /> faz o download dos Termos de Serviço e os apresenta aos usuários ao início de cada sessão de uma conta local do dispositivo. Os usuários só poderão fazer login na sessão após aceitarem os Termos de Serviço.
 
@@ -2701,6 +2721,7 @@
 <translation id="3838094946886335701">Se a política for definida (apenas como recomendado), será possível registrar uma lista de gerenciadores de protocolo, que será mesclada às registradas pelo usuário de forma que as duas configurações sejam aplicadas. Defina a propriedade "protocolo" conforme o esquema, por exemplo, "mailto", e defina a propriedade "URL" conforme o padrão de URL do aplicativo que gerencia o esquema especificado no campo "protocolo". O padrão pode incluir um marcador "%s", que é substituído pelo URL gerenciado.
 
       Os usuários não podem remover um gerenciador de protocolo registrado pela política. No entanto, ao instalar um novo gerenciador padrão, eles podem mudar os gerenciadores de protocolo instalados pela política.</translation>
+<translation id="3851443303439635700">Controla o limite de aninhamento antes que a função setTimeout() do JavaScript comece a ser ajustada.</translation>
 <translation id="3857816702027059082">Ativar <ph name="CHROME_ENTERPRISE_PLATFORM_IDENTITY_CONNECTOR" /> para uma lista de URLs.
 
       Se esta política for definida, ela especificará quais URLs têm permissão para fazer parte do fluxo de atestado e receber o conjunto de sinais da máquina.
@@ -3232,6 +3253,7 @@
 <translation id="4472740647327683596">Largura da página em micrômetros.</translation>
 <translation id="4474167089968829729">Ativar salvamento de senhas no gerenciador de senhas</translation>
 <translation id="4476769083125004742">Se esta política for definida como <ph name="BLOCK_GEOLOCATION_SETTING" />, os apps Android não poderão acessar as informações de local. Se você configurar essa política para qualquer outro valor ou deixá-la sem definição, será solicitado o consentimento do usuário quando um app Android quiser acessar as informações de local.</translation>
+<translation id="4478248026668918517">Detecção do escopo da política de bloqueio.</translation>
 <translation id="4479671363221255277">Se a política for definida, será possível configurar uma lista de padrões de URL que especifica quais sites podem pedir que os usuários concedam permissão de leitura de arquivos ou diretórios no sistema de arquivos do sistema operacional do host com a API File System.
 
       Se a política não tiver definição, <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> será aplicada a todos os sites, se estiver definida. Caso contrário, as configurações pessoais dos usuários serão aplicadas.
@@ -4833,6 +4855,7 @@
 <translation id="6282799760374509080">Permitir ou negar captura de áudio</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
 <translation id="6287310684159482272">Configurações de cookies</translation>
+<translation id="6299147100249359151">Permitir a detecção do escopo da política.</translation>
 <translation id="6300871921951390976">Os usuários só terão permissão para mudar o canal de lançamento do dispositivo se esta política for definida como verdadeira. Se a política for definida como falsa ou não for configurada, os usuários não terão permissão para mudar o canal.
 
       A configuração <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> só terá efeito se <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> for definida como falsa.</translation>
diff --git a/components/policy/resources/policy_templates_ru.xtb b/components/policy/resources/policy_templates_ru.xtb
index 2ba05e3..893a509 100644
--- a/components/policy/resources/policy_templates_ru.xtb
+++ b/components/policy/resources/policy_templates_ru.xtb
@@ -86,6 +86,7 @@
       Если указано значение True, данные передаются.</translation>
 <translation id="1076751984131277498">Список разрешенных отсоединяемых USB-устройств</translation>
 <translation id="1077675271127011209">Не передавать отчеты с данными об использовании и сбоях</translation>
+<translation id="1079120839835170592">Event.path API снова доступен в версиях до M115</translation>
 <translation id="1079425471279127373">Правило позволяет разрешать некоторым источникам принудительно установленных веб-приложений получать атрибуты устройств (например, серийный номер, имя хоста) с помощью Device Attributes API.
 
       Device Attributes API – это список Web API, который указан на странице https://wicg.github.io/WebApiDevice/device_attributes. Они доступны только для источников, которые соответствуют принудительно установленным веб-приложениям, указанным в списке <ph name="WEB_APP_INSTALL_FORCE_LIST_POLICY_NAME" /> или настроенным в сеансе киоска.</translation>
@@ -262,6 +263,7 @@
       Если правило не настроено, <ph name="CHROME_CLEANUP_NAME" /> может отправлять в Google отчеты о сканировании в соответствии с правилом <ph name="SAFE_BROWSING_EXTENDED_REPORTING_ENABLED_POLICY_NAME" />. <ph name="CHROME_CLEANUP_NAME" /> запрашивает у пользователей разрешение на очистку от нежелательного ПО и отправку отчета с результатами сканирования в Google, чтобы улучшить функцию обнаружения такого ПО. Отчет включает метаданные файлов, сведения об автоматически установленных расширениях и ключи реестра в соответствии с Технической публикацией о конфиденциальности в Google Chrome.
 
       В <ph name="MS_WIN_NAME" /> это правило можно настроить только на устройствах домена <ph name="MS_AD_NAME" />, на которых установлена ОС Windows 10 Pro или которые зарегистрированы в программе "<ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />".</translation>
+<translation id="1285819498003746288">Event.path API будет недоступен</translation>
 <translation id="1290634681382861275">Регулирует дополнительные настройки, например для USB, Bluetooth, обновления правил, режима разработчика и другие.</translation>
 <translation id="1291880496936992484">Внимание! Поддержка RC4 в <ph name="PRODUCT_NAME" /> будет полностью прекращена после выхода версии 52 в сентябре 2016 года. После этого правило перестанет действовать.
 
@@ -2543,6 +2545,7 @@
 <translation id="3652670852519271837">Разрешать сайтам запрашивать у пользователей доступ для чтения к файлам и каталогам через File System API</translation>
 <translation id="3653237928288822292">Значок поисковой системы по умолчанию</translation>
 <translation id="3654906736796256792">Разрешить использование тестовой среды для аудио</translation>
+<translation id="3655885297177292093">Будет использоваться статус Event.path API по умолчанию: доступен в версиях до M109 и недоступен в версиях M109 – M114</translation>
 <translation id="3659542706175323490">Если правило включено, загрузка поддерживаемых устройств будет происходить при подаче переменного тока. Система автоматически включается или выходит из спящего режима при появлении сетевого напряжения.
 
       Если правило отключено, загрузка при подаче переменного тока происходить не будет.
@@ -4084,6 +4087,7 @@
 
       Если правило не настроено, пользователь может сам настраивать показ подсказок. По умолчанию они включены.
       </translation>
+<translation id="5449690328792750354">Event.path API будет доступен</translation>
 <translation id="5455609857202311243">Не учитывать подтверждение от KDC при HTTP-аутентификации</translation>
 <translation id="5455888515928026628">При входе в аккаунт на заблокированном экране в <ph name="PRODUCT_OS_NAME" /> аутентификация пользователей может выполняться на сервере (онлайн) или с помощью кешированных паролей (офлайн).
 
@@ -6839,6 +6843,15 @@
 <translation id="8410477879938914253">Правило действует только для управляемых гостевых сеансов.
       Если правило не настроено или задано значение True, то после закрытия последнего окна будет появляться диалоговое окно, в котором пользователь сможет разрешить выход из сеанса или отказаться.
       Если указано значение False, то после закрытия последнего окна диалоговое окно подтверждения появляться не будет и, соответственно, автоматический выход из сеанса будет отключен.</translation>
+<translation id="8411050083243181286"> В версиях, начиная с M109, нестандартный Event.path API будет удален, чтобы улучшить веб-совместимость. Это правило снова включит API, которым можно будет пользоваться до версии M115.
+
+      Если правило включено, Event.path API будет доступен.
+
+      Если оно отключено, Event.path API будет недоступен.
+
+      Если правило не настроено, будет использоваться статус Event.path API по умолчанию: доступен в версиях до M109 и недоступен в версиях M109 – M114.
+
+      Правило будет удалено из Chrome после версии 115.</translation>
 <translation id="8415953438346821074">Если правило включено, настройки профиля <ph name="PRODUCT_NAME" /> (например, закладки, данные автозаполнения, пароли и т. д.) копируются в отдельный файл. Он хранится в папке перемещаемого профиля пользователя или в каталоге, который администратор определил в правиле <ph name="ROAMING_PROFILE_LOCATION_POLICY_NAME" />. Если правило настроено, синхронизация с облаком отключена.
 
       Если правило отключено или не настроено, используются только обычные локальные профили.</translation>
diff --git a/components/policy/resources/policy_templates_tr.xtb b/components/policy/resources/policy_templates_tr.xtb
index 212e8d4f..70f279d 100644
--- a/components/policy/resources/policy_templates_tr.xtb
+++ b/components/policy/resources/policy_templates_tr.xtb
@@ -86,6 +86,7 @@
       True (doğru) değerine ayarlanırsa cihazın arka ışık bilgileri raporlanır.</translation>
 <translation id="1076751984131277498">İzin verilen çıkarılabilir USB cihazların listesi</translation>
 <translation id="1077675271127011209">Kullanım ve kilitlenme ile ilgili verilerin raporlanmasını devre dışı bırak</translation>
+<translation id="1079120839835170592">Event.path API, M115'e kadar yeniden etkinleştirildi.</translation>
 <translation id="1079425471279127373">Zorunlu yüklenmiş web uygulamalarıyla ilgili bazı kaynakların Device Attributes API'yi kullanarak cihaz özelliklerini (ör. seri numarası, ana makine adı) almasına izin vermek için politikayı ayarlar.
 
       Device Attributes API, web API'leri içeren bir listedir. Lütfen https://wicg.github.io/WebApiDevice/device_attributes adresini ziyaret edin. Bu API'ler, yalnızca <ph name="WEB_APP_INSTALL_FORCE_LIST_POLICY_NAME" /> veya Kiosk oturumunda yapılandırılan politika aracılığıyla zorunlu yüklenmiş web uygulamalarına karşılık gelen kaynaklar için kullanılabilir.</translation>
@@ -147,6 +148,7 @@
 <translation id="1160939557934457296">Güvenli Tarama uyarı sayfasından ilerlemeyi devre dışı bırak</translation>
 <translation id="1163080558183062209">Reddetme listesinde yazıcı türlerini devre dışı bırakma</translation>
 <translation id="117059611145966538">Harici yazdırma sunucuları</translation>
+<translation id="117080706484659953"><ph name="MAC_OS_NAME" /> işletim sisteminde politika kapsamını algılamaya izin ver</translation>
 <translation id="1171785618439752042">Politikanın ayarlanması, <ph name="MS_AD_NAME" /> sunucusundan Kerberos biletleri istenirken izin verilen şifreleme türlerini belirler.
 
       Bu politika:
@@ -263,6 +265,7 @@
       Politika ayarlanmadan bırakılırsa <ph name="CHROME_CLEANUP_NAME" />, <ph name="SAFE_BROWSING_EXTENDED_REPORTING_ENABLED_POLICY_NAME" /> tarafından ayarlanan politikaya uygun olarak istenmeyen yazılımların tespit edilmesi için tarama verilerini Google'a gönderebilir. <ph name="CHROME_CLEANUP_NAME" />, kullanıcılara temizlemeyi ve ileride istenmeyen yazılımların tespiti konusunda yardımcı olmak için sonuçları Google ile paylaşmayı isteyip istemediklerini sorar. Bu sonuçlar, Chrome Gizlilik Raporu'nda açıklandığı gibi dosya meta verilerini, otomatik olarak yüklenen uzantıları ve kayıt defteri anahtarlarını içerir.
 
       <ph name="MS_WIN_NAME" /> işletim sisteminde bu işlev yalnızca Windows 10 Pro üzerinde çalışan bir <ph name="MS_AD_NAME" /> alan adına katılmış veya <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" /> öğesine kaydolmuş örneklerde kullanılabilir.</translation>
+<translation id="1285819498003746288">Event.path API kullanılamaz.</translation>
 <translation id="1290634681382861275">USB, Bluetooth, politika yenileme, geliştirici modu gibi çeşitli ayarları kontrol eder.</translation>
 <translation id="1291880496936992484">Uyarı: RC4, sürüm 52'den sonra (yaklaşık olarak Eylül 2016'da) <ph name="PRODUCT_NAME" /> ürününden tamamen kaldırılacak ve sonrasında bu politika çalışmayacaktır.
 
@@ -930,6 +933,17 @@
 <translation id="1962864958436828230">Veri sızıntısını önleme amaçlı pano kısıtlaması için minimum boyut sınırını belirleyin</translation>
 <translation id="1964634611280150550">Gizli mod devre dışı</translation>
 <translation id="1964802606569741174">Bu politikanın Android YouTube uygulaması üzerinde hiçbir etkisi yoktur. YouTube'da Güvenlik Modu uygulanacaksa Android YouTube uygulamasının yüklenmesine izin verilmemelidir.</translation>
+<translation id="1965363065727209968">setTimeout(…, 0), genellikle uzun JavaScript görevlerinin dökümünü almak için kullanılır.
+          Politika, Etkin değerine ayarlandığında 4 ms'den kısa bir aralığa sahip setTimeout'lar ve setInterval'lar yoğun şekilde zaman aşımına uğramaz.
+          Bu şekilde kısa dönem performansı iyileştirilir ancak, API'yi kötüye kullanan web sitelerinin setTimeout'ları nihayetinde zaman aşımına uğrar.
+
+          Bu, bir web sayfasındaki görev sıralamasını değiştirerek bir şekilde belirli bir sıralamaya bağlı olan sitelerde beklenmeyen davranışlara yol açabilir.
+          Ayrıca, 0 ms zaman aşımına sahip çok sayıda setTimeout() kullanımı içeren siteyi de etkileyebilir. (ör. CPU yükünü artırabilir.)
+
+          <ph name="PRODUCT_NAME" />, bu politikanın ayarlanmadığı kullanıcılar için değişikliği kararlı kanalında kademeli olarak kullanıma sunacaktır.
+
+          Bu politika geçicidir ve <ph name="PRODUCT_NAME" /> 107 sürümünde kaldırılması planlanmaktadır. Kuruluşların ihtiyaç duyması halinde bu süre uzatılabilir.
+          </translation>
 <translation id="1967334955994230472">Projektörü devre dışı bırak</translation>
 <translation id="1969212217917526199">Uzaktan erişim ana makinesinin Hata Ayıklama yapılarındaki politikaları geçersiz kılar.
 
@@ -1464,6 +1478,14 @@
 <translation id="2496180316473517155">Tarama geçmişi</translation>
 <translation id="2497751676088107779">Kullanıcı komut dosyası</translation>
 <translation id="2497965601277442929">Kullanıcıların Yalnızca HTTPS Modunu etkinleştirmesine izin verme</translation>
+<translation id="249798396824949930"> Tarayıcının, <ph name="MAC_OS_NAME" /> işletim sisteminde zorunlu politika kapsamını algılayıp algılamayacağını kontrol eder.
+
+      Politika, etkin değerine ayarlanır veya ayarlanmadan bırakılırsa her politikanın kapsamı, <ph name="MAC_OS_NAME" /> yönetilen profilinin kapsamına göre belirlenir.
+      Politika, devre dışı değerine ayarlanırsa tüm politikalar, makine genelinde geçerli politika olarak yeniden değerlendirilir.
+
+      Bu politika, <ph name="MAC_OS_NAME" /> işletim sisteminde uygun kapsama sahip politikalara sorunsuz geçişi kolaylaştırmak için geçici olarak kullanımdadır ve <ph name="PRODUCT_NAME" /> 107 sürümünde kaldırılacaktır.
+
+      </translation>
 <translation id="2498238926436517902">Rafı her zaman otomatik olarak gizle</translation>
 <translation id="250022556568924228">Politika ayarlanırsa <ph name="PRODUCT_OS_NAME" />, Hizmet Şartları'nı indirir ve cihaz yerel hesabı oturumu her başlatıldığında kullanıcılara gösterir. Kullanıcılar yalnızca Hizmet Şartları'nı kabul ettikten sonra oturuma giriş yapabilirler.
 
@@ -2509,6 +2531,7 @@
 <translation id="3652670852519271837">Sitelerin kullanıcıdan File System API üzerinden dosya ve dizinlere okuma erişimi istemesine izin ver</translation>
 <translation id="3653237928288822292">Varsayılan arama sağlayıcı simgesi</translation>
 <translation id="3654906736796256792">Sesli korumalı alanın çalışmasına izin ver</translation>
+<translation id="3655885297177292093">Event.path API varsayılan durumda olacak: M109'dan önce kullanılabilir ve M109 ile 114 arasında kullanılamaz.</translation>
 <translation id="3659542706175323490">Politika, Etkin değerine ayarlanırsa AC'de başlat özelliği her zaman açık olur (desteklenen cihazlarda). AC'de başlat özelliği, güç kablosu takıldığında sisteminin Kapalı veya Hazırda Bekleme durumundan yeniden başlatılmasına olanak sağlar.
 
       Politika, Devre Dışı değerine ayarlanırsa AC'de başlat özelliğini kapalı olur.
@@ -2681,6 +2704,7 @@
 <translation id="3838094946886335701">Politikayı (yalnızca önerildiği gibi) ayarlamak, kullanıcının kaydettiği ile birleşen protokol işleyicileri listesi kaydetmenize olanak tanır. Böylece her iki liste de kullanılır. "Protokol" özelliğini "mailto" gibi bir düzene ayarlayın ve "URL" özelliğini "protokol" alanında belirtilen düzeni işleyen uygulamanın URL kalıbına ayarlayın. Kalıp, işlenen URL'nin yerini aldığı bir "%s" yer tutucu içerebilir.
 
       Kullanıcılar politika tarafından kaydedilen bir protokol işleyicisini kaldıramazlar. Ancak kullanıcılar yeni bir varsayılan işleyici yükleyerek politika tarafından kaydedilen protokol işleyicilerini değiştirebilirler.</translation>
+<translation id="3851443303439635700">JavaScript setTimeout() fonksiyonu zaman aşımına uğramaya başlamadan önceki iç içe yerleştirme eşiğini kontrol et</translation>
 <translation id="3857816702027059082">URL listesi için <ph name="CHROME_ENTERPRISE_PLATFORM_IDENTITY_CONNECTOR" /> politikasını etkinleştirin.
 
       Bu politikanın ayarlanması, makineden sinyal grubu alma onay akışına dahil olmasına izin verilmesi gereken URL'leri belirtir.
@@ -3211,6 +3235,7 @@
 <translation id="4472740647327683596">Mikrometre cinsinden sayfanın genişliği</translation>
 <translation id="4474167089968829729">Şifrelerin, şifre yöneticisine kaydedilmesini etkinleştir</translation>
 <translation id="4476769083125004742">Bu politika <ph name="BLOCK_GEOLOCATION_SETTING" /> seçeneğine ayarlanırsa Android uygulamaları konum bilgisine erişemez. Bu politikayı başka bir değere ayarlar veya ayarlamadan bırakırsanız, bir Android uygulaması konum bilgisine erişmek istediğinde kullanıcıdan izin istenir.</translation>
+<translation id="4478248026668918517">Politika kapsamını algılamayı engelle.</translation>
 <translation id="4479671363221255277">Bu politika ayarlanırsa kullanıcılardan ana makine işletim sisteminin dosya sisteminde bulunan dosya veya dizinlere File System API üzerinden okuma erişimi vermelerini isteyebilecek sitelerin belirtildiği URL kalıpları listesini oluşturabilirsiniz.
 
       Politika ayarlanmadan bırakılırsa <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> (etkinse) bütün siteler için geçerli olur. Etkin değilse kullanıcının ayarları geçerlidir.
@@ -4051,6 +4076,7 @@
 
       Politika ayarlanmazsa kart görünürlüğünü kullanıcı kontrol edebilir. Varsayılan ayarda kartlar görünür.
       </translation>
+<translation id="5449690328792750354">Event.path API kullanılabilir.</translation>
 <translation id="5455609857202311243">HTTP kimlik doğrulaması sırasında KDC politikası onayını yoksay</translation>
 <translation id="5455888515928026628">Kilit ekranı üzerinden giriş yapılırken <ph name="PRODUCT_OS_NAME" />, bir sunucu (çevrimiçi) veya önbelleğe alınmış bir şifre (çevrimdışı) ile kimlik doğrulaması yapabilir.
 
@@ -4797,6 +4823,7 @@
 <translation id="6282799760374509080">Ses yakalamaya izin verme veya reddetme</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
 <translation id="6287310684159482272">Çerez ayarları</translation>
+<translation id="6299147100249359151">Politika kapsamını algılamaya izin ver.</translation>
 <translation id="6300871921951390976">Yalnızca bu politika Doğru değerine ayarlanırsa kullanıcıların cihazın sürüm kanalını değiştirmesine izin verilir. Bu politika Yanlış değerine ayarlanır veya ayarlanmadan bırakılırsa kullanıcıların kanalı değiştirmesine izin verilmez.
 
       <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> politikasının etkili olabilmesi için <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> politikasının Yanlış değerine ayarlanması şarttır.</translation>
@@ -6798,6 +6825,15 @@
 <translation id="8410477879938914253">Bu politika, yalnızca yönetilen misafir oturumları için geçerlidir.
       Politika, Doğru değerine ayarlanır veya ayarlamadan bırakılırsa son pencere kapatıldığında kullanıcıya oturumu kapatmayı onaylayıp onaylamadığını soran bir iletişim gösterilir.
       Politikayı Yanlış değerine ayarlamak, iletişimin gösterilmesine engel olur ve dolayısıyla son pencerenin kapatılmasından sonra otomatik oturum kapatmayı devre dışı bırakır.</translation>
+<translation id="8411050083243181286"> Standart olmayan Event.path API, web uyumluluğunu iyileştirmek için M109'dan itibaren kaldırılacak. Bu politika, API'yi M115'e kadar yeniden etkinleştirir.
+
+      Bu politika etkin değerine ayarlanırsa Event.path API kullanılabilir.
+
+      Bu politika devre dışı değerine ayarlanırsa Event.path API kullanılamaz.
+
+      Bu politika ayarlanmadan bırakılırsa Event.path API varsayılan durumda olur: M109'dan önce kullanılabilir ve M109 ile 114 arasında kullanılamaz.
+
+      Bu politika Chrome 115'ten sonra kaldırılacaktır.</translation>
 <translation id="8415953438346821074">Bu ayarı etkinleştirirseniz <ph name="PRODUCT_NAME" /> profillerinde depolanan yer işaretleri, otomatik doldurma verileri, şifreler gibi ayarlar ayrıca Dolaşım kullanıcı profil klasöründe depolanan bir dosyaya veya Yönetici tarafından <ph name="ROAMING_PROFILE_LOCATION_POLICY_NAME" /> politikası aracılığıyla belirtilen bir konuma da yazılır. Bu politikayı etkinleştirmek bulut senkronizasyonunu devre dışı bırakır.
 
       Bu politika devre dışı bırakılır veya ayarlanmazsa yalnızca normal yerel profiller kullanılır.</translation>
diff --git a/components/policy/resources/policy_templates_uk.xtb b/components/policy/resources/policy_templates_uk.xtb
index 91d4d45..3be42fd 100644
--- a/components/policy/resources/policy_templates_uk.xtb
+++ b/components/policy/resources/policy_templates_uk.xtb
@@ -147,6 +147,7 @@
 <translation id="1160939557934457296">Вимикати переходи зі сторінки застереження Безпечного перегляду</translation>
 <translation id="1163080558183062209">Вимкнути типи принтерів у списку заборонених</translation>
 <translation id="117059611145966538">Зовнішні сервери друку</translation>
+<translation id="117080706484659953">Дозволити виявлення області дії правил для <ph name="MAC_OS_NAME" /></translation>
 <translation id="1171785618439752042">За допомогою налаштувань цього правила можна визначити, які типи шифрувань дозволені, коли надсилаються запити на заявки Kerberos із сервера <ph name="MS_AD_NAME" />.
 
       Якщо для цього правила вибрано значення:
@@ -943,6 +944,17 @@
 <translation id="1962864958436828230">Установити мінімальний обсяг для обмеження буфера обміну, пов’язаного із запобіганням витоку даних</translation>
 <translation id="1964634611280150550">Режим анонімного перегляду вимкнено</translation>
 <translation id="1964802606569741174">Це правило не впливає на додаток YouTube на пристрої Android. Щоб для YouTube використовувався Безпечний режим, забороніть встановлення додатка YouTube на пристрої Android.</translation>
+<translation id="1965363065727209968">Функція setTimeout(…, 0) зазвичай використовується, щоб розділяти великі завдання JavaScript на менші.
+          Якщо правило ввімкнено, значення функцій setTimeouts і setIntervals з інтервалом, меншим ніж 4 мс, обмежуються не так швидко.
+          Це покращує ефективність у короткостроковій перспективі, але на веб-сайтах, які зловживають API, значення функції setTimeouts будуть обмежуватися.
+
+          Це може вплинути на послідовність виконання завдань на веб-сторінці. Через це на сайтах, що якимось чином залежать від певної послідовності, може відбуватися несподівана поведінка.
+          Також це може впливати на сайти, що містять багато функцій setTimeout() з часом очікування 0 мс (зокрема може зрости навантаження на ЦП).
+
+          Якщо правило не вказано, <ph name="PRODUCT_NAME" /> запускатиме цю зміну поступово в стабільній версії.
+
+          Це тимчасове правило, яке планується вилучити в <ph name="PRODUCT_NAME" /> 107. Кінцевий термін може бути подовжено, якщо це потрібно для підприємств.
+          </translation>
 <translation id="1967334955994230472">Вимкнути Projector</translation>
 <translation id="1969212217917526199">Замінює правила налагоджувальних складань хосту віддаленого доступу.
 
@@ -1487,6 +1499,14 @@
 <translation id="2496180316473517155">Історія веб-перегляду</translation>
 <translation id="2497751676088107779">Скрипт користувача</translation>
 <translation id="2497965601277442929">Заборонити користувачам вмикати режим "Лише HTTPS"</translation>
+<translation id="249798396824949930"> Визначає, чи може веб-переглядач виявляти обов’язкову область дії правил у <ph name="MAC_OS_NAME" />.
+
+      Якщо правило ввімкнено або не налаштовано, область дії для кожного правила залежатиме від області дії керованого профілю в <ph name="MAC_OS_NAME" />.
+      Якщо його вимкнути, усі правила визначатимуться як правила на рівні пристрою.
+
+      Це правило діє тимчасово, щоб спростити перехід на правила з відповідною областю дії в <ph name="MAC_OS_NAME" />. У <ph name="PRODUCT_NAME" /> 107 його буде вилучено.
+
+      </translation>
 <translation id="2498238926436517902">Завжди автоматично ховати полицю</translation>
 <translation id="250022556568924228">Якщо це правило налаштоване, <ph name="PRODUCT_OS_NAME" /> завантажує Умови використання та показує їх користувачам щоразу, коли починається сеанс локального облікового запису на пристрої. Користувачі зможуть увійти в обліковий запис, лише коли приймуть Умови використання.
 
@@ -2708,6 +2728,7 @@
 <translation id="3838094946886335701">Налаштувавши це правило (лише як рекомендоване), ви зможете зареєструвати список обробників протоколів, які об'єднуються з тими, що реєструє користувач, використовуючи обидва набори. Для властивості "protocol" потрібно вказати схему, як-от mailto, а для властивості "URL" – шаблон URL-адреси додатка, який обробляє схему, указану в полі "protocol". Шаблон може містити заповнювач "%s", який замінює оброблена URL-адреса.
 
       Користувачі не можуть видалити обробник протоколів, зареєстрований цим правилом. Проте, установивши новий обробник за умовчанням, вони зможуть змінити обробники протоколів, установлених правилом.</translation>
+<translation id="3851443303439635700">Контролювати поріг для вкладень, до якого значення функції JavaScript setTimeout() починають обмежуватися</translation>
 <translation id="3857816702027059082">Увімкнути <ph name="CHROME_ENTERPRISE_PLATFORM_IDENTITY_CONNECTOR" /> для списку URL-адрес.
 
       Це правило визначає, які URL-адреси можуть проходити засвідчення й отримувати набір сигналів від машини.
@@ -3239,6 +3260,7 @@
 <translation id="4472740647327683596">Ширина сторінки в мікрометрах</translation>
 <translation id="4474167089968829729">Дозволити зберігати паролі в диспетчері паролів</translation>
 <translation id="4476769083125004742">Якщо для правила вибрано значення "<ph name="BLOCK_GEOLOCATION_SETTING" />", додатки Android не матимуть доступу до геоданих. Якщо це правило не налаштовано або має інше значення, користувачеві пропонуватиметься надати дозвіл, коли додатки Android запитуватимуть доступ до геоданих.</translation>
+<translation id="4478248026668918517">Блокувати виявлення області дії правил.</translation>
 <translation id="4479671363221255277">За допомогою цього правила можна вказати список шаблонів URL-адрес, що визначають сайти, яким дозволено запитувати дозвіл на перегляд файлів чи каталогів у файловій системі ОС хосту через File System API.
 
       Якщо це правило не налаштовано, до всіх сайтів застосовуватиметься правило <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> за умови, що воно налаштоване. Якщо ні, використовуються особисті налаштування користувачів.
@@ -4840,6 +4862,7 @@
 <translation id="6282799760374509080">Дозволити чи заборонити запис аудіо</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
 <translation id="6287310684159482272">Налаштування файлів сookie</translation>
+<translation id="6299147100249359151">Дозволити виявлення області дії правил.</translation>
 <translation id="6300871921951390976">Користувачі можуть змінювати версію оновлення для пристрою, лише якщо для цього правила вибрано значення True. Якщо для цього правила вибрано значення False або його не налаштовано, користувачі не можуть змінювати цю версію.
 
 Налаштування правила <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> діють, лише якщо для <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> вибрано значення False.</translation>
diff --git a/components/policy/resources/policy_templates_vi.xtb b/components/policy/resources/policy_templates_vi.xtb
index 8c883d2..6be2a06 100644
--- a/components/policy/resources/policy_templates_vi.xtb
+++ b/components/policy/resources/policy_templates_vi.xtb
@@ -86,6 +86,7 @@
       Nếu bạn đặt chính sách này thành true, thì thông tin về đèn nền của thiết bị sẽ được báo cáo.</translation>
 <translation id="1076751984131277498">Danh sách thiết bị USB được phép tháo</translation>
 <translation id="1077675271127011209">Tắt tính năng báo cáo về hoạt động sử dụng và dữ liệu liên quan đến sự cố</translation>
+<translation id="1079120839835170592">Đã bật lại API Event.path cho đến phiên bản M115.</translation>
 <translation id="1079425471279127373">Đặt chính sách để cho phép một số nguồn gốc của ứng dụng web bị buộc cài đặt nhận các thuộc tính của thiết bị (ví dụ: số sê-ri, tên máy chủ) bằng cách sử dụng API thuộc tính thiết bị.
 
       API Thuộc tính thiết bị là danh sách các API web, vui lòng xem tại https://wicg.github.io/WebApiDevice/device_attributes. Các API này chỉ có sẵn cho những nguồn tương ứng với các ứng dụng web bị buộc cài đặt qua <ph name="WEB_APP_INSTALL_FORCE_LIST_POLICY_NAME" /> hoặc ứng dụng được định cấu hình trong phiên Kiosk.</translation>
@@ -265,6 +266,7 @@
       Nếu bạn không đặt chính sách này, <ph name="CHROME_CLEANUP_NAME" /> có thể báo cáo về các lần quét tìm phần mềm không muốn cho Google, theo chính sách do <ph name="SAFE_BROWSING_EXTENDED_REPORTING_ENABLED_POLICY_NAME" /> đặt ra. <ph name="CHROME_CLEANUP_NAME" /> sẽ hỏi người dùng xem họ có muốn dọn dẹp hay không và chia sẻ kết quả với Google nhằm giúp phát hiện phần mềm không mong muốn trong tương lai. Những kết quả này có siêu dữ liệu tệp, tiện ích tự động cài đặt và khóa sổ đăng ký như mô tả trong Báo cáo chính thức về quyền riêng tư của Chrome.
 
       Trên <ph name="MS_WIN_NAME" />, chức năng này chỉ có ở những phiên bản liên kết với một miền <ph name="MS_AD_NAME" />, chạy trên Windows 10 Pro hoặc đã đăng ký <ph name="CHROME_BROWSER_CLOUD_MANAGEMENT_NAME" />.</translation>
+<translation id="1285819498003746288">Sẽ không cung cấp API Event.path.</translation>
 <translation id="1290634681382861275">Kiểm soát các tùy chọn cài đặt khác bao gồm USB, Bluetooth, làm mới chính sách, chế độ nhà phát triển và những nội dung khác.</translation>
 <translation id="1291880496936992484">Cảnh báo: RC4 sẽ bị xóa hoàn toàn khỏi <ph name="PRODUCT_NAME" /> sau phiên bản 52 (khoảng tháng 9 năm 2016) và chính sách này sẽ ngừng hoạt động sau đó.
 
@@ -2560,6 +2562,7 @@
 <translation id="3652670852519271837">Cho phép các trang web yêu cầu người dùng cấp quyền đọc các tệp và thư mục qua API Hệ thống tệp</translation>
 <translation id="3653237928288822292">Biểu tượng nhà cung cấp dịch vụ tìm kiếm mặc định</translation>
 <translation id="3654906736796256792">Cho phép chạy hộp cát âm thanh</translation>
+<translation id="3655885297177292093">API Event.path sẽ ở trạng thái mặc định: có ở các phiên bản trước M109 và không có ở các phiên bản từ M109 đến 114.</translation>
 <translation id="3659542706175323490">Khi bạn đặt chính sách này thành Bật, tính năng khởi động khi cắm nguồn AC sẽ bật liên tục nếu được hỗ trợ trên thiết bị này. Tính năng khởi động khi cắm nguồn AC cho phép hệ thống khởi động lại từ trạng thái Tắt hoặc Ngủ đông sau khi người dùng cắm dây nguồn.
 
       Khi bạn đặt chính sách này thành Tắt, tính năng khởi động khi cắm nguồn AC sẽ tắt liên tục.
@@ -4099,6 +4102,7 @@
 
       Nếu bạn không đặt chính sách này, người dùng có thể kiểm soát khả năng hiển thị của thẻ. Thẻ sẽ hiển thị theo tùy chọn cài đặt mặc định.
       </translation>
+<translation id="5449690328792750354">Sẽ cung cấp API Event.path.</translation>
 <translation id="5455609857202311243">Bỏ qua việc phê duyệt chính sách KDC trong quá trình xác thực HTTP</translation>
 <translation id="5455888515928026628">Trong khi đăng nhập qua màn hình khóa, <ph name="PRODUCT_OS_NAME" /> có thể xác thực với một máy chủ (trực tuyến) hoặc dùng mật khẩu lưu trong bộ nhớ đệm (ngoại tuyến).
 
@@ -6840,6 +6844,15 @@
 <translation id="8410477879938914253">Chính sách này chỉ áp dụng cho các phiên khách được quản lý.
       Nếu bạn không đặt hoặc đặt chính sách này thành Bật, thì một hộp thoại yêu cầu người dùng xác nhận hoặc từ chối đăng xuất khi cửa sổ cuối cùng đóng lại sẽ hiển thị.
       Nếu bạn đặt chính sách này thành Tắt, hộp thoại này sẽ không hiển thị, đồng thời tính năng tự động đăng xuất sẽ tắt sau khi đóng cửa sổ cuối cùng.</translation>
+<translation id="8411050083243181286"> Kể từ M109, API Event.path không chuẩn sẽ bị xoá để cải thiện khả năng tương thích trên web. Chính sách này sẽ bật lại API cho đến phiên bản M115.
+
+      Nếu bạn bật chính sách này, thì API Event.path sẽ được cung cấp.
+
+      Nếu bạn tắt chính sách này, thì API Event.path sẽ không được cung cấp.
+
+      Nếu bạn không đặt chính sách này, thì API Event.path sẽ ở trạng thái mặc định: có ở các phiên bản trước M109 và không có ở phiên bản từ M109 đến 114.
+
+      Chính sách này sẽ bị xoá sau Chrome 115.</translation>
 <translation id="8415953438346821074">Nếu bạn bật tùy chọn cài đặt này, các tùy chọn cài đặt lưu trữ trong hồ sơ của <ph name="PRODUCT_NAME" /> như dấu trang, dữ liệu tự động điền, mật khẩu, v.v, cũng sẽ được ghi vào một tệp được lưu trữ trong thư mục hồ sơ Người dùng chuyển vùng hoặc một vị trí do Quản trị viên chỉ định thông qua chính sách <ph name="ROAMING_PROFILE_LOCATION_POLICY_NAME" />. Việc bật chính sách này sẽ tắt tính năng đồng bộ hóa trên đám mây.
 
       Nếu bạn tắt hoặc không đặt chính sách này, thì người dùng chỉ dùng được các hồ sơ cục bộ thông thường.</translation>
diff --git a/components/policy/resources/policy_templates_zh-CN.xtb b/components/policy/resources/policy_templates_zh-CN.xtb
index ffe0dc5..a50f3d5 100644
--- a/components/policy/resources/policy_templates_zh-CN.xtb
+++ b/components/policy/resources/policy_templates_zh-CN.xtb
@@ -147,6 +147,7 @@
 <translation id="1160939557934457296">禁止从安全浏览警告页面继续访问</translation>
 <translation id="1163080558183062209">禁用拒绝列表中的打印机类型</translation>
 <translation id="117059611145966538">外部打印服务器</translation>
+<translation id="117080706484659953">允许在 <ph name="MAC_OS_NAME" /> 上检测政策范围</translation>
 <translation id="1171785618439752042">通过设置此政策,您可以指定能使用哪些加密类型向 <ph name="MS_AD_NAME" /> 服务器请求 Kerberos 票据。
 
       如果此政策设为:
@@ -914,6 +915,17 @@
 <translation id="1962864958436828230">设定数据大小下限以与旨在预防数据泄露的剪贴板限制规则搭配使用</translation>
 <translation id="1964634611280150550">隐身模式已停用</translation>
 <translation id="1964802606569741174">此政策对 Android 版 YouTube 应用没有任何影响。如果应在 YouTube 中强制启用安全模式,则应禁止安装 Android 版 YouTube 应用。</translation>
+<translation id="1965363065727209968">setTimeout(…, 0) 通常用于中断耗时较长的 JavaScript 任务。
+          如果此政策设为 Enabled,系统不会主动将时间间隔小于 4 毫秒的 setTimeout 和 setInterval 强制设为下限值。
+          这可以提升短时间内的性能,但如果网站滥用该 API,其 setTimeout 最终仍会被强制设为下限值。
+
+          这可能会改变网页上的任务排序,从而导致以某种方式依赖于特定顺序的网站上出现意外行为。
+          这可能还会影响大量使用超时设为 0 毫秒的 setTimeout() 的网站,例如增加 CPU 负载。
+
+          对于未设置此政策的用户,<ph name="PRODUCT_NAME" /> 将在稳定渠道上逐步推出相应变更。
+
+          这是一项暂时性政策,我们计划在 <ph name="PRODUCT_NAME" /> 107 中将其移除。如果众多企业需要此政策,这个期限可能会延长。
+          </translation>
 <translation id="1967334955994230472">停用投影仪</translation>
 <translation id="1969212217917526199">覆盖与远程访问主机的调试版本号相关的政策。
 
@@ -1446,6 +1458,14 @@
 <translation id="2496180316473517155">浏览记录</translation>
 <translation id="2497751676088107779">用户脚本</translation>
 <translation id="2497965601277442929">不允许用户启用纯 HTTPS 模式</translation>
+<translation id="249798396824949930"> 控制浏览器是否可以在 <ph name="MAC_OS_NAME" /> 上检测到强制性政策范围。
+
+      如果此政策设为 Enabled 或未设置,每个政策的范围都会由 <ph name="MAC_OS_NAME" /> 所管理个人资料的范围决定。
+      如果此政策设为 Disabled,系统会将所有政策识别为机器范围的政策。
+
+      此政策是暂时性政策,为了便于在 <ph name="MAC_OS_NAME" /> 中顺利过渡到适当范围的政策,并且将在 <ph name="PRODUCT_NAME" /> 107 中移除。
+
+      </translation>
 <translation id="2498238926436517902">始终自动隐藏任务栏</translation>
 <translation id="250022556568924228">如果您设置了此政策,<ph name="PRODUCT_OS_NAME" />会下载《服务条款》,并会在用户开始进行设备本地帐号会话时将其呈现给用户。用户必须先接受《服务条款》才能登录会话。
 
@@ -2655,6 +2675,7 @@
 <translation id="3838094946886335701">通过设置此政策(仅为建议性政策),您可以注册一个协议处理程序列表以与用户注册的协议处理程序列表合并,从而同时使用这两组协议处理程序。“protocol”属性应设为“mailto”之类的协议,“URL”属性应设为处理相应协议(“protocol”字段中指定的协议)的应用所采用的网址格式。该格式可以包含一个“%s”占位符(将会替换为被处理的网址)。
 
       用户无法卸载由政策注册的协议处理程序,但可通过安装新的默认处理程序来更改由政策安装的协议处理程序。</translation>
+<translation id="3851443303439635700">控制嵌套阈值,以指定何时开始将 JavaScript setTimeout() 函数强制设为下限值</translation>
 <translation id="3857816702027059082">此政策旨在为一个网址列表启用 <ph name="CHROME_ENTERPRISE_PLATFORM_IDENTITY_CONNECTOR" />。
 
       通过设置此政策,您可以指定应允许哪些网址参与认证流程,以便接收来自计算机的一系列信号。
@@ -3174,6 +3195,7 @@
 <translation id="4472740647327683596">页面的宽度(以微米为单位)</translation>
 <translation id="4474167089968829729">允许将密码保存到密码管理器</translation>
 <translation id="4476769083125004742">如果此政策设为 <ph name="BLOCK_GEOLOCATION_SETTING" />,Android 应用将无法使用位置信息。如果此政策设为任何其他值或未设置,那么当 Android 应用想使用位置信息时,它会询问用户是否同意。</translation>
+<translation id="4478248026668918517">屏蔽政策范围检测。</translation>
 <translation id="4479671363221255277">通过设置此政策,您可以罗列一些网址格式,从而指定哪些网站可以通过 File System API 请求用户向其授予对主机操作系统的文件系统中的文件或目录的读取权限。
 
       如果您未设置此政策,那么,倘若 <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME" /> 已设置,系统便会将它应用于所有网站,否则就会应用用户的个人设置。
@@ -4751,6 +4773,7 @@
 <translation id="6282799760374509080">是否允许音频捕获</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
 <translation id="6287310684159482272">Cookie 设置</translation>
+<translation id="6299147100249359151">允许检测政策范围。</translation>
 <translation id="6300871921951390976">如果此政策设为 True,用户只能更改设备的发布版本。如果此政策设为 False 或未设置,用户将无法更改版本。
 
       仅当 <ph name="CHROME_OS_RELEASE_CHANNEL_DELEGATED_POLICY_NAME" /> 设为 False 时,设置 <ph name="CHROME_OS_RELEASE_CHANNEL_POLICY_NAME" /> 才会产生影响。</translation>
diff --git a/components/policy/resources/webui/policy.html b/components/policy/resources/webui/policy.html
index 5126fac..8675505 100644
--- a/components/policy/resources/webui/policy.html
+++ b/components/policy/resources/webui/policy.html
@@ -5,7 +5,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no">
 <title>$i18n{title}</title>
 
-<link rel="stylesheet" href="./policy.css">
+<link rel="stylesheet" href="chrome://policy/policy.css">
 <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
 
 </head>
@@ -40,6 +40,175 @@
       <!--  This is where policy tables get dynamically added. -->
     </section>
   </main>
+  <div hidden>
+    <fieldset id="status-box-template">
+      <legend class="legend"></legend>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelVersion}</div>
+        <div class="version"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelMachineEnrollmentMachineName}</div>
+        <div class="machine-enrollment-name"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelMachineEnrollmentDomain}</div>
+        <div class="machine-enrollment-domain"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelMachineEnrollmentToken}</div>
+        <div class="machine-enrollment-token"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelMachineEntrollmentDeviceId}</div>
+        <div class="machine-enrollment-device-id"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelUsername}</div>
+        <div class="username"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelManagedBy}</div>
+        <div class="managed-by"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelGaiaId}</div>
+        <div class="gaia-id"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelClientId}</div>
+        <div class="client-id"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelAssetId}</div>
+        <div class="asset-id"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelLocation}</div>
+        <div class="location"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelDirectoryApiId}</div>
+        <div class="directory-api-id"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelTimeSinceLastFetchAttempt}</div>
+        <div class="time-since-last-fetch-attempt"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelTimeSinceLastRefresh}</div>
+        <div class="time-since-last-refresh"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelRefreshInterval}</div>
+        <div class="refresh-interval"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelPoliciesPush}</div>
+        <div class="policy-push"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelStatus}</div>
+        <div class="status"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelIsAffiliated}</div>
+        <div class="is-affiliated"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelIsOffHoursActive}</div>
+        <div class="is-offhours-active"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelVersion}</div>
+        <div class="version"></div>
+      </div>
+      <div class="status-entry" hidden>
+        <div class="label">$i18n{labelLastCloudReportSentTimestamp}</div>
+        <div class="last-cloud-report-sent-timestamp"></div>
+      </div>
+    </fieldset>
+
+    <div class="policy-table" id="policy-table-template" role="table"
+         aria-labelledby="policy-header">
+      <h3 class="header" id="policy-header"></h3>
+      <p class="id"></p>
+      <div class="main">
+        <div class="header row" role="row">
+          <div class="name" role="columnheader">$i18n{headerName}</div>
+          <div class="value" role="columnheader">$i18n{headerValue}</div>
+          <div class="source" role="columnheader">$i18n{headerSource}</div>
+          <div class="scope" role="columnheader">$i18n{headerScope}</div>
+          <div class="level" role="columnheader">$i18n{headerLevel}</div>
+          <div class="messages" role="columnheader">$i18n{headerStatus}</div>
+          <div class="toggle" role="columnheader"></div>
+        </div>
+        <div class="no-policy">$i18n{noPoliciesSet}</div>
+      </div>
+    </div>
+
+    <div class="policy-conflict-data" id="policy-conflict-template"
+         role="rowgroup" hidden>
+      <div class="policy conflict row" role="row">
+          <div class="name" role="rowheader">$i18n{conflictValue}</div>
+          <div class="value" role="cell"></div>
+          <div class="source" role="cell"></div>
+          <div class="scope" role="cell"></div>
+          <div class="level" role="cell"></div>
+          <div class="messages" role="cell"></div>
+          <div class="toggle" role="cell"></div>
+      </div>
+    </div>
+
+    <div class="policy-data" id="policy-template" role="rowgroup">
+      <div class="policy row" role="row">
+        <div class="name" role="rowheader" aria-labelledby="name">
+          <a class="link" target="_blank">
+            <span id="name"></span>
+            <img src="chrome://resources/images/open_in_new.svg">
+          </a>
+        </div>
+        <div class="value" role="cell"></div>
+        <div class="source" role="cell"></div>
+        <div class="scope" role="cell"></div>
+        <div class="level" role="cell"></div>
+        <div class="messages" role="cell"></div>
+        <div class="toggle" role="cell">
+          <a is="action-link" class="show-more">$i18n{showMore}</a>
+          <a is="action-link" class="show-less" hidden>$i18n{showLess}</a>
+        </div>
+      </div>
+      <div class="value row" role="row" hidden>
+        <div class="name" role="rowheader">$i18n{value}</div>
+        <div class="value" role="cell"></div>
+        <div class="copy" role="cell">
+          <a is="action-link" class="copy-value link" role="cell">
+            <img src="chrome://resources/images/icon_copy_content.svg">
+          </a>
+        </div>
+      </div>
+      <div class="errors row" role="row" hidden>
+        <div class="name" role="rowheader">$i18n{error}</div>
+        <div class="value" role="cell"></div>
+      </div>
+      <div class="warnings row" role="row" hidden>
+        <div class="name" role="rowheader">$i18n{warning}</div>
+        <div class="value" role="cell"></div>
+      </div>
+      <div class="infos row" role="row" hidden>
+        <div class="name" role="rowheader">$i18n{info}</div>
+        <div class="value" role="cell"></div>
+      </div>
+    </div>
+
+    <div class="policy-precedence-data" id="policy-precedence-template"
+         role="rowgroup">
+      <div class="precedence row" role="row">
+          <div class="name" role="rowheader">$i18n{labelPrecedence}</div>
+          <div class="value" role="cell"></div>
+      </div>
+    </div>
+  </div>
 </body>
 
 <script type="module" src="policy.js"></script>
diff --git a/components/policy/resources/webui/policy.js b/components/policy/resources/webui/policy.js
index a9d997b..e745cc8 100644
--- a/components/policy/resources/webui/policy.js
+++ b/components/policy/resources/webui/policy.js
@@ -13,39 +13,31 @@
 
 // Functions for tests that directly inject JS to access certain UI elements.
 function getPolicyFieldsets() {
-  const statusBoxes = document.querySelectorAll('status-box');
-  return Array.from(statusBoxes)
-      .map(box => box.shadowRoot.querySelector('fieldset'));
+  const statusSection = document.querySelector('#status-section');
+  return statusSection.querySelectorAll('fieldset');
 }
 
 function getAllPolicyTables() {
-  return document.querySelectorAll('#policy-ui policy-table');
+  return document.querySelector('#policy-ui').querySelectorAll('.policy-table');
 }
 
 function getAllPolicyRows(policyTable) {
-  return policyTable.shadowRoot.querySelectorAll('policy-row');
+  return policyTable.querySelectorAll('.policy.row');
 }
 
 function getAllPolicyRowDivs(policyRow) {
-  const row = policyRow.shadowRoot.querySelector('.policy.row');
-  return row.querySelectorAll('div');
+  return policyRow.querySelectorAll('div');
 }
 
 function getPrecedenceRowValue() {
-  const tables = document.querySelectorAll('policy-table');
-  let precedenceRow = null;
-  tables.forEach(table => {
-    const row = table.shadowRoot.querySelector('policy-precedence-row');
-    if (row) {
-      precedenceRow = row.shadowRoot.querySelector('.value');
-    }
-  });
+  const precedenceRow =
+      document.querySelector('#policy-ui')
+          .querySelector('.policy-table .precedence.row > .value');
   return precedenceRow;
 }
 
 function getRefreshIntervalEl() {
-  return document.querySelector('status-box')
-      .shadowRoot.querySelector('.refresh-interval');
+  return document.querySelector('#status-box-container .refresh-interval');
 }
 
 Object.assign(window, {
diff --git a/components/policy/resources/webui/policy_base.js b/components/policy/resources/webui/policy_base.js
index ba187c7..54a34474 100644
--- a/components/policy/resources/webui/policy_base.js
+++ b/components/policy/resources/webui/policy_base.js
@@ -4,14 +4,13 @@
 
 import './strings.m.js';
 import 'chrome://resources/js/action_link.js';
+
 // <if expr="is_ios">
 import 'chrome://resources/js/ios/web_ui.js';
 // </if>
 
-import './status_box.js';
-import './policy_table.js';
-
 import {addSingletonGetter, addWebUIListener} from 'chrome://resources/js/cr.m.js';
+import {define as crUiDefine} from 'chrome://resources/js/cr/ui.m.js';
 import {FocusOutlineManager} from 'chrome://resources/js/cr/ui/focus_outline_manager.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {$} from 'chrome://resources/js/util.m.js';
@@ -36,6 +35,551 @@
 let PolicyValuesResponse;
 
 /**
+ * @typedef {{
+ *    level: string,
+ *    scope: string,
+ *    source: string,
+ *    value: any,
+ * }}
+ */
+let Conflict;
+
+/**
+ * @typedef {{
+ *    ignored?: boolean,
+ *    name: string,
+ *    level: string,
+ *    link: ?string,
+ *    scope: string,
+ *    source: string,
+ *    error: string,
+ *    warning: string,
+ *    info: string,
+ *    value: any,
+ *    deprecated: ?boolean,
+ *    future: ?boolean,
+ *    allSourcesMerged: ?boolean,
+ *    conflicts: ?Array<!Conflict>,
+ *    superseded: ?Array<!Conflict>,
+ * }}
+ */
+let Policy;
+
+/**
+ * @typedef {{
+ *     id: ?string,
+ *     isExtension?: boolean,
+ *     name: string,
+ *     policies: !Array<!Policy>,
+ *     precedenceOrder: ?Array<string>,
+ * }}
+ */
+let PolicyTableModel;
+
+/**
+ * A box that shows the status of cloud policy for a device, machine or user.
+ * @constructor
+ * @extends {HTMLFieldSetElement}
+ */
+const StatusBox = crUiDefine(function() {
+  const node = $('status-box-template').cloneNode(true);
+  node.removeAttribute('id');
+  return node;
+});
+
+StatusBox.prototype = {
+  // Set up the prototype chain.
+  __proto__: HTMLFieldSetElement.prototype,
+
+  /**
+   * Initialization function for the cr.ui framework.
+   */
+  decorate() {},
+
+  /**
+   * Sets the text of a particular named label element in the status box
+   * and updates the visibility if needed.
+   * @param {string} labelName The name of the label element that is being
+   *     updated.
+   * @param {string} labelValue The new text content for the label.
+   * @param {boolean=} needsToBeShown True if we want to show the label
+   *     False otherwise.
+   */
+  setLabelAndShow_(labelName, labelValue, needsToBeShown = true) {
+    const labelElement = this.querySelector(labelName);
+    labelElement.textContent = labelValue ? ' ' + labelValue : '';
+    if (needsToBeShown) {
+      labelElement.parentElement.hidden = false;
+    }
+  },
+  /**
+   * Populate the box with the given cloud policy status.
+   * @param {string} scope The policy scope, either "device", "machine",
+   *     "user", or "updater".
+   * @param {Object} status Dictionary with information about the status.
+   */
+  initialize(scope, status) {
+    const notSpecifiedString = loadTimeData.getString('notSpecified');
+
+    // Set appropriate box legend based on status key
+    this.querySelector('.legend').textContent =
+        loadTimeData.getString(status.boxLegendKey);
+
+    if (scope === 'device') {
+      // Populate the device naming information.
+      // Populate the asset identifier.
+      this.setLabelAndShow_('.asset-id', status.assetId || notSpecifiedString);
+
+      // Populate the device location.
+      this.setLabelAndShow_('.location', status.location || notSpecifiedString);
+
+      // Populate the directory API ID.
+      this.setLabelAndShow_(
+          '.directory-api-id', status.directoryApiId || notSpecifiedString);
+      this.setLabelAndShow_('.client-id', status.clientId);
+      // For off-hours policy, indicate if it's active or not.
+      if (status.isOffHoursActive != null) {
+        this.setLabelAndShow_(
+            '.is-offhours-active',
+            loadTimeData.getString(
+                status.isOffHoursActive ? 'offHoursActive' :
+                                          'offHoursNotActive'));
+      }
+    } else if (scope === 'machine') {
+      this.setLabelAndShow_('.machine-enrollment-device-id', status.deviceId);
+      this.setLabelAndShow_(
+          '.machine-enrollment-token', status.enrollmentToken);
+      if (status.machine) {
+        this.setLabelAndShow_('.machine-enrollment-name', status.machine);
+      }
+      this.setLabelAndShow_('.machine-enrollment-domain', status.domain);
+    } else if (scope === 'updater') {
+      if (status.version) {
+        this.setLabelAndShow_('.version', status.version);
+      }
+      if (status.domain) {
+        this.setLabelAndShow_('.machine-enrollment-domain', status.domain);
+      }
+    } else {
+      // Populate the topmost item with the username.
+      this.setLabelAndShow_('.username', status.username);
+      // Populate the user gaia id.
+      this.setLabelAndShow_('.gaia-id', status.gaiaId || notSpecifiedString);
+      this.setLabelAndShow_('.client-id', status.clientId);
+      if (status.isAffiliated != null) {
+        this.setLabelAndShow_(
+            '.is-affiliated',
+            loadTimeData.getString(
+                status.isAffiliated ? 'isAffiliatedYes' : 'isAffiliatedNo'));
+      }
+    }
+
+    if (status.enterpriseDomainManager) {
+      this.setLabelAndShow_('.managed-by', status.enterpriseDomainManager);
+    }
+
+    if (status.timeSinceLastFetchAttempt) {
+      this.setLabelAndShow_(
+          '.time-since-last-fetch-attempt', status.timeSinceLastFetchAttempt);
+    }
+
+    if (status.timeSinceLastRefresh) {
+      this.setLabelAndShow_(
+          '.time-since-last-refresh', status.timeSinceLastRefresh);
+    }
+
+    if (scope !== 'updater') {
+      if (status.refreshInterval) {
+        this.setLabelAndShow_('.refresh-interval', status.refreshInterval);
+      }
+      this.setLabelAndShow_('.status', status.status);
+      this.setLabelAndShow_(
+          '.policy-push',
+          loadTimeData.getString(
+              status.policiesPushAvailable ? 'policiesPushOn' :
+                                             'policiesPushOff'));
+    }
+
+    if (status.lastCloudReportSentTimestamp) {
+      this.setLabelAndShow_(
+          '.last-cloud-report-sent-timestamp',
+          status.lastCloudReportSentTimestamp + ' (' +
+              status.timeSinceLastCloudReportSent + ')');
+    }
+  },
+};
+
+/**
+ * A single policy conflict's entry in the policy table.
+ * @constructor
+ * @extends {HTMLDivElement}
+ */
+const PolicyConflict = crUiDefine(function() {
+  const node = $('policy-conflict-template').cloneNode(true);
+  node.removeAttribute('id');
+  return node;
+});
+
+PolicyConflict.prototype = {
+  // Set up the prototype chain.
+  __proto__: HTMLDivElement.prototype,
+
+  decorate() {},
+
+  /**
+   * @param {Conflict} conflict
+   * @param {string} row_label
+   */
+  initialize(conflict, row_label) {
+    this.querySelector('.scope').textContent = loadTimeData.getString(
+        conflict.scope === 'user' ? 'scopeUser' : 'scopeDevice');
+    this.querySelector('.level').textContent = loadTimeData.getString(
+        conflict.level === 'recommended' ? 'levelRecommended' :
+                                           'levelMandatory');
+    this.querySelector('.source').textContent =
+        loadTimeData.getString(conflict.source);
+    this.querySelector('.value').textContent = conflict.value;
+    this.querySelector('.name').textContent = loadTimeData.getString(row_label);
+  }
+};
+
+/**
+ * A single policy's row entry in the policy table.
+ * @constructor
+ * @extends {HTMLDivElement}
+ */
+const PolicyRow = crUiDefine(function() {
+  const node = $('policy-template').cloneNode(true);
+  node.removeAttribute('id');
+  return node;
+});
+
+PolicyRow.prototype = {
+  // Set up the prototype chain.
+  __proto__: HTMLDivElement.prototype,
+
+  /**
+   * Initialization function for the cr.ui framework.
+   */
+  decorate() {
+    const toggle = this.querySelector('.policy.row .toggle');
+    toggle.addEventListener('click', () => this.toggleExpanded_());
+
+    const copy = this.querySelector('.copy-value');
+    copy.addEventListener('click', () => this.copyValue_());
+  },
+
+  /** @param {Policy} policy */
+  initialize(policy) {
+    /** @type {Policy} */
+    this.policy = policy;
+
+    /** @private {boolean} */
+    this.unset_ = policy.value === undefined;
+
+    /** @private {boolean} */
+    this.hasErrors_ = !!policy.error;
+
+    /** @private {boolean} */
+    this.hasWarnings_ = !!policy.warning;
+
+    /** @private {boolean} */
+    this.hasInfos_ = !!policy.info;
+
+    /** @private {boolean} */
+    this.hasConflicts_ = !!policy.conflicts;
+
+    /** @private {boolean} */
+    this.hasSuperseded_ = !!policy.superseded;
+
+    /** @private {boolean} */
+    this.isMergedValue_ = !!policy.allSourcesMerged;
+
+    /** @private {boolean} */
+    this.deprecated_ = !!policy.deprecated;
+
+    /** @private {boolean} */
+    this.future_ = !!policy.future;
+
+    // Populate the name column.
+    const nameDisplay = this.querySelector('.name .link span');
+    nameDisplay.textContent = policy.name;
+    if (policy.link) {
+      const link = this.querySelector('.name .link');
+      link.href = policy.link;
+      link.title = loadTimeData.getStringF('policyLearnMore', policy.name);
+    } else {
+      this.classList.add('no-help-link');
+    }
+
+    // Populate the remaining columns with policy scope, level and value if a
+    // value has been set. Otherwise, leave them blank.
+    if (!this.unset_) {
+      const scopeDisplay = this.querySelector('.scope');
+      scopeDisplay.textContent = loadTimeData.getString(
+          policy.scope === 'user' ? 'scopeUser' : 'scopeDevice');
+
+      const levelDisplay = this.querySelector('.level');
+      levelDisplay.textContent = loadTimeData.getString(
+          policy.level === 'recommended' ? 'levelRecommended' :
+                                           'levelMandatory');
+
+      const sourceDisplay = this.querySelector('.source');
+      sourceDisplay.textContent = loadTimeData.getString(policy.source);
+      // Reduces load on the DOM for long values;
+      const truncatedValue =
+          (policy.value && policy.value.toString().length > 256) ?
+          `${policy.value.toString().substr(0, 256)}\u2026` :
+          policy.value;
+
+      const valueDisplay = this.querySelector('.value');
+      valueDisplay.textContent = truncatedValue;
+
+      const copyLink = this.querySelector('.copy .link');
+      copyLink.title = loadTimeData.getStringF('policyCopyValue', policy.name);
+
+      const valueRowContentDisplay = this.querySelector('.value.row .value');
+      valueRowContentDisplay.textContent = policy.value;
+
+      const errorRowContentDisplay = this.querySelector('.errors.row .value');
+      errorRowContentDisplay.textContent = policy.error;
+      const warningRowContentDisplay =
+          this.querySelector('.warnings.row .value');
+      warningRowContentDisplay.textContent = policy.warning;
+      const infoRowContentDisplay = this.querySelector('.infos.row .value');
+      infoRowContentDisplay.textContent = policy.info;
+
+      const messagesDisplay = this.querySelector('.messages');
+      const errorsNotice =
+          this.hasErrors_ ? loadTimeData.getString('error') : '';
+      const deprecationNotice =
+          this.deprecated_ ? loadTimeData.getString('deprecated') : '';
+      const futureNotice = this.future_ ? loadTimeData.getString('future') : '';
+      const warningsNotice =
+          this.hasWarnings_ ? loadTimeData.getString('warning') : '';
+      const conflictsNotice = this.hasConflicts_ && !this.isMergedValue_ ?
+          loadTimeData.getString('conflict') :
+          '';
+      const ignoredNotice =
+          this.policy.ignored ? loadTimeData.getString('ignored') : '';
+      let notice =
+          [
+            errorsNotice, deprecationNotice, futureNotice, warningsNotice,
+            ignoredNotice, conflictsNotice
+          ].filter(x => !!x)
+              .join(', ') ||
+          loadTimeData.getString('ok');
+      const supersededNotice = this.hasSuperseded_ && !this.isMergedValue_ ?
+          loadTimeData.getString('superseding') :
+          '';
+      if (supersededNotice) {
+        // Include superseded notice regardless of other notices
+        notice += `, ${supersededNotice}`;
+      }
+      messagesDisplay.textContent = notice;
+
+      if (policy.conflicts) {
+        policy.conflicts.forEach(conflict => {
+          const row = new PolicyConflict();
+          row.initialize(conflict, 'conflictValue');
+          this.appendChild(row);
+        });
+      }
+      if (policy.superseded) {
+        policy.superseded.forEach(superseded => {
+          const row = new PolicyConflict();
+          row.initialize(superseded, 'supersededValue');
+          this.appendChild(row);
+        });
+      }
+    } else {
+      const messagesDisplay = this.querySelector('.messages');
+      messagesDisplay.textContent = loadTimeData.getString('unset');
+    }
+  },
+
+  /**
+   * Copies the policy's value to the clipboard.
+   * @private
+   */
+  copyValue_() {
+    const policyValueDisplay = this.querySelector('.value.row .value');
+
+    // Select the text that will be copied.
+    const selection = window.getSelection();
+    const range = window.document.createRange();
+    range.selectNodeContents(policyValueDisplay);
+    selection.removeAllRanges();
+    selection.addRange(range);
+
+    // Copy the policy value to the clipboard.
+    navigator.clipboard.writeText(policyValueDisplay.innerText).catch(error => {
+      console.error('Unable to copy policy value to clipboard:', error);
+    });
+  },
+
+  /**
+   * Toggle the visibility of an additional row containing the complete text.
+   * @private
+   */
+  toggleExpanded_() {
+    const warningRowDisplay = this.querySelector('.warnings.row');
+    const errorRowDisplay = this.querySelector('.errors.row');
+    const infoRowDisplay = this.querySelector('.infos.row');
+    const valueRowDisplay = this.querySelector('.value.row');
+    valueRowDisplay.hidden = !valueRowDisplay.hidden;
+    if (valueRowDisplay.hidden) {
+      this.classList.remove('expanded');
+    } else {
+      this.classList.add('expanded');
+    }
+
+    this.querySelector('.show-more').hidden = !valueRowDisplay.hidden;
+    this.querySelector('.show-less').hidden = valueRowDisplay.hidden;
+    if (this.hasWarnings_) {
+      warningRowDisplay.hidden = !warningRowDisplay.hidden;
+    }
+    if (this.hasErrors_) {
+      errorRowDisplay.hidden = !errorRowDisplay.hidden;
+    }
+    if (this.hasInfos_) {
+      infoRowDisplay.hidden = !infoRowDisplay.hidden;
+    }
+    this.querySelectorAll('.policy-conflict-data')
+        .forEach(row => row.hidden = !row.hidden);
+    this.querySelectorAll('.policy-superseded-data')
+        .forEach(row => row.hidden = !row.hidden);
+  },
+};
+
+/**
+ * A row describing the current policy precedence.
+ * @constructor
+ * @extends {HTMLDivElement}
+ */
+const PolicyPrecedenceRow = crUiDefine(function() {
+  const node = $('policy-precedence-template').cloneNode(true);
+  node.removeAttribute('id');
+  return node;
+});
+
+PolicyPrecedenceRow.prototype = {
+  // Set up the prototype chain.
+  __proto__: HTMLDivElement.prototype,
+
+  decorate() {},
+
+  /**
+   * @param {Array<String>} precedenceOrder Array containing ordered strings
+   *     which represent the order of policy precedence.
+   */
+  initialize(precedenceOrder) {
+    this.querySelector('.precedence.row > .value').textContent =
+        precedenceOrder.join(' > ');
+  }
+};
+
+/**
+ * A table of policies and their values.
+ * @constructor
+ * @extends {HTMLDivElement}
+ */
+const PolicyTable = crUiDefine(function() {
+  const node = $('policy-table-template').cloneNode(true);
+  node.removeAttribute('id');
+  return node;
+});
+
+
+PolicyTable.prototype = {
+  // Set up the prototype chain.
+  __proto__: HTMLDivElement.prototype,
+
+  /**
+   * Initialization function for the cr.ui framework.
+   */
+  decorate() {
+    this.policies_ = {};
+    this.filterPattern_ = '';
+  },
+
+  /** @param {PolicyTableModel} dataModel */
+  update(dataModel) {
+    // Clear policies
+    const mainContent = this.querySelector('.main');
+    const policies = this.querySelectorAll('.policy-data');
+    this.querySelector('.header').textContent = dataModel.name;
+    this.querySelector('.id').textContent = dataModel.id;
+    this.querySelector('.id').hidden = !dataModel.id;
+    policies.forEach(row => mainContent.removeChild(row));
+
+    dataModel.policies
+        .sort((a, b) => {
+          if ((a.value !== undefined && b.value !== undefined) ||
+              a.value === b.value) {
+            if (a.link !== undefined && b.link !== undefined) {
+              // Sorting the policies in ascending alpha order.
+              return a.name > b.name ? 1 : -1;
+            }
+
+            // Sorting so unknown policies are last.
+            return a.link !== undefined ? -1 : 1;
+          }
+
+          // Sorting so unset values are last.
+          return a.value !== undefined ? -1 : 1;
+        })
+        .forEach(policy => {
+          const policyRow = new PolicyRow();
+          policyRow.initialize(policy);
+          mainContent.appendChild(policyRow);
+        });
+    this.filter();
+
+    // Show the current policy precedence order in the Policy Precedence table.
+    if (dataModel.name === 'Policy Precedence') {
+      // Clear previous precedence row.
+      const precedenceRowOld = this.querySelectorAll('.policy-precedence-data');
+      precedenceRowOld.forEach(row => mainContent.removeChild(row));
+
+      const precedenceRow = new PolicyPrecedenceRow();
+      precedenceRow.initialize(dataModel.precedenceOrder);
+      mainContent.appendChild(precedenceRow);
+    }
+  },
+
+  /**
+   * Set the filter pattern. Only policies whose name contains |pattern| are
+   * shown in the policy table. The filter is case insensitive. It can be
+   * disabled by setting |pattern| to an empty string.
+   * @param {string} pattern The filter pattern.
+   */
+  setFilterPattern(pattern) {
+    this.filterPattern_ = pattern.toLowerCase();
+    this.filter();
+  },
+
+  /**
+   * Filter policies. Only policies whose name contains the filter pattern are
+   * shown in the table. Furthermore, policies whose value is not currently
+   * set are only shown if the corresponding checkbox is checked.
+   */
+  filter() {
+    const showUnset = $('show-unset').checked;
+    const policies = this.querySelectorAll('.policy-data');
+    for (let i = 0; i < policies.length; i++) {
+      const policyDisplay = policies[i];
+      policyDisplay.hidden =
+          policyDisplay.policy.value === undefined && !showUnset ||
+          policyDisplay.policy.name.toLowerCase().indexOf(
+              this.filterPattern_) === -1;
+    }
+    this.querySelector('.no-policy').hidden =
+        !!this.querySelector('.policy-data:not([hidden])');
+  },
+};
+
+/**
  * A singleton object that handles communication between browser and WebUI.
  */
 export class Page {
@@ -166,7 +710,7 @@
   createOrUpdatePolicyTable(dataModel) {
     const id = `${dataModel.name}-${dataModel.id}`;
     if (!this.policyTables[id]) {
-      this.policyTables[id] = document.createElement('policy-table');
+      this.policyTables[id] = new PolicyTable();
       this.mainSection.appendChild(this.policyTables[id]);
     }
     this.policyTables[id].update(dataModel);
@@ -189,7 +733,7 @@
 
     // Add a status box for each scope that has a cloud policy status.
     for (const scope in status) {
-      const box = document.createElement('status-box');
+      const box = new StatusBox();
       box.initialize(scope, status[scope]);
       container.appendChild(box);
       // Show the status section.
diff --git a/components/policy/tools/syntax_check_policy_template_json.py b/components/policy/tools/syntax_check_policy_template_json.py
index 2d652153..61ee086 100755
--- a/components/policy/tools/syntax_check_policy_template_json.py
+++ b/components/policy/tools/syntax_check_policy_template_json.py
@@ -997,6 +997,26 @@
                 'documentation string in the messages dictionary.' % feature,
                 'policy', policy.get('name', policy))
 
+      can_be_recommended = self._CheckContains(features,
+                                               'can_be_recommended',
+                                               bool,
+                                               optional=True,
+                                               container_name='features')
+      can_be_mandatory = self._CheckContains(features,
+                                             'can_be_mandatory',
+                                             bool,
+                                             optional=True,
+                                             container_name='features')
+
+      can_be_recommended = False if (
+          can_be_recommended) is None else can_be_recommended
+      can_be_mandatory = True if can_be_mandatory is None else can_be_mandatory
+
+      if not can_be_recommended and not can_be_mandatory:
+        self._Error('Policy can not be mandatory or recommended.', 'policy',
+                    policy.get('name'))
+
+
       # All user policies must have a per_profile feature flag.
       if (not policy.get('device_only', False)
           and not policy.get('deprecated', False)
@@ -1042,12 +1062,10 @@
         if 'default_for_enterprise_users' not in policy:
           self._Error('default_for_enteprise_users should be set when '
                       'default_policy_level is set ')
-        if (default_policy_level == 'recommended'
-            and not features.get('can_be_recommended', False)):
+        if (default_policy_level == 'recommended' and not can_be_recommended):
           self._Error('can_be_recommended should be set to True when '
                       'default_policy_level is set to "recommended"')
-        if (default_policy_level == 'mandatory'
-            and not features.get('can_be_mandatory', True)):
+        if (default_policy_level == 'mandatory' and not can_be_mandatory):
           self._Error('can_be_mandatory should be set to True when '
                       'default_policy_level is set to "recommended"')
 
diff --git a/components/prefs/pref_member_unittest.cc b/components/prefs/pref_member_unittest.cc
index c11ddf5..0b22916 100644
--- a/components/prefs/pref_member_unittest.cc
+++ b/components/prefs/pref_member_unittest.cc
@@ -213,7 +213,7 @@
   string_list.Init(kStringListPref, &prefs);
 
   // Check the defaults
-  EXPECT_EQ(expected_list, *prefs.GetValueList(kStringListPref));
+  EXPECT_EQ(expected_list, prefs.GetValueList(kStringListPref));
   EXPECT_EQ(expected_vector, string_list.GetValue());
   EXPECT_EQ(expected_vector, *string_list);
   EXPECT_TRUE(string_list.IsDefaultValue());
@@ -223,7 +223,7 @@
   expected_vector.push_back("foo");
   string_list.SetValue(expected_vector);
 
-  EXPECT_EQ(expected_list, *prefs.GetValueList(kStringListPref));
+  EXPECT_EQ(expected_list, prefs.GetValueList(kStringListPref));
   EXPECT_EQ(expected_vector, string_list.GetValue());
   EXPECT_EQ(expected_vector, *string_list);
   EXPECT_FALSE(string_list.IsDefaultValue());
@@ -233,7 +233,7 @@
   expected_vector.push_back("bar");
   prefs.SetList(kStringListPref, expected_list.Clone());
 
-  EXPECT_EQ(expected_list, *prefs.GetValueList(kStringListPref));
+  EXPECT_EQ(expected_list, prefs.GetValueList(kStringListPref));
   EXPECT_EQ(expected_vector, string_list.GetValue());
   EXPECT_EQ(expected_vector, *string_list);
   EXPECT_FALSE(string_list.IsDefaultValue());
@@ -243,7 +243,7 @@
   expected_vector.erase(expected_vector.begin());
   prefs.SetList(kStringListPref, expected_list.Clone());
 
-  EXPECT_EQ(expected_list, *prefs.GetValueList(kStringListPref));
+  EXPECT_EQ(expected_list, prefs.GetValueList(kStringListPref));
   EXPECT_EQ(expected_vector, string_list.GetValue());
   EXPECT_EQ(expected_vector, *string_list);
   EXPECT_FALSE(string_list.IsDefaultValue());
diff --git a/components/prefs/pref_service.cc b/components/prefs/pref_service.cc
index 344e68dc..2a0810a9 100644
--- a/components/prefs/pref_service.cc
+++ b/components/prefs/pref_service.cc
@@ -222,72 +222,40 @@
 }
 
 bool PrefService::GetBoolean(const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  const base::Value* value = GetPreferenceValueChecked(path);
-  if (!value || !value->is_bool())
+  const base::Value& value = GetValue(path);
+  if (!value.is_bool())
     return false;
-  return value->GetBool();
+  return value.GetBool();
 }
 
 int PrefService::GetInteger(const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  const base::Value* value = GetPreferenceValueChecked(path);
-  if (!value || !value->is_int())
+  const base::Value& value = GetValue(path);
+  if (!value.is_int())
     return 0;
-  return value->GetInt();
+  return value.GetInt();
 }
 
 double PrefService::GetDouble(const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  const base::Value* value = GetPreferenceValueChecked(path);
-  if (!value || !value->is_double())
+  const base::Value& value = GetValue(path);
+  if (!value.is_double())
     return 0.0;
-  return value->GetDouble();
+  return value.GetDouble();
 }
 
 std::string PrefService::GetString(const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  const base::Value* value = GetPreferenceValueChecked(path);
-  if (!value || !value->is_string())
+  const base::Value& value = GetValue(path);
+  if (!value.is_string())
     return std::string();
-  return value->GetString();
+  return value.GetString();
 }
 
 base::FilePath PrefService::GetFilePath(const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  const base::Value* value = GetPreferenceValueChecked(path);
-  if (!value)
-    return base::FilePath();
-  absl::optional<base::FilePath> result = base::ValueToFilePath(*value);
+  const base::Value& value = GetValue(path);
+  absl::optional<base::FilePath> result = base::ValueToFilePath(value);
   DCHECK(result);
   return *result;
 }
 
-const base::Value::Dict* PrefService::GetValueDict(
-    const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  const base::Value* value = GetDictionary(path);
-  if (!value)
-    return nullptr;
-  return &value->GetDict();
-}
-
-const base::Value::List* PrefService::GetValueList(
-    const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  const base::Value* value = GetList(path);
-  if (!value)
-    return nullptr;
-  return &value->GetList();
-}
-
 bool PrefService::HasPrefPath(const std::string& path) const {
   const Preference* pref = FindPreference(path);
   return pref && !pref->IsDefaultValue();
@@ -380,21 +348,30 @@
 }
 
 const base::Value* PrefService::Get(const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return GetPreferenceValueChecked(path);
+  return &GetValue(path);
 }
 
 const base::Value* PrefService::GetDictionary(const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  const base::Value& value = GetValue(path);
+  DCHECK(value.is_dict());
+  return &value;
+}
 
-  const base::Value* value = GetPreferenceValueChecked(path);
-  if (!value)
-    return nullptr;
-  if (value->type() != base::Value::Type::DICTIONARY) {
-    NOTREACHED();
-    return nullptr;
-  }
-  return value;
+const base::Value& PrefService::GetValue(const std::string& path) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return *GetPreferenceValueChecked(path);
+}
+
+const base::Value::Dict& PrefService::GetValueDict(
+    const std::string& path) const {
+  const base::Value& value = GetValue(path);
+  return value.GetDict();
+}
+
+const base::Value::List& PrefService::GetValueList(
+    const std::string& path) const {
+  const base::Value& value = GetValue(path);
+  return value.GetList();
 }
 
 const base::Value* PrefService::GetUserPrefValue(
@@ -438,16 +415,9 @@
 }
 
 const base::Value* PrefService::GetList(const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  const base::Value* value = GetPreferenceValueChecked(path);
-  if (!value)
-    return nullptr;
-  if (value->type() != base::Value::Type::LIST) {
-    NOTREACHED();
-    return nullptr;
-  }
-  return value;
+  const base::Value& value = GetValue(path);
+  DCHECK(value.is_list());
+  return &value;
 }
 
 void PrefService::AddPrefObserver(const std::string& path, PrefObserver* obs) {
@@ -585,7 +555,7 @@
 }
 
 int64_t PrefService::GetInt64(const std::string& path) const {
-  const base::Value* value = GetPreferenceValueChecked(path);
+  const base::Value& value = GetValue(path);
   absl::optional<int64_t> integer = base::ValueToInt64(value);
   DCHECK(integer);
   return integer.value_or(0);
@@ -596,14 +566,12 @@
 }
 
 uint64_t PrefService::GetUint64(const std::string& path) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  const base::Value* value = GetPreferenceValueChecked(path);
-  if (!value || !value->is_string())
+  const base::Value& value = GetValue(path);
+  if (!value.is_string())
     return 0;
 
   uint64_t result;
-  base::StringToUint64(value->GetString(), &result);
+  base::StringToUint64(value.GetString(), &result);
   return result;
 }
 
@@ -612,7 +580,7 @@
 }
 
 base::Time PrefService::GetTime(const std::string& path) const {
-  const base::Value* value = GetPreferenceValueChecked(path);
+  const base::Value& value = GetValue(path);
   absl::optional<base::Time> time = base::ValueToTime(value);
   DCHECK(time);
   return time.value_or(base::Time());
@@ -623,7 +591,7 @@
 }
 
 base::TimeDelta PrefService::GetTimeDelta(const std::string& path) const {
-  const base::Value* value = GetPreferenceValueChecked(path);
+  const base::Value& value = GetValue(path);
   absl::optional<base::TimeDelta> time_delta = base::ValueToTimeDelta(value);
   DCHECK(time_delta);
   return time_delta.value_or(base::TimeDelta());
diff --git a/components/prefs/pref_service.h b/components/prefs/pref_service.h
index 0c8ca54a..74da1aa 100644
--- a/components/prefs/pref_service.h
+++ b/components/prefs/pref_service.h
@@ -241,18 +241,30 @@
   double GetDouble(const std::string& path) const;
   std::string GetString(const std::string& path) const;
   base::FilePath GetFilePath(const std::string& path) const;
-  const base::Value::Dict* GetValueDict(const std::string& path) const;
-  const base::Value::List* GetValueList(const std::string& path) const;
 
+  // DEPRECATED: Prefer GetValue(), GetValueDict(), and GetValueList().
   // Returns the branch if it exists, or the registered default value otherwise.
   // Note that |path| must point to a registered preference. In that case, these
   // functions will never return NULL.
-  const base::Value* Get(const std::string& path) const;
-  // DEPRECATED: Prefer Get(), GetValueDict(), and GetValueList().
   // TODO(https://crbug.com/1334665): Remove these methods.
+  const base::Value* Get(const std::string& path) const;
   const base::Value* GetDictionary(const std::string& path) const;
   const base::Value* GetList(const std::string& path) const;
 
+  // Returns the branch if it exists, or the registered default value otherwise.
+  // `path` must point to a registered preference (DCHECK).
+  const base::Value& GetValue(const std::string& path) const;
+
+  // Returns the branch if it exists, or the registered default value otherwise.
+  // `path` must point to a registered preference whose value and registered
+  // default are of type `base::Value::Type::DICT (DCHECK).
+  const base::Value::Dict& GetValueDict(const std::string& path) const;
+
+  // Returns the branch if it exists, or the registered default value otherwise.
+  // `path` must point to a registered preference whose value and registered
+  // default are of type `base::Value::Type::LIST (DCHECK).
+  const base::Value::List& GetValueList(const std::string& path) const;
+
   // Removes a user pref and restores the pref to its default value.
   void ClearPref(const std::string& path);
 
diff --git a/components/prefs/scoped_user_pref_update_unittest.cc b/components/prefs/scoped_user_pref_update_unittest.cc
index f344c79..1bcf3aa 100644
--- a/components/prefs/scoped_user_pref_update_unittest.cc
+++ b/components/prefs/scoped_user_pref_update_unittest.cc
@@ -85,11 +85,11 @@
 
   std::string pref_name = "mypref";
   prefs_.registry()->RegisterListPref(pref_name, std::move(defaults));
-  EXPECT_EQ(2u, prefs_.GetValueList(pref_name)->size());
+  EXPECT_EQ(2u, prefs_.GetValueList(pref_name).size());
 
   ListPrefUpdate update(&prefs_, pref_name);
   update->Append("thirdvalue");
-  EXPECT_EQ(3u, prefs_.GetValueList(pref_name)->size());
+  EXPECT_EQ(3u, prefs_.GetValueList(pref_name).size());
 }
 
 TEST_F(ScopedUserPrefUpdateTest, UpdatingDictionaryPrefWithDefaults) {
diff --git a/components/remote_cocoa/app_shim/bridged_content_view.mm b/components/remote_cocoa/app_shim/bridged_content_view.mm
index 1fc2ac0..c9b96a2d3 100644
--- a/components/remote_cocoa/app_shim/bridged_content_view.mm
+++ b/components/remote_cocoa/app_shim/bridged_content_view.mm
@@ -1327,24 +1327,30 @@
 // NSServicesMenuRequestor protocol
 
 - (BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard types:(NSArray*)types {
-  // NB: The NSServicesMenuRequestor protocol has not (as of 10.14) been
+  // NB: The NSServicesMenuRequestor protocol has not (as of macOS 12) been
   // upgraded to request UTIs rather than obsolete PboardType constants. Handle
   // either for when it is upgraded.
-  DCHECK([types containsObject:NSStringPboardType] ||
-         [types containsObject:base::mac::CFToNSCast(kUTTypeUTF8PlainText)]);
+  bool wasAbleToWriteAtLeastOneType = false;
 
-  bool result = NO;
-  std::u16string text;
-  if (_bridge)
-    _bridge->text_input_host()->GetSelectionText(&result, &text);
-  if (!result)
-    return NO;
-  return [pboard writeObjects:@[ base::SysUTF16ToNSString(text) ]];
+  if ([types containsObject:NSStringPboardType] ||
+      [types containsObject:base::mac::CFToNSCast(kUTTypeUTF8PlainText)]) {
+    bool result = false;
+    std::u16string selection_text;
+    if (_bridge)
+      _bridge->text_input_host()->GetSelectionText(&result, &selection_text);
+
+    if (result) {
+      NSString* text = base::SysUTF16ToNSString(selection_text);
+      wasAbleToWriteAtLeastOneType |= [pboard writeObjects:@[ text ]];
+    }
+  }
+
+  return wasAbleToWriteAtLeastOneType;
 }
 
 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard {
-  NSArray* objects = [pboard readObjectsForClasses:@ [[NSString class]]
-      options:0];
+  NSArray* objects = [pboard readObjectsForClasses:@[ [NSString class] ]
+                                           options:nil];
   DCHECK([objects count] == 1);
   [self insertText:[objects lastObject]];
   return YES;
diff --git a/components/services/screen_ai/proto/proto_convertor.cc b/components/services/screen_ai/proto/proto_convertor.cc
index 0e4fc82..740d6b1b 100644
--- a/components/services/screen_ai/proto/proto_convertor.cc
+++ b/components/services/screen_ai/proto/proto_convertor.cc
@@ -48,6 +48,11 @@
                                   const chrome_screen_ai::WordBox& word_2) {
   if (word_1.language() != word_2.language())
     return false;
+
+  // The absence of reliable color information makes the two words have unequal
+  // style, because it could indicate vastly different colors between them.
+  if (word_1.estimate_color_success() != word_2.estimate_color_success())
+    return false;
   if (word_1.estimate_color_success() && word_2.estimate_color_success()) {
     if (word_1.foreground_rgb_value() != word_2.foreground_rgb_value())
       return false;
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc
index 8d7520a..f48e040 100644
--- a/components/signin/core/browser/account_reconcilor.cc
+++ b/components/signin/core/browser/account_reconcilor.cc
@@ -14,7 +14,6 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/containers/contains.h"
-#include "base/feature_list.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
@@ -29,7 +28,6 @@
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_client.h"
 #include "components/signin/public/base/signin_metrics.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
 #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
 #include "components/signin/public/identity_manager/accounts_mutator.h"
@@ -135,10 +133,8 @@
   timeout_ = delegate_->GetReconcileTimeout();
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-  if (base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-    consistency_cookie_manager_ =
-        std::make_unique<signin::ConsistencyCookieManager>(client_, this);
-  }
+  consistency_cookie_manager_ =
+      std::make_unique<signin::ConsistencyCookieManager>(client_, this);
 #endif
 }
 
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc
index 3af0287..b0971ba 100644
--- a/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/scoped_observation.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "base/timer/mock_timer.h"
@@ -54,7 +53,6 @@
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "components/signin/core/browser/mirror_landing_account_reconcilor_delegate.h"
-#include "components/signin/public/base/signin_switches.h"
 #endif
 
 using signin_metrics::AccountReconcilorState;
@@ -139,15 +137,12 @@
     switch (account_consistency) {
       case signin::AccountConsistencyMethod::kMirror:
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-        if (base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-          bool is_main_profile = client->GetInitialPrimaryAccount().has_value();
-          return std::make_unique<
-              signin::MirrorLandingAccountReconcilorDelegate>(identity_manager,
-                                                              is_main_profile);
-        }
-#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+        return std::make_unique<signin::MirrorLandingAccountReconcilorDelegate>(
+            identity_manager, client->GetInitialPrimaryAccount().has_value());
+#else
         return std::make_unique<signin::MirrorAccountReconcilorDelegate>(
             identity_manager);
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
       case signin::AccountConsistencyMethod::kDisabled:
         return std::make_unique<signin::AccountReconcilorDelegate>();
       case signin::AccountConsistencyMethod::kDice:
@@ -1947,7 +1942,7 @@
 
   bool expect_logout =
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-      base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles);
+      true;
 #else
       account_consistency == signin::AccountConsistencyMethod::kDice;
 #endif
@@ -2047,9 +2042,7 @@
       GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-  if (base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-    EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
-  }
+  EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
 #endif
   AccountReconcilor* reconcilor = GetMockReconcilor();
   signin::SetListAccountsResponseTwoAccounts(
@@ -2058,13 +2051,11 @@
   reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
   base::RunLoop().RunUntilIdle();
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-  if (base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)) {
-    ASSERT_TRUE(reconcilor->is_reconcile_started_);
-    SimulateLogOutFromCookieCompleted(reconcilor,
-                                      GoogleServiceAuthError::AuthErrorNone());
-    testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
-    base::RunLoop().RunUntilIdle();
-  }
+  ASSERT_TRUE(reconcilor->is_reconcile_started_);
+  SimulateLogOutFromCookieCompleted(reconcilor,
+                                    GoogleServiceAuthError::AuthErrorNone());
+  testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
+  base::RunLoop().RunUntilIdle();
 #endif
   ASSERT_FALSE(reconcilor->is_reconcile_started_);
 }
diff --git a/components/signin/core/browser/chrome_connected_header_helper.cc b/components/signin/core/browser/chrome_connected_header_helper.cc
index 15fa8016..e4a071d 100644
--- a/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -15,7 +14,6 @@
 #include "build/chromeos_buildflags.h"
 #include "components/google/core/common/google_util.h"
 #include "components/signin/core/browser/cookie_settings_util.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/tribool.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
@@ -248,18 +246,13 @@
       break;
   }
 
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  std::string consistency_enabled_by_default =
-      base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)
-          ? "true"
-          : "false";
-#else
-  std::string consistency_enabled_by_default = "false";
-#endif
-
   parts.push_back(base::StringPrintf("%s=%s",
                                      kConsistencyEnabledByDefaultAttrName,
-                                     consistency_enabled_by_default.c_str()));
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+                                     "true"));
+#else
+                                     "false"));
+#endif
 
   return base::JoinString(parts, is_header_request ? "," : ":");
 }
diff --git a/components/signin/core/browser/consistency_cookie_manager_unittest.cc b/components/signin/core/browser/consistency_cookie_manager_unittest.cc
index ae03f51..9e7813b 100644
--- a/components/signin/core/browser/consistency_cookie_manager_unittest.cc
+++ b/components/signin/core/browser/consistency_cookie_manager_unittest.cc
@@ -6,11 +6,9 @@
 
 #include <memory>
 
-#include "base/test/scoped_feature_list.h"
 #include "components/signin/core/browser/account_reconcilor.h"
 #include "components/signin/core/browser/account_reconcilor_delegate.h"
 #include "components/signin/public/base/signin_metrics.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/base/test_signin_client.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/cookies/canonical_cookie.h"
@@ -127,12 +125,6 @@
   MockCookieManager* cookie_manager() { return cookie_manager_; }
 
  private:
-  // The kLacrosNonSyncingProfiles flags bundles several features: non-syncing
-  // profiles, signed out profiles, and Mirror Landing. The
-  // `ConsistencyCookieManager` is related to MirrorLanding.
-  base::test::ScopedFeatureList feature_list_{
-      switches::kLacrosNonSyncingProfiles};
-
   TestSigninClient signin_client_{/*prefs=*/nullptr};
   MockCookieManager* cookie_manager_ = nullptr;  // Owned by `signin_client_`.
   std::unique_ptr<AccountReconcilor> reconcilor_;
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc
index 0953cdc..fefe396 100644
--- a/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/command_line.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -19,7 +18,6 @@
 #include "components/signin/core/browser/chrome_connected_header_helper.h"
 #include "components/signin/public/base/account_consistency_method.h"
 #include "components/signin/public/base/signin_buildflags.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/tribool.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "google_apis/gaia/gaia_urls.h"
@@ -173,8 +171,6 @@
   sync_preferences::TestingPrefServiceSyncable prefs_;
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-  base::test::ScopedFeatureList scoped_feature_list_{
-      switches::kLacrosNonSyncingProfiles};
   std::unique_ptr<chromeos::ScopedLacrosServiceTestHelper>
       scoped_lacros_test_helper_;
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/components/signin/public/base/signin_switches.cc b/components/signin/public/base/signin_switches.cc
index 2413900..5b36ca6 100644
--- a/components/signin/public/base/signin_switches.cc
+++ b/components/signin/public/base/signin_switches.cc
@@ -59,10 +59,4 @@
                                   base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-// Allows local (not signed-in) profiles on lacros.
-const base::Feature kLacrosNonSyncingProfiles{"LacrosNonSyncingProfiles",
-                                              base::FEATURE_ENABLED_BY_DEFAULT};
-#endif
-
 }  // namespace switches
diff --git a/components/signin/public/base/signin_switches.h b/components/signin/public/base/signin_switches.h
index 37c8689..4ea4647 100644
--- a/components/signin/public/base/signin_switches.h
+++ b/components/signin/public/base/signin_switches.h
@@ -41,10 +41,6 @@
 extern const base::Feature kTangibleSync;
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-extern const base::Feature kLacrosNonSyncingProfiles;
-#endif
-
 }  // namespace switches
 
 #endif  // COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_SWITCHES_H_
diff --git a/components/signin/public/identity_manager/identity_manager.cc b/components/signin/public/identity_manager/identity_manager.cc
index 223b74b..9de8ca3 100644
--- a/components/signin/public/identity_manager/identity_manager.cc
+++ b/components/signin/public/identity_manager/identity_manager.cc
@@ -7,7 +7,6 @@
 #include <string>
 
 #include "base/bind.h"
-#include "base/feature_list.h"
 #include "base/observer_list.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -41,7 +40,6 @@
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "components/account_manager_core/account.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/tribool.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #endif
@@ -174,16 +172,12 @@
     const absl::optional<bool>& initial_account_is_child =
         signin_client_->IsInitialPrimaryAccountChild();
     CHECK(initial_account_is_child.has_value());
-    SetPrimaryAccount(
-        this, account_tracker_service_.get(), signin_client_,
-        initial_account.value(),
-        initial_account_is_child.value() ? signin::Tribool::kTrue
-                                         : signin::Tribool::kFalse,
-        base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)
-            ? ConsentLevel::kSignin
-            : ConsentLevel::kSync
-
-    );
+    SetPrimaryAccount(this, account_tracker_service_.get(), signin_client_,
+                      initial_account.value(),
+                      initial_account_is_child.value()
+                          ? signin::Tribool::kTrue
+                          : signin::Tribool::kFalse,
+                      ConsentLevel::kSignin);
   }
 #endif
 }
diff --git a/components/signin/public/identity_manager/identity_manager_unittest.cc b/components/signin/public/identity_manager/identity_manager_unittest.cc
index a759918..2adf52d1 100644
--- a/components/signin/public/identity_manager/identity_manager_unittest.cc
+++ b/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -2370,14 +2370,12 @@
   RecreateIdentityManager(AccountConsistencyMethod::kDisabled,
                           PrimaryAccountManagerSetup::kNoAuthenticatedAccount);
 
-  // We should have a Primary Account set up automatically.
-  ConsentLevel consent_level =
-      base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)
-          ? ConsentLevel::kSignin
-          : ConsentLevel::kSync;
-  ASSERT_TRUE(identity_manager()->HasPrimaryAccount(consent_level));
-  EXPECT_EQ(kTestGaiaId,
-            identity_manager()->GetPrimaryAccountInfo(consent_level).gaia);
+  // We should have a non-syncing Primary Account set up automatically.
+  ASSERT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+  ASSERT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+  EXPECT_EQ(
+      kTestGaiaId,
+      identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin).gaia);
 }
 
 // TODO(https://crbug.com/1223364): Remove this when all the users are migrated.
@@ -2395,14 +2393,11 @@
   // provided by the SigninClient.
   RecreateIdentityManager(AccountConsistencyMethod::kDisabled,
                           PrimaryAccountManagerSetup::kWithAuthenticatedAccout);
-
-  ConsentLevel consent_level =
-      base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles)
-          ? ConsentLevel::kSignin
-          : ConsentLevel::kSync;
-  ASSERT_TRUE(identity_manager()->HasPrimaryAccount(consent_level));
-  EXPECT_EQ(kTestGaiaId2,
-            identity_manager()->GetPrimaryAccountInfo(consent_level).gaia);
+  ASSERT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+  ASSERT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+  EXPECT_EQ(
+      kTestGaiaId2,
+      identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin).gaia);
 }
 #endif
 
diff --git a/components/strings/components_strings_uk.xtb b/components/strings/components_strings_uk.xtb
index a93dccc..465d9fb 100644
--- a/components/strings/components_strings_uk.xtb
+++ b/components/strings/components_strings_uk.xtb
@@ -1161,7 +1161,7 @@
 <translation id="4152318981910038897">{COUNT,plural, =1{Сторінка 1}one{Сторінка {COUNT}}few{Сторінка {COUNT}}many{Сторінка {COUNT}}other{Сторінка {COUNT}}}</translation>
 <translation id="4154664944169082762">Відбитки</translation>
 <translation id="4159784952369912983">Пурпуровий</translation>
-<translation id="4165986682804962316">Налаштування сайту</translation>
+<translation id="4165986682804962316">Налаштування сайтів</translation>
 <translation id="4171400957073367226">Недійсний підпис для підтвердження</translation>
 <translation id="4171489848299289778"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_OWNER" />, <ph name="RESULT_PRODUCT_SOURCE" /></translation>
 <translation id="4172051516777682613">Завжди показувати</translation>
diff --git a/components/strings/components_strings_zu.xtb b/components/strings/components_strings_zu.xtb
index 48d32b9b..f45291a 100644
--- a/components/strings/components_strings_zu.xtb
+++ b/components/strings/components_strings_zu.xtb
@@ -842,7 +842,7 @@
 <translation id="3249151924975132674">Izimali mboleko zabafundi kanye nezimali zasekolishi</translation>
 <translation id="3249845759089040423">I-Groovy</translation>
 <translation id="3250640885957938546">Ukukhangisa nokumaketha</translation>
-<translation id="3252266817569339921">Isi-French</translation>
+<translation id="3252266817569339921">French</translation>
 <translation id="3256863843508922226">Ukuyeka emsebenzini nepenshini</translation>
 <translation id="3259648571731540213"><ph name="CREATE_GOOGLE_CALENDAR_EVENT_FOCUSED_FRIENDLY_MATCH_TEXT" />, cindezela u-Tab bese u-Enter ukuze udale umcimbi omusha ngokushesha ku-Google Calendar</translation>
 <translation id="3261488570342242926">Funda mayelana namakhadi we-virtual</translation>
@@ -1646,7 +1646,7 @@
 <translation id="541416427766103491">Isitaki esingu-4</translation>
 <translation id="5421136146218899937">Sula idatha yokudlulisa amehlo...</translation>
 <translation id="5426179911063097041">I-<ph name="SITE" /> ifuna ukukuthumelela izaziso</translation>
-<translation id="5428105026674456456">Isi-Spanish</translation>
+<translation id="5428105026674456456">Spanish</translation>
 <translation id="5430298929874300616">Susa ibhukhimakhi</translation>
 <translation id="5439770059721715174">Iphutha lokuqinisekisa i-schema ku-"<ph name="ERROR_PATH" />": <ph name="ERROR" /></translation>
 <translation id="5443468954631487277">I-oda elingemuva libheke phezulu</translation>
@@ -2663,7 +2663,7 @@
 <translation id="8294431847097064396">Umthombo</translation>
 <translation id="8296205692406981542">Izifunda zamaphakhi nezingadi</translation>
 <translation id="8298115750975731693">I-Wi-Fi oyisebenzisayo (<ph name="WIFI_NAME" />) ingakudinga ukuthi uvakashele ku-<ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />.</translation>
-<translation id="8299269255470343364">Isi-Japanese</translation>
+<translation id="8299269255470343364">Japanese</translation>
 <translation id="8303854710873047864">Isigaba se-"<ph name="SECTION" />" esibonisiwe</translation>
 <translation id="830498451218851433">Goqa ngohafu</translation>
 <translation id="8307358339886459768">Isithombe esincane</translation>
@@ -2761,7 +2761,7 @@
 <translation id="8625384913736129811">Londoloza leli khadi kule divayisi</translation>
 <translation id="865032292777205197">izinzwa zokunyakaza</translation>
 <translation id="8663226718884576429">Isifinyezo se-oda, <ph name="TOTAL_LABEL" />, Imininingwane eminingi</translation>
-<translation id="8666678546361132282">I-English</translation>
+<translation id="8666678546361132282">English</translation>
 <translation id="8669306706049782872">Sebenzisa ulwazi olumayelana nezikrini zakho ukuze uvule futhi ubeke amawindi</translation>
 <translation id="867224526087042813">Isiginesha</translation>
 <translation id="8672264262457010862">Amabhizinisi nomkhakha</translation>
diff --git a/components/sync/driver/sync_service_impl.cc b/components/sync/driver/sync_service_impl.cc
index d147589..5e878a4 100644
--- a/components/sync/driver/sync_service_impl.cc
+++ b/components/sync/driver/sync_service_impl.cc
@@ -22,7 +22,6 @@
 #include "build/build_config.h"
 #include "components/invalidation/public/invalidation_service.h"
 #include "components/signin/public/base/signin_metrics.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
@@ -832,9 +831,6 @@
       // On every platform except ash, revoke the Sync consent/Clear primary
       // account after a dashboard clear.
       if (!IsLocalSyncEnabled() &&
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-          base::FeatureList::IsEnabled(switches::kLacrosNonSyncingProfiles) &&
-#endif
           identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync)) {
         signin::PrimaryAccountMutator* account_mutator =
             identity_manager_->GetPrimaryAccountMutator();
diff --git a/components/sync/driver/sync_service_impl_unittest.cc b/components/sync/driver/sync_service_impl_unittest.cc
index 453aa8e..3083dc1 100644
--- a/components/sync/driver/sync_service_impl_unittest.cc
+++ b/components/sync/driver/sync_service_impl_unittest.cc
@@ -24,7 +24,6 @@
 #include "build/chromeos_buildflags.h"
 #include "components/policy/core/common/policy_service_impl.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "components/signin/public/identity_manager/identity_test_utils.h"
@@ -258,10 +257,6 @@
   raw_ptr<SyncClientMock> sync_client_;  // Owned by |service_|.
   // The controllers are owned by |service_|.
   std::map<ModelType, FakeDataTypeController*> controller_map_;
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  base::test::ScopedFeatureList scoped_feature_list{
-      switches::kLacrosNonSyncingProfiles};
-#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 };
 
 class SyncServiceImplTestWithSyncInvalidationsServiceCreated
diff --git a/components/sync/trusted_vault/download_keys_response_handler.cc b/components/sync/trusted_vault/download_keys_response_handler.cc
index ffef434..345f37a 100644
--- a/components/sync/trusted_vault/download_keys_response_handler.cc
+++ b/components/sync/trusted_vault/download_keys_response_handler.cc
@@ -13,6 +13,7 @@
 #include "components/sync/trusted_vault/securebox.h"
 #include "components/sync/trusted_vault/trusted_vault_crypto.h"
 #include "components/sync/trusted_vault/trusted_vault_server_constants.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace syncer {
 
@@ -35,8 +36,9 @@
 }
 
 // Extracts (decrypts |wrapped_key| and converts to ExtractedSharedKey) shared
-// keys from |membership| and sorts them by version.
-std::vector<ExtractedSharedKey> ExtractAndSortSharedKeys(
+// keys from |membership| and sorts them by version. In case of decryption
+// errors it returns nullopt.
+absl::optional<std::vector<ExtractedSharedKey>> ExtractAndSortSharedKeys(
     const sync_pb::SecurityDomainMember::SecurityDomainMembership& membership,
     const SecureBoxPrivateKey& member_private_key) {
   std::map<int, ExtractedSharedKey> epoch_to_extracted_key;
@@ -46,7 +48,7 @@
             member_private_key, ProtoStringToBytes(shared_key.wrapped_key()));
     if (!decrypted_key.has_value()) {
       // Decryption failed.
-      return std::vector<ExtractedSharedKey>();
+      return absl::nullopt;
     }
     epoch_to_extracted_key[shared_key.epoch()].version = shared_key.epoch();
     epoch_to_extracted_key[shared_key.epoch()].trusted_vault_key =
@@ -155,8 +157,7 @@
       break;
     case TrustedVaultRequest::HttpStatus::kNotFound:
       return ProcessedResponse(
-          /*status=*/TrustedVaultDownloadKeysStatus::
-              kMemberNotFoundOrCorrupted);
+          /*status=*/TrustedVaultDownloadKeysStatus::kMemberNotFound);
     case TrustedVaultRequest::HttpStatus::kAccessTokenFetchingFailure:
       return ProcessedResponse(
           /*status=*/TrustedVaultDownloadKeysStatus::
@@ -180,19 +181,24 @@
   if (!membership) {
     // Member is not in sync security domain.
     return ProcessedResponse(
-        /*status=*/TrustedVaultDownloadKeysStatus::kMemberNotFoundOrCorrupted);
+        /*status=*/TrustedVaultDownloadKeysStatus::kMembershipNotFound);
   }
 
-  std::vector<ExtractedSharedKey> extracted_keys =
+  const absl::optional<std::vector<ExtractedSharedKey>> extracted_keys =
       ExtractAndSortSharedKeys(*membership, device_key_pair_->private_key());
-  if (extracted_keys.empty()) {
-    // |current_member| doesn't have any keys, should be treated as not
-    // registered member.
+  if (!extracted_keys.has_value()) {
+    // |current_member| appears corrupt, as its keys could not be decrypted.
     return ProcessedResponse(
-        /*status=*/TrustedVaultDownloadKeysStatus::kMemberNotFoundOrCorrupted);
+        /*status=*/TrustedVaultDownloadKeysStatus::kMembershipCorrupted);
+  }
+  if (extracted_keys->empty()) {
+    // |current_member| doesn't have any keys, should be treated as a corrupt
+    // state.
+    return ProcessedResponse(
+        /*status=*/TrustedVaultDownloadKeysStatus::kMembershipEmpty);
   }
 
-  if (!IsValidKeyChain(extracted_keys, last_trusted_vault_key_and_version_)) {
+  if (!IsValidKeyChain(*extracted_keys, last_trusted_vault_key_and_version_)) {
     // Data corresponding to |current_member| is corrupted or
     // |last_trusted_vault_key_and_version_| is too old.
     return ProcessedResponse(
@@ -201,7 +207,7 @@
   }
 
   std::vector<ExtractedSharedKey> new_keys =
-      GetNewKeys(extracted_keys, last_trusted_vault_key_and_version_.version);
+      GetNewKeys(*extracted_keys, last_trusted_vault_key_and_version_.version);
   if (new_keys.empty()) {
     return ProcessedResponse(
         /*status=*/TrustedVaultDownloadKeysStatus::kNoNewKeys);
diff --git a/components/sync/trusted_vault/download_keys_response_handler_unittest.cc b/components/sync/trusted_vault/download_keys_response_handler_unittest.cc
index 9089cbd6..42df9a72 100644
--- a/components/sync/trusted_vault/download_keys_response_handler_unittest.cc
+++ b/components/sync/trusted_vault/download_keys_response_handler_unittest.cc
@@ -99,7 +99,7 @@
 };
 
 // All HttpStatuses except kSuccess should end up in kOtherError or
-// kMemberNotFoundOrCorrupted reporting.
+// kMemberNotFound reporting.
 TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleHttpErrors) {
   EXPECT_THAT(
       handler()
@@ -107,7 +107,7 @@
               /*http_status=*/TrustedVaultRequest::HttpStatus::kNotFound,
               /*response_body=*/std::string())
           .status,
-      Eq(TrustedVaultDownloadKeysStatus::kMemberNotFoundOrCorrupted));
+      Eq(TrustedVaultDownloadKeysStatus::kMemberNotFound));
   EXPECT_THAT(
       handler()
           .ProcessResponse(
@@ -261,7 +261,7 @@
 }
 
 // The test populates undecryptable/corrupted |wrapped_key| field, handler
-// should return kMemberNotFoundOrCorrupted to allow client to restore Member by
+// should return kMembershipCorrupted to allow client to restore the member by
 // re-registration.
 TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleUndecryptableKey) {
   sync_pb::SecurityDomainMember member;
@@ -281,7 +281,7 @@
                       /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess,
                       /*response_body=*/member.SerializeAsString())
                   .status,
-              Eq(TrustedVaultDownloadKeysStatus::kMemberNotFoundOrCorrupted));
+              Eq(TrustedVaultDownloadKeysStatus::kMembershipCorrupted));
 }
 
 // The test populates invalid |rotation_proof| field for the single key
@@ -362,7 +362,7 @@
                       /*response_body=*/sync_pb::SecurityDomainMember()
                           .SerializeAsString())
                   .status,
-              Eq(TrustedVaultDownloadKeysStatus::kMemberNotFoundOrCorrupted));
+              Eq(TrustedVaultDownloadKeysStatus::kMembershipNotFound));
 }
 
 // Same as above, but there is a different security domain membership.
@@ -379,7 +379,23 @@
                       /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess,
                       /*response_body=*/member.SerializeAsString())
                   .status,
-              Eq(TrustedVaultDownloadKeysStatus::kMemberNotFoundOrCorrupted));
+              Eq(TrustedVaultDownloadKeysStatus::kMembershipNotFound));
+}
+
+TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleEmptyMembership) {
+  sync_pb::SecurityDomainMember member;
+  AddSecurityDomainMembership(kSyncSecurityDomainName,
+                              MakeTestKeyPair()->public_key(),
+                              /*trusted_vault_keys=*/{},
+                              /*trusted_vault_keys_versions=*/{},
+                              /*signing_keys=*/{}, &member);
+
+  EXPECT_THAT(handler()
+                  .ProcessResponse(
+                      /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess,
+                      /*response_body=*/member.SerializeAsString())
+                  .status,
+              Eq(TrustedVaultDownloadKeysStatus::kMembershipEmpty));
 }
 
 // Tests handling presence of other security domain memberships.
diff --git a/components/sync/trusted_vault/standalone_trusted_vault_backend.cc b/components/sync/trusted_vault/standalone_trusted_vault_backend.cc
index d419df1..d95d6e48 100644
--- a/components/sync/trusted_vault/standalone_trusted_vault_backend.cc
+++ b/components/sync/trusted_vault/standalone_trusted_vault_backend.cc
@@ -153,6 +153,35 @@
 StandaloneTrustedVaultBackend::PendingTrustedRecoveryMethod::
     ~PendingTrustedRecoveryMethod() = default;
 
+// static
+StandaloneTrustedVaultBackend::TrustedVaultDownloadKeysStatusForUMA
+StandaloneTrustedVaultBackend::GetDownloadKeysStatusForUMAFromResponse(
+    TrustedVaultDownloadKeysStatus response_status) {
+  switch (response_status) {
+    case TrustedVaultDownloadKeysStatus::kSuccess:
+      return TrustedVaultDownloadKeysStatusForUMA::kSuccess;
+    case TrustedVaultDownloadKeysStatus::kMemberNotFound:
+      return TrustedVaultDownloadKeysStatusForUMA::kMemberNotFound;
+    case TrustedVaultDownloadKeysStatus::kMembershipNotFound:
+      return TrustedVaultDownloadKeysStatusForUMA::kMembershipNotFound;
+    case TrustedVaultDownloadKeysStatus::kMembershipCorrupted:
+      return TrustedVaultDownloadKeysStatusForUMA::kMembershipCorrupted;
+    case TrustedVaultDownloadKeysStatus::kMembershipEmpty:
+      return TrustedVaultDownloadKeysStatusForUMA::kMembershipEmpty;
+    case TrustedVaultDownloadKeysStatus::kNoNewKeys:
+      return TrustedVaultDownloadKeysStatusForUMA::kNoNewKeys;
+    case TrustedVaultDownloadKeysStatus::kKeyProofsVerificationFailed:
+      return TrustedVaultDownloadKeysStatusForUMA::kKeyProofsVerificationFailed;
+    case TrustedVaultDownloadKeysStatus::kAccessTokenFetchingFailure:
+      return TrustedVaultDownloadKeysStatusForUMA::kAccessTokenFetchingFailure;
+    case TrustedVaultDownloadKeysStatus::kOtherError:
+      return TrustedVaultDownloadKeysStatusForUMA::kOtherError;
+  }
+
+  NOTREACHED();
+  return TrustedVaultDownloadKeysStatusForUMA::kOtherError;
+}
+
 StandaloneTrustedVaultBackend::StandaloneTrustedVaultBackend(
     const base::FilePath& file_path,
     std::unique_ptr<Delegate> delegate,
@@ -192,22 +221,42 @@
   const sync_pb::LocalTrustedVaultPerUser* per_user_vault =
       FindUserVault(account_info.gaia);
 
+  if (per_user_vault && HasNonConstantKey(*per_user_vault) &&
+      !per_user_vault->keys_are_stale()) {
+    // There are locally available keys, which weren't marked as stale. Keys
+    // download attempt is not needed.
+    FulfillOngoingFetchKeys(/*status_for_uma=*/absl::nullopt);
+    return;
+  }
+  if (!connection_) {
+    // Feature disabled.
+    FulfillOngoingFetchKeys(/*status_for_uma=*/absl::nullopt);
+    return;
+  }
   // TODO(crbug.com/1094326): currently there is no guarantee that
   // |primary_account_| is set before FetchKeys() call and this may cause
   // redundant sync error in the UI (for key retrieval), especially during the
   // browser startup. Try to find a way to avoid this issue.
-  if (!connection_ || !primary_account_.has_value() ||
-      primary_account_->gaia != account_info.gaia ||
-      !per_user_vault->local_device_registration_info().device_registered() ||
-      AreConnectionRequestsThrottled()) {
-    // Keys download attempt is not possible.
-    FulfillOngoingFetchKeys();
+  if (!primary_account_.has_value() ||
+      primary_account_->gaia != account_info.gaia) {
+    // Keys download attempt is not possible because there is no primary
+    // account.
+    FulfillOngoingFetchKeys(
+        TrustedVaultDownloadKeysStatusForUMA::kNoPrimaryAccount);
     return;
   }
-  if (HasNonConstantKey(*per_user_vault) && !per_user_vault->keys_are_stale()) {
-    // There are locally available keys, which weren't marked as stale. Keys
-    // download attempt is not needed.
-    FulfillOngoingFetchKeys();
+  DCHECK(per_user_vault);
+  if (!per_user_vault->local_device_registration_info().device_registered()) {
+    // Keys download attempt is not possible because the device is not
+    // registered.
+    FulfillOngoingFetchKeys(
+        TrustedVaultDownloadKeysStatusForUMA::kDeviceNotRegistered);
+    return;
+  }
+  if (AreConnectionRequestsThrottled()) {
+    // Keys download attempt is not possible.
+    FulfillOngoingFetchKeys(
+        TrustedVaultDownloadKeysStatusForUMA::kThrottledClientSide);
     return;
   }
 
@@ -228,7 +277,8 @@
     // Corrupted state: device is registered, but |key_pair| can't be imported.
     // TODO(crbug.com/1094326): restore from this state (throw away the key and
     // trigger device registration again).
-    FulfillOngoingFetchKeys();
+    FulfillOngoingFetchKeys(TrustedVaultDownloadKeysStatusForUMA::
+                                kCorruptedLocalDeviceRegistration);
     return;
   }
 
@@ -688,8 +738,6 @@
   DCHECK(ongoing_connection_request_);
   ongoing_connection_request_ = nullptr;
 
-  base::UmaHistogramEnumeration("Sync.TrustedVaultDownloadKeysStatus", status);
-
   sync_pb::LocalTrustedVaultPerUser* per_user_vault =
       FindUserVault(primary_account_->gaia);
   DCHECK(per_user_vault);
@@ -704,7 +752,10 @@
       StoreKeys(primary_account_->gaia, vault_keys, last_vault_key_version);
       break;
     }
-    case TrustedVaultDownloadKeysStatus::kMemberNotFoundOrCorrupted:
+    case TrustedVaultDownloadKeysStatus::kMemberNotFound:
+    case TrustedVaultDownloadKeysStatus::kMembershipNotFound:
+    case TrustedVaultDownloadKeysStatus::kMembershipCorrupted:
+    case TrustedVaultDownloadKeysStatus::kMembershipEmpty:
     case TrustedVaultDownloadKeysStatus::kNoNewKeys:
     case TrustedVaultDownloadKeysStatus::kKeyProofsVerificationFailed: {
       // Unable to download new keys due to known protocol errors. The only way
@@ -724,8 +775,9 @@
       RecordFailedConnectionRequestForThrottling();
       break;
   }
-  // Regardless of the |status| ongoing fetch keys request should be fulfilled.
-  FulfillOngoingFetchKeys();
+
+  // In all cases the ongoing fetch keys request should be fulfilled.
+  FulfillOngoingFetchKeys(GetDownloadKeysStatusForUMAFromResponse(status));
 }
 
 void StandaloneTrustedVaultBackend::OnTrustedRecoveryMethodAdded(
@@ -740,15 +792,21 @@
 
 void StandaloneTrustedVaultBackend::AbandonConnectionRequest() {
   ongoing_connection_request_ = nullptr;
-  FulfillOngoingFetchKeys();
+  FulfillOngoingFetchKeys(TrustedVaultDownloadKeysStatusForUMA::kAborted);
 }
 
-void StandaloneTrustedVaultBackend::FulfillOngoingFetchKeys() {
+void StandaloneTrustedVaultBackend::FulfillOngoingFetchKeys(
+    absl::optional<TrustedVaultDownloadKeysStatusForUMA> status_for_uma) {
   if (!ongoing_fetch_keys_gaia_id_.has_value()) {
     return;
   }
   DCHECK(!ongoing_fetch_keys_callback_.is_null());
 
+  if (status_for_uma.has_value()) {
+    base::UmaHistogramEnumeration("Sync.TrustedVaultDownloadKeysStatus",
+                                  *status_for_uma);
+  }
+
   const sync_pb::LocalTrustedVaultPerUser* per_user_vault =
       FindUserVault(*ongoing_fetch_keys_gaia_id_);
   std::vector<std::vector<uint8_t>> vault_keys;
diff --git a/components/sync/trusted_vault/standalone_trusted_vault_backend.h b/components/sync/trusted_vault/standalone_trusted_vault_backend.h
index f32c423..54d888d1 100644
--- a/components/sync/trusted_vault/standalone_trusted_vault_backend.h
+++ b/components/sync/trusted_vault/standalone_trusted_vault_backend.h
@@ -121,9 +121,35 @@
 
   void SetClockForTesting(base::Clock* clock);
 
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused. Exposed publicly for testing.
+  enum class TrustedVaultDownloadKeysStatusForUMA {
+    kSuccess = 0,
+    // Deprecated in favor of the more fine-grained buckets.
+    kDeprecatedMembershipNotFoundOrCorrupted = 1,
+    kNoNewKeys = 2,
+    kKeyProofsVerificationFailed = 3,
+    kAccessTokenFetchingFailure = 4,
+    kOtherError = 5,
+    kMemberNotFound = 6,
+    kMembershipNotFound = 7,
+    kMembershipCorrupted = 8,
+    kMembershipEmpty = 9,
+    kNoPrimaryAccount = 10,
+    kDeviceNotRegistered = 11,
+    kThrottledClientSide = 12,
+    kCorruptedLocalDeviceRegistration = 13,
+    kAborted = 14,
+    kMaxValue = kAborted
+  };
+
  private:
   friend class base::RefCountedThreadSafe<StandaloneTrustedVaultBackend>;
 
+  static TrustedVaultDownloadKeysStatusForUMA
+  GetDownloadKeysStatusForUMAFromResponse(
+      TrustedVaultDownloadKeysStatus response_status);
+
   ~StandaloneTrustedVaultBackend();
 
   // Finds the per-user vault in |data_| for |gaia_id|. Returns null if not
@@ -155,7 +181,8 @@
 
   void AbandonConnectionRequest();
 
-  void FulfillOngoingFetchKeys();
+  void FulfillOngoingFetchKeys(
+      absl::optional<TrustedVaultDownloadKeysStatusForUMA> status_for_uma);
 
   // Returns true if the last failed request time imply that upcoming requests
   // should be throttled now (certain amount of time should pass since the last
diff --git a/components/sync/trusted_vault/standalone_trusted_vault_backend_unittest.cc b/components/sync/trusted_vault/standalone_trusted_vault_backend_unittest.cc
index 87ceb13..e07050f 100644
--- a/components/sync/trusted_vault/standalone_trusted_vault_backend_unittest.cc
+++ b/components/sync/trusted_vault/standalone_trusted_vault_backend_unittest.cc
@@ -963,7 +963,9 @@
 
   histogram_tester.ExpectUniqueSample(
       "Sync.TrustedVaultDownloadKeysStatus",
-      /*sample=*/TrustedVaultDownloadKeysStatus::kSuccess,
+      /*sample=*/
+      StandaloneTrustedVaultBackend::TrustedVaultDownloadKeysStatusForUMA::
+          kSuccess,
       /*expected_bucket_count=*/1);
 }
 
@@ -1007,7 +1009,9 @@
            /*last_key_version=*/0);
   histogram_tester.ExpectUniqueSample(
       "Sync.TrustedVaultDownloadKeysStatus",
-      /*sample=*/TrustedVaultDownloadKeysStatus::kOtherError,
+      /*sample=*/
+      StandaloneTrustedVaultBackend::TrustedVaultDownloadKeysStatusForUMA::
+          kOtherError,
       /*expected_bucket_count=*/1);
 
   download_keys_callback = TrustedVaultConnection::DownloadNewKeysCallback();
diff --git a/components/sync/trusted_vault/trusted_vault_connection.h b/components/sync/trusted_vault/trusted_vault_connection.h
index 0dac86d8..03689f2c 100644
--- a/components/sync/trusted_vault/trusted_vault_connection.h
+++ b/components/sync/trusted_vault/trusted_vault_connection.h
@@ -32,24 +32,27 @@
   kOtherError
 };
 
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
 enum class TrustedVaultDownloadKeysStatus {
-  kSuccess = 0,
-  // Member corresponding to the authentication factor doesn't exist, not
-  // registered in the security domain or corrupted.
-  kMemberNotFoundOrCorrupted = 1,
+  kSuccess,
+  // Member corresponding to the authentication factor doesn't exist.
+  kMemberNotFound,
+  // Member corresponding to the authentication factor not registered in the
+  // security domain.
+  kMembershipNotFound,
+  // Membership exists but is corrupted.
+  kMembershipCorrupted,
+  // Membership exists but is empty.
+  kMembershipEmpty,
   // Keys were successfully downloaded and verified, but no new keys exist.
-  kNoNewKeys = 2,
+  kNoNewKeys,
   // At least one of the key proofs isn't valid or unable to verify them using
   // latest local trusted vault key (e.g. it's too old).
-  kKeyProofsVerificationFailed = 3,
+  kKeyProofsVerificationFailed,
   // Used when request isn't sent due to access token fetching failure.
-  kAccessTokenFetchingFailure = 4,
+  kAccessTokenFetchingFailure,
   // Used for all network, http and protocol errors, when no statuses above
   // fits.
-  kOtherError = 5,
-  kMaxValue = kOtherError
+  kOtherError,
 };
 
 enum class TrustedVaultRecoverabilityStatus {
diff --git a/components/test/data/history/history.56.sql b/components/test/data/history/history.56.sql
new file mode 100644
index 0000000..0fa69b7
--- /dev/null
+++ b/components/test/data/history/history.56.sql
@@ -0,0 +1,35 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO meta VALUES('mmap_status','-1');
+INSERT INTO meta VALUES('version','55');
+INSERT INTO meta VALUES('last_compatible_version','16');
+CREATE TABLE urls(id INTEGER PRIMARY KEY AUTOINCREMENT,url LONGVARCHAR,title LONGVARCHAR,visit_count INTEGER DEFAULT 0 NOT NULL,typed_count INTEGER DEFAULT 0 NOT NULL,last_visit_time INTEGER NOT NULL,hidden INTEGER DEFAULT 0 NOT NULL);
+CREATE TABLE visits(id INTEGER PRIMARY KEY AUTOINCREMENT,url INTEGER NOT NULL,visit_time INTEGER NOT NULL,from_visit INTEGER,transition INTEGER DEFAULT 0 NOT NULL,segment_id INTEGER,visit_duration INTEGER DEFAULT 0 NOT NULL,incremented_omnibox_typed_score BOOLEAN DEFAULT FALSE NOT NULL,opener_visit INTEGER,originator_cache_guid TEXT,originator_visit_id INTEGER,originator_from_visit INTEGER,originator_opener_visit INTEGER);
+CREATE TABLE visit_source(id INTEGER PRIMARY KEY,source INTEGER NOT NULL);
+CREATE TABLE keyword_search_terms (keyword_id INTEGER NOT NULL,url_id INTEGER NOT NULL,term LONGVARCHAR NOT NULL,normalized_term LONGVARCHAR NOT NULL);
+CREATE TABLE downloads (id INTEGER PRIMARY KEY,guid VARCHAR NOT NULL,current_path LONGVARCHAR NOT NULL,target_path LONGVARCHAR NOT NULL,start_time INTEGER NOT NULL,received_bytes INTEGER NOT NULL,total_bytes INTEGER NOT NULL,state INTEGER NOT NULL,danger_type INTEGER NOT NULL,interrupt_reason INTEGER NOT NULL,hash BLOB NOT NULL,end_time INTEGER NOT NULL,opened INTEGER NOT NULL,last_access_time INTEGER NOT NULL,transient INTEGER NOT NULL,referrer VARCHAR NOT NULL,site_url VARCHAR NOT NULL,embedder_download_data VARCHAR NOT NULL,tab_url VARCHAR NOT NULL,tab_referrer_url VARCHAR NOT NULL,http_method VARCHAR NOT NULL,by_ext_id VARCHAR NOT NULL,by_ext_name VARCHAR NOT NULL,etag VARCHAR NOT NULL,last_modified VARCHAR NOT NULL,mime_type VARCHAR(255) NOT NULL,original_mime_type VARCHAR(255) NOT NULL);
+CREATE TABLE downloads_url_chains (id INTEGER NOT NULL,chain_index INTEGER NOT NULL,url LONGVARCHAR NOT NULL, PRIMARY KEY (id, chain_index) );
+CREATE TABLE downloads_slices (download_id INTEGER NOT NULL,offset INTEGER NOT NULL,received_bytes INTEGER NOT NULL,finished INTEGER NOT NULL DEFAULT 0,PRIMARY KEY (download_id, offset) );
+CREATE TABLE downloads_reroute_info (download_id INTEGER NOT NULL,reroute_info_serialized  VARCHAR NOT NULL,PRIMARY KEY (download_id) );
+CREATE TABLE segments (id INTEGER PRIMARY KEY,name VARCHAR,url_id INTEGER NON NULL);
+CREATE TABLE segment_usage (id INTEGER PRIMARY KEY,segment_id INTEGER NOT NULL,time_slot INTEGER NOT NULL,visit_count INTEGER DEFAULT 0 NOT NULL);
+CREATE TABLE typed_url_sync_metadata (storage_key INTEGER PRIMARY KEY NOT NULL,value BLOB);
+CREATE TABLE content_annotations(visit_id INTEGER PRIMARY KEY,visibility_score NUMERIC,floc_protected_score NUMERIC,categories VARCHAR,page_topics_model_version INTEGER,annotation_flags INTEGER NOT NULL,entities VARCHAR,related_searches VARCHAR,search_normalized_url VARCHAR,search_terms LONGVARCHAR,alternative_title VARCHAR);
+CREATE TABLE context_annotations(visit_id INTEGER PRIMARY KEY,context_annotation_flags INTEGER NOT NULL,duration_since_last_visit INTEGER,page_end_reason INTEGER,total_foreground_duration INTEGER);
+CREATE TABLE clusters(cluster_id INTEGER PRIMARY KEY,score NUMERIC NOT NULL);
+CREATE TABLE clusters_and_visits(cluster_id INTEGER NOT NULL,visit_id INTEGER NOT NULL,score NUMERIC NOT NULL,PRIMARY KEY(cluster_id,visit_id))WITHOUT ROWID;
+DELETE FROM sqlite_sequence;
+CREATE INDEX visits_url_index ON visits (url);
+CREATE INDEX visits_from_index ON visits (from_visit);
+CREATE INDEX visits_time_index ON visits (visit_time);
+CREATE INDEX keyword_search_terms_index1 ON keyword_search_terms (keyword_id, normalized_term);
+CREATE INDEX keyword_search_terms_index2 ON keyword_search_terms (url_id);
+CREATE INDEX keyword_search_terms_index3 ON keyword_search_terms (term);
+CREATE INDEX segments_name ON segments(name);
+CREATE INDEX segments_url_id ON segments(url_id);
+CREATE INDEX segment_usage_time_slot_segment_id ON segment_usage(time_slot, segment_id);
+CREATE INDEX segments_usage_seg_id ON segment_usage(segment_id);
+CREATE INDEX clusters_for_visit ON clusters_and_visits(visit_id);
+CREATE INDEX urls_url_index ON urls (url);
+COMMIT;
diff --git a/components/test/data/omnibox/in_memory_url_index_test.sql b/components/test/data/omnibox/in_memory_url_index_test.sql
index 015f6df..f2368a8 100644
--- a/components/test/data/omnibox/in_memory_url_index_test.sql
+++ b/components/test/data/omnibox/in_memory_url_index_test.sql
@@ -46,7 +46,9 @@
 --                     incremented_omnibox_typed_score BOOLEAN DEFAULT FALSE NOT NULL,
 --                     opener_visit INTEGER,
 --                     originator_cache_guid TEXT,
---                     originator_visit_id INTEGER)
+--                     originator_visit_id INTEGER,
+--                     originator_from_visit INTEGER,
+--                     originator_opener_visit INTEGER)
 INSERT INTO "urls" VALUES(1,'http://www.reuters.com/article/idUSN0839880620100708','UPDATE 1-US 30-yr mortgage rate drops to new record low | Reuters',3,1,2,0);  -- Qualifies
 INSERT INTO "urls" VALUES(2,'http://www.golfweek.com/news/2010/jul/08/goydos-opens-john-deere-classic-59/','Goydos opens John Deere Classic with 59',3,1,4,0);  -- Qualifies
 INSERT INTO "urls" VALUES(3,'http://www.businessandmedia.org/articles/2010/20100708120415.aspx','LeBronomics: Could High Taxes Influence James'' Team Decision?',4,1,2,0);  -- Qualifies
@@ -87,25 +89,25 @@
 -- This file creates some visits, enough to test (in InMemoryURLIndexTest)
 -- the visits functionality, certainly not as many visits as are implied
 -- by the visit counts associated with the URLs above.
-INSERT INTO "visits" VALUES(1, 1, 2, 4, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(2, 1, 5, 0, 1, 0, 1, TRUE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(3, 1, 12, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(4, 32, 1, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(5, 32, 2, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(6, 32, 3, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(7, 32, 4, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(8, 32, 5, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(9, 32, 6, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(10, 32, 7, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(11, 32, 8, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(12, 32, 9, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(13, 32, 10, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(14, 32, 11, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(15, 32, 12, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(16, 32, 13, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(17, 32, 14, 0, 0, 0, 1, FALSE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(18, 32, 15, 0, 1, 0, 1, TRUE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(19, 35, 0, 0, 1, 0, 1, TRUE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(20, 35, 7, 0, 1, 0, 1, TRUE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(21, 36, 1, 0, 1, 0, 1, TRUE, 0, NULL, NULL);
-INSERT INTO "visits" VALUES(22, 36, 2, 0, 1, 0, 1, TRUE, 0, NULL, NULL);
+INSERT INTO "visits" VALUES(1, 1, 2, 4, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(2, 1, 5, 0, 1, 0, 1, TRUE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(3, 1, 12, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(4, 32, 1, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(5, 32, 2, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(6, 32, 3, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(7, 32, 4, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(8, 32, 5, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(9, 32, 6, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(10, 32, 7, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(11, 32, 8, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(12, 32, 9, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(13, 32, 10, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(14, 32, 11, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(15, 32, 12, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(16, 32, 13, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(17, 32, 14, 0, 0, 0, 1, FALSE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(18, 32, 15, 0, 1, 0, 1, TRUE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(19, 35, 0, 0, 1, 0, 1, TRUE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(20, 35, 7, 0, 1, 0, 1, TRUE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(21, 36, 1, 0, 1, 0, 1, TRUE, 0, NULL, NULL, NULL, NULL);
+INSERT INTO "visits" VALUES(22, 36, 2, 0, 1, 0, 1, TRUE, 0, NULL, NULL, NULL, NULL);
diff --git a/components/user_notes/browser/frame_user_note_changes.cc b/components/user_notes/browser/frame_user_note_changes.cc
index dbe4bd8..72b52b3 100644
--- a/components/user_notes/browser/frame_user_note_changes.cc
+++ b/components/user_notes/browser/frame_user_note_changes.cc
@@ -18,7 +18,8 @@
     const ChangeList& notes_added,
     const ChangeList& notes_modified,
     const ChangeList& notes_removed)
-    : service_(service),
+    : id_(base::UnguessableToken::Create()),
+      service_(service),
       rfh_(rfh),
       notes_added_(notes_added),
       notes_modified_(notes_modified),
@@ -34,7 +35,8 @@
     ChangeList&& notes_added,
     ChangeList&& notes_modified,
     ChangeList&& notes_removed)
-    : service_(service),
+    : id_(base::UnguessableToken::Create()),
+      service_(service),
       rfh_(rfh),
       notes_added_(std::move(notes_added)),
       notes_modified_(std::move(notes_modified)),
diff --git a/components/user_notes/browser/frame_user_note_changes.h b/components/user_notes/browser/frame_user_note_changes.h
index 053570b..113e6a13 100644
--- a/components/user_notes/browser/frame_user_note_changes.h
+++ b/components/user_notes/browser/frame_user_note_changes.h
@@ -42,11 +42,16 @@
   FrameUserNoteChanges(FrameUserNoteChanges&& other);
   virtual ~FrameUserNoteChanges();
 
+  const base::UnguessableToken& id() const { return id_; }
+  const ChangeList& notes_added() const { return notes_added_; }
+  const ChangeList& notes_modified() const { return notes_modified_; }
+  const content::RenderFrameHost* render_frame_host() const { return rfh_; }
+
   // Kicks off the asynchronous logic to add and remove highlights in the frame
   // as necessary. Invokes the provided callback after the changes have fully
   // propagated to the note manager and the new notes have had their highlights
-  // created in the web page.
-  void Apply(base::OnceClosure callback);
+  // created in the web page. Marked virtual for tests to override.
+  virtual void Apply(base::OnceClosure callback);
 
  protected:
   // Called by `Apply()` to construct a new note instance pointing to the
@@ -58,6 +63,9 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(UserNoteUtilsTest, CalculateNoteChanges);
 
+  // An internal ID for this change, so it can be stored and retrieved later.
+  base::UnguessableToken id_;
+
   base::SafeRef<UserNoteService> service_;
   raw_ptr<content::RenderFrameHost> rfh_;
   ChangeList notes_added_;
diff --git a/components/user_notes/browser/user_note_base_test.cc b/components/user_notes/browser/user_note_base_test.cc
index 5a83fda9..f06d17ea 100644
--- a/components/user_notes/browser/user_note_base_test.cc
+++ b/components/user_notes/browser/user_note_base_test.cc
@@ -5,6 +5,7 @@
 #include "components/user_notes/browser/user_note_base_test.h"
 
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "components/user_notes/model/user_note_model_test_utils.h"
@@ -30,7 +31,12 @@
 
 void UserNoteBaseTest::SetUp() {
   content::RenderViewHostTestHarness::SetUp();
-  note_service_ = std::make_unique<UserNoteService>(/*delegate=*/nullptr);
+  CreateService();
+}
+
+void UserNoteBaseTest::CreateService() {
+  note_service_ = std::make_unique<UserNoteService>(/*delegate=*/nullptr,
+                                                    /*storage=*/nullptr);
 }
 
 void UserNoteBaseTest::TearDown() {
diff --git a/components/user_notes/browser/user_note_base_test.h b/components/user_notes/browser/user_note_base_test.h
index 9c18b56..0b92f95 100644
--- a/components/user_notes/browser/user_note_base_test.h
+++ b/components/user_notes/browser/user_note_base_test.h
@@ -30,6 +30,10 @@
 
   void TearDown() override;
 
+  // Called by SetUp. Creates a basic service with a null delegate and storage.
+  // Can be overridden to create a service with a delegate and / or storage.
+  virtual void CreateService();
+
   void AddNewNotesToService(size_t count);
 
   void AddPartialNotesToService(size_t count);
diff --git a/components/user_notes/browser/user_note_service.cc b/components/user_notes/browser/user_note_service.cc
index f1d8d7e..b9dd67db 100644
--- a/components/user_notes/browser/user_note_service.cc
+++ b/components/user_notes/browser/user_note_service.cc
@@ -4,8 +4,12 @@
 
 #include "components/user_notes/browser/user_note_service.h"
 
+#include "base/bind.h"
 #include "base/notreached.h"
+#include "components/user_notes/browser/frame_user_note_changes.h"
 #include "components/user_notes/browser/user_note_manager.h"
+#include "components/user_notes/browser/user_note_utils.h"
+#include "components/user_notes/interfaces/user_note_metadata_snapshot.h"
 #include "components/user_notes/interfaces/user_notes_ui.h"
 #include "components/user_notes/user_notes_features.h"
 #include "content/public/browser/render_frame_host.h"
@@ -14,8 +18,11 @@
 namespace user_notes {
 
 UserNoteService::UserNoteService(
-    std::unique_ptr<UserNoteServiceDelegate> delegate)
-    : delegate_(std::move(delegate)) {}
+    std::unique_ptr<UserNoteServiceDelegate> delegate,
+    std::unique_ptr<UserNoteStorage> storage)
+    : delegate_(std::move(delegate)), storage_(std::move(storage)) {
+  // TODO(gujen): Observe the storage.
+}
 
 UserNoteService::~UserNoteService() = default;
 
@@ -149,6 +156,7 @@
   // `OnNoteCreationCancelled`, in which the partial note will be finalized or
   // deleted, respectively.
   UserNotesUI* ui = delegate_->GetUICoordinatorForFrame(frame);
+  DCHECK(ui);
   ui->StartNoteCreation(instance_raw);
 }
 
@@ -182,9 +190,6 @@
       << "Attempted to complete the creation of a note that doesn't exist";
   // TODO(gujen): Call
   // UserNoteStorage::UpdateNote(entry.model, content, /*is_creation=*/true).
-
-  // TODO(gujen): Make sure to transfer the model from the creation map to the
-  // model map in the OnNotesChanged() event sent by the storage layer.
 }
 
 void UserNoteService::OnNoteCreationCancelled(
@@ -210,6 +215,115 @@
   NOTIMPLEMENTED();
 }
 
+void UserNoteService::OnNotesChanged() {
+  std::vector<content::RenderFrameHost*> all_frames =
+      delegate_->GetAllFramesForUserNotes();
+  std::vector<GURL> urls;
+
+  for (content::RenderFrameHost* frame : all_frames) {
+    urls.emplace_back(frame->GetLastCommittedURL());
+  }
+
+  storage_->GetNoteMetadataForUrls(
+      urls, base::BindOnce(&UserNoteService::OnNoteMetadataFetched,
+                           weak_ptr_factory_.GetWeakPtr(), all_frames));
+}
+
+void UserNoteService::OnNoteMetadataFetched(
+    const std::vector<content::RenderFrameHost*>& all_frames,
+    UserNoteMetadataSnapshot metadata_snapshot) {
+  std::vector<std::unique_ptr<FrameUserNoteChanges>> note_changes =
+      CalculateNoteChanges(*this, all_frames, metadata_snapshot);
+
+  // All added and modified notes must be fetched from storage to eventually be
+  // put in the model map. For removed notes there is no need to update the
+  // model map at this point; it will be done later when applying the changes.
+  std::vector<base::UnguessableToken> notes_to_fetch;
+  std::unordered_set<base::UnguessableToken, base::UnguessableTokenHash>
+      new_notes;
+
+  for (const std::unique_ptr<FrameUserNoteChanges>& diff : note_changes) {
+    for (const base::UnguessableToken& note_id : diff->notes_added()) {
+      notes_to_fetch.emplace_back(note_id);
+      new_notes.emplace(note_id);
+    }
+    for (const base::UnguessableToken& note_id : diff->notes_modified()) {
+      notes_to_fetch.emplace_back(note_id);
+    }
+  }
+
+  storage_->GetNotesById(
+      notes_to_fetch, base::BindOnce(&UserNoteService::OnNoteModelsFetched,
+                                     weak_ptr_factory_.GetWeakPtr(), new_notes,
+                                     std::move(note_changes)));
+}
+
+void UserNoteService::OnNoteModelsFetched(
+    const IdSet& new_notes,
+    std::vector<std::unique_ptr<FrameUserNoteChanges>> note_changes,
+    std::vector<std::unique_ptr<UserNote>> notes) {
+  // Update the model map with the new models.
+  for (std::unique_ptr<UserNote>& note : notes) {
+    base::UnguessableToken id = note->id();
+    const auto& new_note_it = new_notes.find(id);
+    const auto& creation_entry_it = creation_map_.find(id);
+    const auto& model_entry_it = model_map_.find(id);
+
+    if (new_note_it == new_notes.end()) {
+      // This note was modified; simply update the existing model in the model
+      // map.
+      DCHECK(creation_entry_it == creation_map_.end());
+      DCHECK(model_entry_it != model_map_.end());
+      model_entry_it->second.model->Update(std::move(note));
+    } else {
+      DCHECK(model_entry_it == model_map_.end());
+
+      if (creation_entry_it == creation_map_.end()) {
+        // This is a new note that wasn't authored locally. Simply add the model
+        // to the model map.
+        UserNoteService::ModelMapEntry entry(std::move(note));
+        model_map_.emplace(id, std::move(entry));
+      } else {
+        // This is a new note that was authored locally, which means it has a
+        // partial model in the creation map. Update it with the new model from
+        // storage, then move it from the creation map to the model map. The new
+        // model from storage can't be used directly because the note instance
+        // for the page highlight has a reference to the partial model, and that
+        // connection must be maintained.
+        creation_entry_it->second.model->Update(std::move(note));
+        model_map_.emplace(id, std::move(creation_entry_it->second));
+        creation_map_.erase(creation_entry_it);
+      }
+    }
+  }
+
+  // Now that the creation and model maps have been updated, apply all the diffs
+  // to propagate the changes to the webpages and UI.
+  for (std::unique_ptr<FrameUserNoteChanges>& diff : note_changes) {
+    diff->Apply(base::BindOnce(&UserNoteService::OnFrameChangesApplied,
+                               weak_ptr_factory_.GetWeakPtr(), diff->id()));
+    note_changes_in_progress_.emplace(diff->id(), std::move(diff));
+  }
+}
+
+void UserNoteService::OnFrameChangesApplied(base::UnguessableToken change_id) {
+  const auto& changes_it = note_changes_in_progress_.find(change_id);
+  DCHECK(changes_it != note_changes_in_progress_.end());
+
+  // If this set of changes was for a page that's in an active tab, notify the
+  // UI to reload the notes it's displaying.
+  const std::unique_ptr<FrameUserNoteChanges>& frame_changes =
+      changes_it->second;
+  if (delegate_->IsFrameInActiveTab(frame_changes->render_frame_host())) {
+    UserNotesUI* ui =
+        delegate_->GetUICoordinatorForFrame(frame_changes->render_frame_host());
+    DCHECK(ui);
+    ui->Invalidate();
+  }
+
+  note_changes_in_progress_.erase(changes_it);
+}
+
 UserNoteService::ModelMapEntry::ModelMapEntry(std::unique_ptr<UserNote> model)
     : model(std::move(model)) {}
 
diff --git a/components/user_notes/browser/user_note_service.h b/components/user_notes/browser/user_note_service.h
index ef30ee77..8fa56a66 100644
--- a/components/user_notes/browser/user_note_service.h
+++ b/components/user_notes/browser/user_note_service.h
@@ -11,12 +11,14 @@
 #include <string>
 #include <unordered_map>
 #include <unordered_set>
+#include <vector>
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/safe_ref.h"
 #include "base/memory/weak_ptr.h"
 #include "base/unguessable_token.h"
 #include "components/user_notes/interfaces/user_note_service_delegate.h"
+#include "components/user_notes/interfaces/user_note_storage.h"
 #include "components/user_notes/interfaces/user_notes_ui_delegate.h"
 #include "components/user_notes/model/user_note.h"
 
@@ -32,13 +34,21 @@
 
 namespace user_notes {
 
+class FrameUserNoteChanges;
 class UserNoteManager;
+class UserNoteMetadataSnapshot;
 
 // Keyed service coordinating the different parts (Renderer, UI layer, storage
 // layer) of the User Notes feature for the current user profile.
-class UserNoteService : public KeyedService, public UserNotesUIDelegate {
+class UserNoteService : public KeyedService,
+                        public UserNotesUIDelegate,
+                        public UserNoteStorage::Observer {
  public:
-  explicit UserNoteService(std::unique_ptr<UserNoteServiceDelegate> delegate);
+  using IdSet =
+      std::unordered_set<base::UnguessableToken, base::UnguessableTokenHash>;
+
+  UserNoteService(std::unique_ptr<UserNoteServiceDelegate> delegate,
+                  std::unique_ptr<UserNoteStorage> storage);
   ~UserNoteService() override;
   UserNoteService(const UserNoteService&) = delete;
   UserNoteService& operator=(const UserNoteService&) = delete;
@@ -92,6 +102,9 @@
   void OnNoteUpdated(const base::UnguessableToken& id,
                      const std::string& note_content) override;
 
+  // UserNoteStorage implementation
+  void OnNotesChanged() override;
+
  private:
   struct ModelMapEntry {
     explicit ModelMapEntry(std::unique_ptr<UserNote> m);
@@ -104,10 +117,25 @@
     std::unordered_set<UserNoteManager*> managers;
   };
 
+  friend class MockUserNoteService;
   friend class UserNoteBaseTest;
   friend class UserNoteInstanceTest;
   friend class UserNoteUtilsTest;
   friend class ::UserNoteUICoordinatorTest;
+  FRIEND_TEST_ALL_PREFIXES(UserNoteServiceTest, OnNoteMetadataFetched);
+  FRIEND_TEST_ALL_PREFIXES(UserNoteServiceTest, OnNoteModelsFetched);
+  FRIEND_TEST_ALL_PREFIXES(UserNoteServiceTest, OnFrameChangesApplied);
+
+  // Private helpers used when processing note storage changes. Marked virtual
+  // for tests to override.
+  virtual void OnNoteMetadataFetched(
+      const std::vector<content::RenderFrameHost*>& all_frames,
+      UserNoteMetadataSnapshot metadata_snapshot);
+  virtual void OnNoteModelsFetched(
+      const IdSet& new_notes,
+      std::vector<std::unique_ptr<FrameUserNoteChanges>> note_changes,
+      std::vector<std::unique_ptr<UserNote>> notes);
+  virtual void OnFrameChangesApplied(base::UnguessableToken change_id);
 
   // Source of truth for the in-memory note models. Any note currently being
   // displayed in a tab is stored in this data structure. Each entry also
@@ -128,7 +156,15 @@
                      base::UnguessableTokenHash>
       creation_map_;
 
+  // A place to store the user note changes of a frame while they are being
+  // applied.
+  std::unordered_map<base::UnguessableToken,
+                     std::unique_ptr<FrameUserNoteChanges>,
+                     base::UnguessableTokenHash>
+      note_changes_in_progress_;
+
   std::unique_ptr<UserNoteServiceDelegate> delegate_;
+  std::unique_ptr<UserNoteStorage> storage_;
   base::WeakPtrFactory<UserNoteService> weak_ptr_factory_{this};
 };
 
diff --git a/components/user_notes/browser/user_note_service_unittest.cc b/components/user_notes/browser/user_note_service_unittest.cc
index ec981c4..6c26e10 100644
--- a/components/user_notes/browser/user_note_service_unittest.cc
+++ b/components/user_notes/browser/user_note_service_unittest.cc
@@ -4,22 +4,270 @@
 
 #include "components/user_notes/browser/user_note_service.h"
 
+#include <memory>
 #include <vector>
 
 #include "base/unguessable_token.h"
+#include "components/user_notes/browser/frame_user_note_changes.h"
 #include "components/user_notes/browser/user_note_base_test.h"
 #include "components/user_notes/browser/user_note_manager.h"
 #include "components/user_notes/browser/user_note_service.h"
+#include "components/user_notes/interfaces/user_note_service_delegate.h"
+#include "components/user_notes/interfaces/user_notes_ui.h"
+#include "components/user_notes/model/user_note_metadata.h"
+#include "components/user_notes/model/user_note_model_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using testing::_;
+using testing::Invoke;
+using testing::Mock;
 
 namespace user_notes {
 
+using IdList = std::vector<base::UnguessableToken>;
+
+class MockUserNoteServiceDelegate : public UserNoteServiceDelegate {
+ public:
+  MOCK_METHOD(std::vector<content::RenderFrameHost*>,
+              GetAllFramesForUserNotes,
+              (),
+              (override));
+  MOCK_METHOD(UserNotesUI*,
+              GetUICoordinatorForFrame,
+              (const content::RenderFrameHost* rfh),
+              (override));
+  MOCK_METHOD(bool,
+              IsFrameInActiveTab,
+              (const content::RenderFrameHost* rfh),
+              (override));
+
+  void SetFramesForUserNotes(
+      const std::vector<content::RenderFrameHost*>& frames) {
+    frames_ = frames;
+  }
+
+  std::vector<content::RenderFrameHost*> MockGetAllFramesForUserNotes() {
+    return frames_;
+  }
+
+ private:
+  std::vector<content::RenderFrameHost*> frames_;
+};
+
+class MockUserNoteStorage : public UserNoteStorage {
+ public:
+  MOCK_METHOD(void,
+              GetNoteMetadataForUrls,
+              (const std::vector<GURL>& urls,
+               base::OnceCallback<void(UserNoteMetadataSnapshot)> callback),
+              (override));
+
+  MOCK_METHOD(void,
+              GetNotesById,
+              (const IdList& ids,
+               base::OnceCallback<void(std::vector<std::unique_ptr<UserNote>>)>
+                   callback),
+              (override));
+
+  // The following must be mocked even though they're not used in the tests,
+  // because they're abstract.
+  MOCK_METHOD(void,
+              UpdateNote,
+              (const UserNote* model,
+               std::string note_body_text,
+               bool is_creation),
+              (override));
+
+  MOCK_METHOD(void,
+              DeleteNote,
+              (const base::UnguessableToken& guid),
+              (override));
+
+  MOCK_METHOD(void, DeleteAllForUrl, (const GURL& url), (override));
+
+  MOCK_METHOD(void,
+              DeleteAllForOrigin,
+              (const url::Origin& origin),
+              (override));
+
+  MOCK_METHOD(void, DeleteAllNotes, (), (override));
+
+  const std::vector<GURL>& requested_metadata_urls() {
+    return requested_metadata_urls_;
+  }
+  const IdList& requested_model_ids() { return requested_model_ids_; }
+
+  void MockGetNoteMetadataForUrls(
+      const std::vector<GURL>& urls,
+      base::OnceCallback<void(UserNoteMetadataSnapshot)> callback) {
+    requested_metadata_urls_ = urls;
+    std::move(callback).Run(UserNoteMetadataSnapshot());
+  }
+
+  void MockGetNotesById(
+      const IdList& ids,
+      base::OnceCallback<void(std::vector<std::unique_ptr<UserNote>>)>
+          callback) {
+    requested_model_ids_ = ids;
+    std::move(callback).Run({});
+  }
+
+ private:
+  std::vector<GURL> requested_metadata_urls_;
+  IdList requested_model_ids_;
+};
+
+// Partially mock the object under test so tests can control side effects.
+class MockUserNoteService : public UserNoteService {
+ public:
+  MockUserNoteService(std::unique_ptr<UserNoteServiceDelegate> delegate,
+                      std::unique_ptr<UserNoteStorage> storage)
+      : UserNoteService(std::move(delegate), std::move(storage)) {}
+
+  const UserNoteService::IdSet& computed_new_notes() {
+    return computed_new_notes_;
+  }
+
+  const IdList& changes_applied() { return changes_applied_; }
+
+  MOCK_METHOD(void,
+              OnNoteMetadataFetched,
+              (const std::vector<content::RenderFrameHost*>& all_frames,
+               UserNoteMetadataSnapshot metadata_snapshot),
+              (override));
+  MOCK_METHOD(void,
+              OnNoteModelsFetched,
+              (const UserNoteService::IdSet& new_notes,
+               std::vector<std::unique_ptr<FrameUserNoteChanges>> note_changes,
+               std::vector<std::unique_ptr<UserNote>> notes),
+              (override));
+  MOCK_METHOD(void,
+              OnFrameChangesApplied,
+              (base::UnguessableToken change_id),
+              (override));
+
+  void MockOnNoteModelsFetched(
+      const UserNoteService::IdSet& new_notes,
+      std::vector<std::unique_ptr<FrameUserNoteChanges>> note_changes,
+      std::vector<std::unique_ptr<UserNote>> notes) {
+    computed_new_notes_ = new_notes;
+  }
+
+  void MockOnFrameChangesApplied(base::UnguessableToken change_id) {
+    changes_applied_.emplace_back(change_id);
+  }
+
+  void CallBaseClassOnNoteMetadataFetched(
+      const std::vector<content::RenderFrameHost*>& all_frames,
+      UserNoteMetadataSnapshot metadata_snapshot) {
+    UserNoteService::OnNoteMetadataFetched(all_frames,
+                                           std::move(metadata_snapshot));
+  }
+
+  void CallBaseClassOnNoteModelsFetched(
+      const UserNoteService::IdSet& new_notes,
+      std::vector<std::unique_ptr<FrameUserNoteChanges>> note_changes,
+      std::vector<std::unique_ptr<UserNote>> notes) {
+    UserNoteService::OnNoteModelsFetched(new_notes, std::move(note_changes),
+                                         std::move(notes));
+  }
+
+  void CallBaseClassOnFrameChangesApplied(base::UnguessableToken change_id) {
+    UserNoteService::OnFrameChangesApplied(change_id);
+  }
+
+ private:
+  UserNoteService::IdSet computed_new_notes_;
+  IdList changes_applied_;
+};
+
+class MockUserNoteInstance : public UserNoteInstance {
+ public:
+  explicit MockUserNoteInstance(base::SafeRef<UserNote> model_ref,
+                                UserNoteManager* manager)
+      : UserNoteInstance(model_ref, manager) {}
+
+  void InitializeHighlightInternal() override {
+    DidFinishAttachment(gfx::Rect());
+  }
+};
+
+class MockFrameUserNoteChanges : public FrameUserNoteChanges {
+ public:
+  MockFrameUserNoteChanges(base::SafeRef<UserNoteService> service,
+                           content::RenderFrameHost* rfh,
+                           const ChangeList& notes_added,
+                           const ChangeList& notes_modified,
+                           const ChangeList& notes_removed)
+      : FrameUserNoteChanges(service,
+                             rfh,
+                             notes_added,
+                             notes_modified,
+                             notes_removed) {}
+
+ private:
+  std::unique_ptr<UserNoteInstance> MakeNoteInstance(
+      const UserNote* note_model,
+      UserNoteManager* manager) const override {
+    return std::make_unique<MockUserNoteInstance>(note_model->GetSafeRef(),
+                                                  manager);
+  }
+};
+
+class MockUserNotesUI : public UserNotesUI {
+ public:
+  MOCK_METHOD(void, Invalidate, (), (override));
+
+  // The following methods are not used for these tests but they still need to
+  // be mocked because they are sbstract.
+  MOCK_METHOD(void,
+              FocusNote,
+              (const base::UnguessableToken& guid),
+              (override));
+  MOCK_METHOD(void,
+              StartNoteCreation,
+              (UserNoteInstance * instance),
+              (override));
+  MOCK_METHOD(void, Show, (), (override));
+};
+
 class UserNoteServiceTest : public UserNoteBaseTest {
  protected:
   void SetUp() override {
     UserNoteBaseTest::SetUp();
     AddNewNotesToService(2);
   }
+
+  void CreateService() override {
+    auto service_delegate = std::make_unique<MockUserNoteServiceDelegate>();
+    service_delegate_ = service_delegate.get();
+
+    auto storage = std::make_unique<MockUserNoteStorage>();
+    EXPECT_CALL(*storage, UpdateNote).Times(0);
+    EXPECT_CALL(*storage, DeleteNote).Times(0);
+    EXPECT_CALL(*storage, DeleteAllForUrl).Times(0);
+    EXPECT_CALL(*storage, DeleteAllForOrigin).Times(0);
+    EXPECT_CALL(*storage, DeleteAllNotes).Times(0);
+    storage_ = storage.get();
+
+    note_service_ = std::make_unique<MockUserNoteService>(
+        std::move(service_delegate), std::move(storage));
+    mock_service_ = (MockUserNoteService*)note_service_.get();
+  }
+
+  std::vector<content::RenderFrameHost*> GetAllFramesInUse() {
+    std::vector<content::RenderFrameHost*> frames;
+    for (const std::unique_ptr<content::WebContents>& wc : web_contents_list_) {
+      frames.emplace_back(wc->GetPrimaryMainFrame());
+    }
+    return frames;
+  }
+
+  raw_ptr<MockUserNoteService> mock_service_;
+  raw_ptr<MockUserNoteServiceDelegate> service_delegate_;
+  raw_ptr<MockUserNoteStorage> storage_;
 };
 
 // Tests that note models are returned correctly by the service.
@@ -177,4 +425,416 @@
   EXPECT_FALSE(note_service_->IsNoteInProgress(note_ids_[2]));
 }
 
+// Tests that the service requests the metadata snapshot for the right URLs when
+// it gets notified that notes have changed on disk.
+TEST_F(UserNoteServiceTest, OnNotesChanged) {
+  // Initial setup.
+  AddNewNotesToService(2);
+  UserNoteManager* manager1 = ConfigureNewManager();
+  UserNoteManager* manager2 = ConfigureNewManager();
+  AddNewInstanceToManager(manager1, note_ids_[0]);
+  AddNewInstanceToManager(manager1, note_ids_[1]);
+  AddNewInstanceToManager(manager2, note_ids_[2]);
+  AddNewInstanceToManager(manager2, note_ids_[3]);
+  service_delegate_->SetFramesForUserNotes(GetAllFramesInUse());
+
+  // Verify initial setup.
+  EXPECT_EQ(ModelMapSize(), 4u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[0]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[1]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[2]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[3]), 1u);
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[0], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[1], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[2], manager2));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[3], manager2));
+
+  // Configure service delegate mock.
+  EXPECT_CALL(*service_delegate_, GetAllFramesForUserNotes)
+      .Times(1)
+      .WillOnce(
+          Invoke(service_delegate_.get(),
+                 &MockUserNoteServiceDelegate::MockGetAllFramesForUserNotes));
+  EXPECT_CALL(*service_delegate_, GetUICoordinatorForFrame).Times(0);
+  EXPECT_CALL(*service_delegate_, IsFrameInActiveTab).Times(0);
+
+  // Configure storage mock.
+  EXPECT_CALL(*storage_, GetNoteMetadataForUrls)
+      .Times(1)
+      .WillOnce(Invoke(storage_.get(),
+                       &MockUserNoteStorage::MockGetNoteMetadataForUrls));
+  EXPECT_CALL(*storage_, GetNotesById).Times(0);
+
+  // Configure service mock.
+  EXPECT_CALL(*mock_service_, OnNoteMetadataFetched).Times(1);
+  EXPECT_CALL(*mock_service_, OnNoteModelsFetched).Times(0);
+  EXPECT_CALL(*mock_service_, OnFrameChangesApplied).Times(0);
+
+  // Simulate notes changing on disk.
+  note_service_->OnNotesChanged();
+
+  // Mocks ensure callbacks are invoked synchronously, so expectations can be
+  // immediately verified.
+  const std::vector<GURL>& fetched_urls = storage_->requested_metadata_urls();
+  for (size_t i = 0; i < fetched_urls.size(); ++i) {
+    EXPECT_EQ(
+        fetched_urls[i],
+        web_contents_list_[i]->GetPrimaryMainFrame()->GetLastCommittedURL());
+  }
+}
+
+// Tests that the service requests the right models from the storage after
+// receiving the metadata snapshot.
+TEST_F(UserNoteServiceTest, OnNoteMetadataFetched) {
+  // Initial setup.
+  AddNewNotesToService(2);
+  AddPartialNotesToService(1);
+  UserNoteManager* manager1 = ConfigureNewManager();
+  UserNoteManager* manager2 = ConfigureNewManager();
+  AddNewInstanceToManager(manager1, note_ids_[0]);
+  AddNewInstanceToManager(manager1, note_ids_[1]);
+  AddNewInstanceToManager(manager2, note_ids_[2]);
+  AddNewInstanceToManager(manager2, note_ids_[3]);
+
+  // Verify initial setup.
+  EXPECT_EQ(ModelMapSize(), 4u);
+  EXPECT_EQ(CreationMapSize(), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[0]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[1]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[2]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[3]), 1u);
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[0], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[1], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[2], manager2));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[3], manager2));
+
+  // Configure service delegate mock.
+  EXPECT_CALL(*service_delegate_, GetAllFramesForUserNotes).Times(0);
+  EXPECT_CALL(*service_delegate_, GetUICoordinatorForFrame).Times(0);
+  EXPECT_CALL(*service_delegate_, IsFrameInActiveTab).Times(0);
+
+  // Configure storage mock.
+  EXPECT_CALL(*storage_, GetNoteMetadataForUrls).Times(0);
+  EXPECT_CALL(*storage_, GetNotesById)
+      .Times(1)
+      .WillOnce(Invoke(storage_.get(), &MockUserNoteStorage::MockGetNotesById));
+
+  // Configure service mock.
+  EXPECT_CALL(*mock_service_, OnNoteMetadataFetched)
+      .Times(1)
+      .WillOnce(
+          Invoke(mock_service_.get(),
+                 &MockUserNoteService::CallBaseClassOnNoteMetadataFetched));
+  EXPECT_CALL(*mock_service_, OnNoteModelsFetched)
+      .Times(1)
+      .WillOnce(Invoke(mock_service_.get(),
+                       &MockUserNoteService::MockOnNoteModelsFetched));
+  EXPECT_CALL(*mock_service_, OnFrameChangesApplied).Times(0);
+
+  // Create a fake metadata snapshot with some updated and new notes, including
+  // one new note that wasn't in the creation map so simulate receiving it from
+  // Sync.
+  note_ids_.emplace_back(base::UnguessableToken::Create());
+  UserNoteMetadataSnapshot snapshot;
+  GURL url1 =
+      web_contents_list_[0]->GetPrimaryMainFrame()->GetLastCommittedURL();
+  GURL url2 =
+      web_contents_list_[1]->GetPrimaryMainFrame()->GetLastCommittedURL();
+  snapshot.AddEntry(
+      url1, note_ids_[0],
+      std::make_unique<UserNoteMetadata>(base::Time::Now(), base::Time::Now(),
+                                         /*min_note_version=*/1));
+  snapshot.AddEntry(
+      url1, note_ids_[4],
+      std::make_unique<UserNoteMetadata>(base::Time::Now(), base::Time::Now(),
+                                         /*min_note_version=*/1));
+  snapshot.AddEntry(
+      url2, note_ids_[2],
+      std::make_unique<UserNoteMetadata>(base::Time::Now(), base::Time::Now(),
+                                         /*min_note_version=*/1));
+  snapshot.AddEntry(
+      url2, note_ids_[5],
+      std::make_unique<UserNoteMetadata>(base::Time::Now(), base::Time::Now(),
+                                         /*min_note_version=*/1));
+
+  // Simulate the storage returning the metadata snapshot to the service
+  // callback.
+  note_service_->OnNoteMetadataFetched(GetAllFramesInUse(),
+                                       std::move(snapshot));
+
+  // Mocks ensure callbacks are invoked synchronously, so expectations can be
+  // immediately verified.
+  const IdList& fetched_ids = storage_->requested_model_ids();
+  EXPECT_EQ(fetched_ids.size(), 4u);
+  EXPECT_NE(std::find(fetched_ids.begin(), fetched_ids.end(), note_ids_[0]),
+            fetched_ids.end());
+  EXPECT_NE(std::find(fetched_ids.begin(), fetched_ids.end(), note_ids_[2]),
+            fetched_ids.end());
+  EXPECT_NE(std::find(fetched_ids.begin(), fetched_ids.end(), note_ids_[4]),
+            fetched_ids.end());
+  EXPECT_NE(std::find(fetched_ids.begin(), fetched_ids.end(), note_ids_[5]),
+            fetched_ids.end());
+
+  const UserNoteService::IdSet& computed_new_notes =
+      mock_service_->computed_new_notes();
+  EXPECT_EQ(computed_new_notes.size(), 2u);
+  EXPECT_NE(computed_new_notes.find(note_ids_[4]), computed_new_notes.end());
+  EXPECT_NE(computed_new_notes.find(note_ids_[5]), computed_new_notes.end());
+}
+
+// Tests that the service correctly updates the models in the model map and
+// applies the necessary note changes.
+TEST_F(UserNoteServiceTest, OnNoteModelsFetched) {
+  // Initial setup.
+  AddNewNotesToService(2);
+  AddPartialNotesToService(1);
+  UserNoteManager* manager1 = ConfigureNewManager();
+  UserNoteManager* manager2 = ConfigureNewManager();
+  AddNewInstanceToManager(manager1, note_ids_[0]);
+  AddNewInstanceToManager(manager1, note_ids_[1]);
+  AddNewInstanceToManager(manager2, note_ids_[2]);
+  AddNewInstanceToManager(manager2, note_ids_[3]);
+
+  // For note 1 to be correctly deleted later in the test, its target URL must
+  // be changed to match the parent frame.
+  content::RenderFrameHost* frame1 =
+      web_contents_list_[0]->GetPrimaryMainFrame();
+  const auto& note_1_entry_it = note_service_->model_map_.find(note_ids_[1]);
+  note_1_entry_it->second.model->Update(std::make_unique<UserNote>(
+      note_ids_[1], GetTestUserNoteMetadata(), GetTestUserNoteBody(),
+      GetTestUserNotePageTarget(frame1->GetLastCommittedURL().spec())));
+
+  // Verify initial setup.
+  EXPECT_EQ(ModelMapSize(), 4u);
+  EXPECT_EQ(CreationMapSize(), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[0]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[1]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[2]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[3]), 1u);
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[0], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[1], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[2], manager2));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[3], manager2));
+
+  // Configure service delegate mock.
+  EXPECT_CALL(*service_delegate_, GetAllFramesForUserNotes).Times(0);
+  EXPECT_CALL(*service_delegate_, GetUICoordinatorForFrame).Times(0);
+  EXPECT_CALL(*service_delegate_, IsFrameInActiveTab).Times(0);
+
+  // Configure storage mock.
+  EXPECT_CALL(*storage_, GetNoteMetadataForUrls).Times(0);
+  EXPECT_CALL(*storage_, GetNotesById).Times(0);
+
+  // Configure service mock.
+  EXPECT_CALL(*mock_service_, OnNoteMetadataFetched).Times(0);
+  EXPECT_CALL(*mock_service_, OnNoteModelsFetched)
+      .Times(1)
+      .WillOnce(Invoke(mock_service_.get(),
+                       &MockUserNoteService::CallBaseClassOnNoteModelsFetched));
+  EXPECT_CALL(*mock_service_, OnFrameChangesApplied)
+      .Times(2)
+      .WillRepeatedly(Invoke(mock_service_.get(),
+                             &MockUserNoteService::MockOnFrameChangesApplied));
+
+  // Prepare the fake input for passing to the method under test. 2 notes are
+  // simulated as having been updated, 2 notes as created, and one as having
+  // been removed. One of the created notes is not present in the creation map
+  // to simulate receiving it from Sync.
+  note_ids_.emplace_back(base::UnguessableToken::Create());
+  UserNoteService::IdSet new_notes;
+  new_notes.emplace(note_ids_[4]);
+  new_notes.emplace(note_ids_[5]);
+
+  content::RenderFrameHost* frame2 =
+      web_contents_list_[1]->GetPrimaryMainFrame();
+  auto change1 = std::make_unique<MockFrameUserNoteChanges>(
+      note_service_->GetSafeRef(), frame1, /*added=*/IdList{note_ids_[4]},
+      /*modified=*/IdList{note_ids_[0]}, /*removed=*/IdList{note_ids_[1]});
+  auto change2 = std::make_unique<MockFrameUserNoteChanges>(
+      note_service_->GetSafeRef(), frame2, /*added=*/IdList{note_ids_[5]},
+      /*modified=*/IdList{note_ids_[2]}, /*removed=*/IdList{});
+  base::UnguessableToken change1_id = change1->id();
+  base::UnguessableToken change2_id = change2->id();
+  std::vector<std::unique_ptr<FrameUserNoteChanges>> note_changes;
+  note_changes.emplace_back(std::move(change1));
+  note_changes.emplace_back(std::move(change2));
+
+  const std::string kText0 = "updated note 0";
+  const std::string kText2 = "updated note 2";
+  const std::string kText4 = "new note 4";
+  const std::string kText5 = "new note 5";
+  const std::string url1 = frame1->GetLastCommittedURL().spec();
+  const std::string url2 = frame2->GetLastCommittedURL().spec();
+  auto note0 = std::make_unique<UserNote>(
+      note_ids_[0], GetTestUserNoteMetadata(),
+      std::make_unique<UserNoteBody>(kText0), GetTestUserNotePageTarget(url1));
+  auto note2 = std::make_unique<UserNote>(
+      note_ids_[2], GetTestUserNoteMetadata(),
+      std::make_unique<UserNoteBody>(kText2), GetTestUserNotePageTarget(url2));
+  auto note4 = std::make_unique<UserNote>(
+      note_ids_[4], GetTestUserNoteMetadata(),
+      std::make_unique<UserNoteBody>(kText4), GetTestUserNotePageTarget(url1));
+  auto note5 = std::make_unique<UserNote>(
+      note_ids_[5], GetTestUserNoteMetadata(),
+      std::make_unique<UserNoteBody>(kText5), GetTestUserNotePageTarget(url2));
+  std::vector<std::unique_ptr<UserNote>> note_models;
+  note_models.emplace_back(std::move(note0));
+  note_models.emplace_back(std::move(note4));
+  note_models.emplace_back(std::move(note2));
+  note_models.emplace_back(std::move(note5));
+
+  // Simulate the storage returning the updated note models to the service
+  // callback.
+  note_service_->OnNoteModelsFetched(new_notes, std::move(note_changes),
+                                     std::move(note_models));
+
+  // Mocks ensure callbacks are invoked synchronously, so expectations can be
+  // immediately verified.
+  const IdList& changes_applied = mock_service_->changes_applied();
+  EXPECT_EQ(changes_applied.size(), 2u);
+  EXPECT_NE(
+      std::find(changes_applied.begin(), changes_applied.end(), change1_id),
+      changes_applied.end());
+  EXPECT_NE(
+      std::find(changes_applied.begin(), changes_applied.end(), change2_id),
+      changes_applied.end());
+
+  EXPECT_EQ(ModelMapSize(), 5u);
+  EXPECT_EQ(CreationMapSize(), 0u);
+  EXPECT_FALSE(DoesModelExist(note_ids_[1]));
+  EXPECT_EQ(ManagerCountForId(note_ids_[0]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[2]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[3]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[4]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[5]), 1u);
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[0], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[2], manager2));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[3], manager2));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[4], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[5], manager2));
+
+  std::string actual_text_0 =
+      note_service_->GetNoteModel(note_ids_[0])->body().plain_text_value();
+  std::string actual_text_2 =
+      note_service_->GetNoteModel(note_ids_[2])->body().plain_text_value();
+  std::string actual_text_4 =
+      note_service_->GetNoteModel(note_ids_[4])->body().plain_text_value();
+  std::string actual_text_5 =
+      note_service_->GetNoteModel(note_ids_[5])->body().plain_text_value();
+  EXPECT_EQ(actual_text_0, kText0);
+  EXPECT_EQ(actual_text_2, kText2);
+  EXPECT_EQ(actual_text_4, kText4);
+  EXPECT_EQ(actual_text_5, kText5);
+
+  EXPECT_EQ(note_service_->note_changes_in_progress_.size(), 2u);
+  EXPECT_NE(note_service_->note_changes_in_progress_.find(change1_id),
+            note_service_->note_changes_in_progress_.end());
+  EXPECT_NE(note_service_->note_changes_in_progress_.find(change2_id),
+            note_service_->note_changes_in_progress_.end());
+}
+
+// Tests that the service correctly finalizes frame changes that have been
+// applied and notifies the UI to update itself when needed.
+TEST_F(UserNoteServiceTest, OnFrameChangesApplied) {
+  // Initial setup.
+  AddNewNotesToService(2);
+  AddPartialNotesToService(1);
+  UserNoteManager* manager1 = ConfigureNewManager();
+  UserNoteManager* manager2 = ConfigureNewManager();
+  AddNewInstanceToManager(manager1, note_ids_[0]);
+  AddNewInstanceToManager(manager1, note_ids_[1]);
+  AddNewInstanceToManager(manager2, note_ids_[2]);
+  AddNewInstanceToManager(manager2, note_ids_[3]);
+
+  content::RenderFrameHost* frame1 =
+      web_contents_list_[0]->GetPrimaryMainFrame();
+  content::RenderFrameHost* frame2 =
+      web_contents_list_[1]->GetPrimaryMainFrame();
+  auto change1 = std::make_unique<FrameUserNoteChanges>(
+      note_service_->GetSafeRef(), frame1, /*added=*/IdList{},
+      /*modified=*/IdList{note_ids_[0]}, /*removed=*/IdList{});
+  auto change2 = std::make_unique<FrameUserNoteChanges>(
+      note_service_->GetSafeRef(), frame2, /*added=*/IdList{},
+      /*modified=*/IdList{note_ids_[2]}, /*removed=*/IdList{});
+  base::UnguessableToken change1_id = change1->id();
+  base::UnguessableToken change2_id = change2->id();
+  note_service_->note_changes_in_progress_.emplace(change1_id,
+                                                   std::move(change1));
+  note_service_->note_changes_in_progress_.emplace(change2_id,
+                                                   std::move(change2));
+
+  // Verify initial setup.
+  EXPECT_EQ(ModelMapSize(), 4u);
+  EXPECT_EQ(CreationMapSize(), 1u);
+  EXPECT_EQ(note_service_->note_changes_in_progress_.size(), 2u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[0]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[1]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[2]), 1u);
+  EXPECT_EQ(ManagerCountForId(note_ids_[3]), 1u);
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[0], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[1], manager1));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[2], manager2));
+  EXPECT_TRUE(DoesManagerExistForId(note_ids_[3], manager2));
+
+  // Configure UI mock.
+  auto mock_ui = std::make_unique<MockUserNotesUI>();
+  EXPECT_CALL(*mock_ui, Invalidate).Times(1);
+  EXPECT_CALL(*mock_ui, FocusNote).Times(0);
+  EXPECT_CALL(*mock_ui, StartNoteCreation).Times(0);
+  EXPECT_CALL(*mock_ui, Show).Times(0);
+
+  // Configure service delegate mock.
+  EXPECT_CALL(*service_delegate_, GetAllFramesForUserNotes).Times(0);
+  EXPECT_CALL(*service_delegate_, GetUICoordinatorForFrame(_))
+      .Times(1)
+      .WillOnce(Invoke([&mock_ui](const content::RenderFrameHost* frame) {
+        return mock_ui.get();
+      }));
+  EXPECT_CALL(*service_delegate_, IsFrameInActiveTab(_))
+      .Times(2)
+      .WillOnce(
+          Invoke([](const content::RenderFrameHost* frame) { return true; }))
+      .WillOnce(
+          Invoke([](const content::RenderFrameHost* frame) { return false; }));
+
+  // Configure storage mock.
+  EXPECT_CALL(*storage_, GetNoteMetadataForUrls).Times(0);
+  EXPECT_CALL(*storage_, GetNotesById).Times(0);
+
+  // Configure service mock.
+  EXPECT_CALL(*mock_service_, OnNoteMetadataFetched).Times(0);
+  EXPECT_CALL(*mock_service_, OnNoteModelsFetched).Times(0);
+  EXPECT_CALL(*mock_service_, OnFrameChangesApplied)
+      .Times(2)
+      .WillRepeatedly(
+          Invoke(mock_service_.get(),
+                 &MockUserNoteService::CallBaseClassOnFrameChangesApplied));
+
+  // Simulate the first change being applied. It should invalidate the UI since
+  // it is simulated as being in an active tab.
+  note_service_->OnFrameChangesApplied(change1_id);
+
+  EXPECT_EQ(ModelMapSize(), 4u);
+  EXPECT_EQ(CreationMapSize(), 1u);
+  EXPECT_EQ(note_service_->note_changes_in_progress_.size(), 1u);
+  EXPECT_EQ(note_service_->note_changes_in_progress_.find(change1_id),
+            note_service_->note_changes_in_progress_.end());
+  EXPECT_NE(note_service_->note_changes_in_progress_.find(change2_id),
+            note_service_->note_changes_in_progress_.end());
+
+  Mock::VerifyAndClearExpectations(mock_ui.get());
+
+  // Simulate the second change being applied.
+  EXPECT_CALL(*mock_ui, Invalidate).Times(0);
+  EXPECT_CALL(*mock_ui, FocusNote).Times(0);
+  EXPECT_CALL(*mock_ui, StartNoteCreation).Times(0);
+  EXPECT_CALL(*mock_ui, Show).Times(0);
+
+  note_service_->OnFrameChangesApplied(change2_id);
+
+  EXPECT_EQ(ModelMapSize(), 4u);
+  EXPECT_EQ(CreationMapSize(), 1u);
+  EXPECT_EQ(note_service_->note_changes_in_progress_.size(), 0u);
+}
+
 }  // namespace user_notes
diff --git a/components/user_notes/browser/user_note_utils.cc b/components/user_notes/browser/user_note_utils.cc
index abef4b06..16a35d96 100644
--- a/components/user_notes/browser/user_note_utils.cc
+++ b/components/user_notes/browser/user_note_utils.cc
@@ -15,11 +15,11 @@
 
 namespace user_notes {
 
-std::vector<FrameUserNoteChanges> CalculateNoteChanges(
+std::vector<std::unique_ptr<FrameUserNoteChanges>> CalculateNoteChanges(
     const UserNoteService& note_service,
     const std::vector<content::RenderFrameHost*>& rfhs,
     const UserNoteMetadataSnapshot& metadata_snapshot) {
-  std::vector<FrameUserNoteChanges> result;
+  std::vector<std::unique_ptr<FrameUserNoteChanges>> result;
 
   // Create an empty metadata map to simplify the algorithm below for cases
   // where there's no entry in the metadata snapshot for a frame's URL.
@@ -86,9 +86,9 @@
     }
 
     if (!added.empty() || !removed.empty() || !modified.empty()) {
-      result.emplace_back(
-          FrameUserNoteChanges(note_service.GetSafeRef(), rfh, std::move(added),
-                               std::move(modified), std::move(removed)));
+      result.emplace_back(std::make_unique<FrameUserNoteChanges>(
+          note_service.GetSafeRef(), rfh, std::move(added), std::move(modified),
+          std::move(removed)));
     }
   }
 
diff --git a/components/user_notes/browser/user_note_utils.h b/components/user_notes/browser/user_note_utils.h
index a13806f4..1b190d56 100644
--- a/components/user_notes/browser/user_note_utils.h
+++ b/components/user_notes/browser/user_note_utils.h
@@ -23,7 +23,7 @@
 // actually contain based on the provided metadata snapshot. A
 // `FrameUserNoteChanges` object is generated for each frame where notes
 // don't match the metadata.
-std::vector<FrameUserNoteChanges> CalculateNoteChanges(
+std::vector<std::unique_ptr<FrameUserNoteChanges>> CalculateNoteChanges(
     const UserNoteService& note_service,
     const std::vector<content::RenderFrameHost*>& rfhs,
     const UserNoteMetadataSnapshot& metadata_snapshot);
diff --git a/components/user_notes/browser/user_note_utils_unittest.cc b/components/user_notes/browser/user_note_utils_unittest.cc
index fcaf180..1f5f761 100644
--- a/components/user_notes/browser/user_note_utils_unittest.cc
+++ b/components/user_notes/browser/user_note_utils_unittest.cc
@@ -227,8 +227,9 @@
     content::RenderViewHostTestHarness::SetUp();
 
     // Create the note service and the note models that will be used in this
-    // test case. A service delegate isn't needed for these tests.
-    note_service_ = std::make_unique<UserNoteService>(/*delegate=*/nullptr);
+    // test case. A service delegate and storage aren't needed for these tests.
+    note_service_ = std::make_unique<UserNoteService>(/*delegate=*/nullptr,
+                                                      /*storage=*/nullptr);
     for (const NoteConfig& note : GetParam().notes) {
       CreateNewNoteAndAddToService(note);
     }
@@ -700,20 +701,20 @@
 
   // Calculate the diff between the notes in the frames and the notes in the
   // metadata.
-  const std::vector<FrameUserNoteChanges>& actual_diffs =
+  const std::vector<std::unique_ptr<FrameUserNoteChanges>>& actual_diffs =
       CalculateNoteChanges(*note_service_, frame_hosts, metadata_snapshot);
 
   std::unordered_set<content::RenderFrameHost*> frames_with_diff;
-  for (const FrameUserNoteChanges& diff : actual_diffs) {
+  for (const std::unique_ptr<FrameUserNoteChanges>& diff : actual_diffs) {
     // Find the frame config for this diff's frame.
-    const auto config_it = frame_to_config_.find(diff.rfh_);
+    const auto config_it = frame_to_config_.find(diff->rfh_);
     DCHECK(config_it != frame_to_config_.end());
     FrameConfig frame_config = config_it->second;
 
     // Make sure there is at most one diff per frame.
-    EXPECT_TRUE(frames_with_diff.find(diff.rfh_) == frames_with_diff.end())
+    EXPECT_TRUE(frames_with_diff.find(diff->rfh_) == frames_with_diff.end())
         << "More than one diff generated for frame " << frame_config.test_id;
-    frames_with_diff.emplace(diff.rfh_);
+    frames_with_diff.emplace(diff->rfh_);
 
     // Verify that a diff was expected for this frame.
     EXPECT_TRUE(frame_config.expect_diff)
@@ -723,19 +724,19 @@
     // Verify added, modified and removed notes are as expected. Use copies to
     // prevent any side effect of sorting in place.
     NoteIdList actual_added =
-        ConvertToSortedTestIds(diff.notes_added_, token_to_test_id_);
+        ConvertToSortedTestIds(diff->notes_added_, token_to_test_id_);
     NoteIdList expected_added = CopyAndSort(frame_config.added);
     EXPECT_EQ(actual_added, expected_added)
         << "Unexpected ADDED results for frame " << frame_config.test_id;
 
     NoteIdList actual_modified =
-        ConvertToSortedTestIds(diff.notes_modified_, token_to_test_id_);
+        ConvertToSortedTestIds(diff->notes_modified_, token_to_test_id_);
     NoteIdList expected_modified = CopyAndSort(frame_config.modified);
     EXPECT_EQ(actual_modified, expected_modified)
         << "Unexpected MODIFIED results for frame " << frame_config.test_id;
 
     NoteIdList actual_removed =
-        ConvertToSortedTestIds(diff.notes_removed_, token_to_test_id_);
+        ConvertToSortedTestIds(diff->notes_removed_, token_to_test_id_);
     NoteIdList expected_removed = CopyAndSort(frame_config.removed);
     EXPECT_EQ(actual_removed, expected_removed)
         << "Unexpected REMOVED results for frame " << frame_config.test_id;
diff --git a/components/user_notes/interfaces/user_note_service_delegate.h b/components/user_notes/interfaces/user_note_service_delegate.h
index 75d3b92a..d7e215c 100644
--- a/components/user_notes/interfaces/user_note_service_delegate.h
+++ b/components/user_notes/interfaces/user_note_service_delegate.h
@@ -33,6 +33,10 @@
   // example to bring a note into focus or start the note creation flow.
   virtual UserNotesUI* GetUICoordinatorForFrame(
       const content::RenderFrameHost* rfh) = 0;
+
+  // Called by the `UserNoteService` to determine whether the given frame is
+  // part of the active tab of its owning browser window.
+  virtual bool IsFrameInActiveTab(const content::RenderFrameHost* rfh) = 0;
 };
 
 }  // namespace user_notes
diff --git a/components/user_notes/interfaces/user_note_storage.h b/components/user_notes/interfaces/user_note_storage.h
index e612a72..5e2a9c7 100644
--- a/components/user_notes/interfaces/user_note_storage.h
+++ b/components/user_notes/interfaces/user_note_storage.h
@@ -38,13 +38,13 @@
   // results are returned via `callback`, mapped by URL and by note
   // ID.
   virtual void GetNoteMetadataForUrls(
-      std::vector<GURL> urls,
+      const std::vector<GURL>& urls,
       base::OnceCallback<void(UserNoteMetadataSnapshot)> callback) = 0;
 
   // Fetches all `UserNotes` corresponding to the given IDs from disk. The
   // results are returned via `callback`.
   virtual void GetNotesById(
-      std::vector<base::UnguessableToken> ids,
+      const std::vector<base::UnguessableToken>& ids,
       base::OnceCallback<void(std::vector<std::unique_ptr<UserNote>>)>
           callback) = 0;
 
diff --git a/components/user_notes/model/user_note.cc b/components/user_notes/model/user_note.cc
index 1259680..a17e37c 100644
--- a/components/user_notes/model/user_note.cc
+++ b/components/user_notes/model/user_note.cc
@@ -21,4 +21,11 @@
   return weak_ptr_factory_.GetSafeRef();
 }
 
+void UserNote::Update(std::unique_ptr<UserNote> new_model) {
+  DCHECK(new_model->id() == id_);
+  metadata_ = std::move(new_model->metadata_);
+  body_ = std::move(new_model->body_);
+  target_ = std::move(new_model->target_);
+}
+
 }  // namespace user_notes
diff --git a/components/user_notes/model/user_note.h b/components/user_notes/model/user_note.h
index b1746c4f..9d00819 100644
--- a/components/user_notes/model/user_note.h
+++ b/components/user_notes/model/user_note.h
@@ -35,6 +35,9 @@
   const UserNoteBody& body() const { return *body_; }
   const UserNoteTarget& target() const { return *target_; }
 
+  // Consumes the provided model to update this one.
+  void Update(std::unique_ptr<UserNote> new_model);
+
  private:
   // The unique (among the user's notes) ID for this note.
   base::UnguessableToken id_;
diff --git a/components/user_notes/storage/user_note_storage_impl.cc b/components/user_notes/storage/user_note_storage_impl.cc
index afdc176e..88fd75e 100644
--- a/components/user_notes/storage/user_note_storage_impl.cc
+++ b/components/user_notes/storage/user_note_storage_impl.cc
@@ -4,6 +4,7 @@
 
 #include "components/user_notes/storage/user_note_storage_impl.h"
 
+#include "base/bind.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_refptr.h"
@@ -21,11 +22,16 @@
                     {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
                      base::TaskShutdownBehavior::BLOCK_SHUTDOWN}),
                 path_to_database_dir) {
-  database_.AsyncCall(&UserNoteDatabase::Init);
+  // An empty `Then()` is needed to satisfy a DCHECK in `AsyncCall` because
+  // `UserNoteDatabase::Init` returns a value.
+  database_.AsyncCall(&UserNoteDatabase::Init)
+      .Then(base::BindOnce([](bool result) {}));
 }
 
+UserNoteStorageImpl::~UserNoteStorageImpl() = default;
+
 void UserNoteStorageImpl::GetNoteMetadataForUrls(
-    std::vector<GURL> urls,
+    const std::vector<GURL>& urls,
     base::OnceCallback<void(UserNoteMetadataSnapshot)> callback) {
   database_.AsyncCall(&UserNoteDatabase::GetNoteMetadataForUrls)
       .WithArgs(std::move(urls))
@@ -33,7 +39,7 @@
 }
 
 void UserNoteStorageImpl::GetNotesById(
-    std::vector<base::UnguessableToken> ids,
+    const std::vector<base::UnguessableToken>& ids,
     base::OnceCallback<void(std::vector<std::unique_ptr<UserNote>>)> callback) {
   database_.AsyncCall(&UserNoteDatabase::GetNotesById)
       .WithArgs(std::move(ids))
diff --git a/components/user_notes/storage/user_note_storage_impl.h b/components/user_notes/storage/user_note_storage_impl.h
index b12a085..7a84f63 100644
--- a/components/user_notes/storage/user_note_storage_impl.h
+++ b/components/user_notes/storage/user_note_storage_impl.h
@@ -30,11 +30,11 @@
 
   // Implement UserNoteStorage
   void GetNoteMetadataForUrls(
-      std::vector<GURL> urls,
+      const std::vector<GURL>& urls,
       base::OnceCallback<void(UserNoteMetadataSnapshot)> callback) override;
 
   void GetNotesById(
-      std::vector<base::UnguessableToken> ids,
+      const std::vector<base::UnguessableToken>& ids,
       base::OnceCallback<void(std::vector<std::unique_ptr<UserNote>>)> callback)
       override;
 
diff --git a/components/variations/study_filtering.cc b/components/variations/study_filtering.cc
index 8d6e78b..51749f16 100644
--- a/components/variations/study_filtering.cc
+++ b/components/variations/study_filtering.cc
@@ -42,11 +42,7 @@
   if (filter.channel_size() == 0)
     return true;
 
-  for (int i = 0; i < filter.channel_size(); ++i) {
-    if (filter.channel(i) == channel)
-      return true;
-  }
-  return false;
+  return base::Contains(filter.channel(), channel);
 }
 
 bool CheckStudyFormFactor(const Study::Filter& filter,
diff --git a/components/viz/host/client_frame_sink_video_capturer.cc b/components/viz/host/client_frame_sink_video_capturer.cc
index 1d3af9be..8eb856c 100644
--- a/components/viz/host/client_frame_sink_video_capturer.cc
+++ b/components/viz/host/client_frame_sink_video_capturer.cc
@@ -172,6 +172,12 @@
   consumer_->OnFrameWithEmptyRegionCapture();
 }
 
+void ClientFrameSinkVideoCapturer::OnNewCropVersion(uint32_t crop_version) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  consumer_->OnNewCropVersion(crop_version);
+}
+
 void ClientFrameSinkVideoCapturer::OnLog(const std::string& message) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
diff --git a/components/viz/host/client_frame_sink_video_capturer.h b/components/viz/host/client_frame_sink_video_capturer.h
index ce514b0..995fb44 100644
--- a/components/viz/host/client_frame_sink_video_capturer.h
+++ b/components/viz/host/client_frame_sink_video_capturer.h
@@ -129,6 +129,7 @@
       const gfx::Rect& content_rect,
       mojo::PendingRemote<mojom::FrameSinkVideoConsumerFrameCallbacks>
           callbacks) final;
+  void OnNewCropVersion(uint32_t crop_version) final;
   void OnFrameWithEmptyRegionCapture() final;
   void OnStopped() final;
   void OnLog(const std::string& message) final;
diff --git a/components/viz/service/display/overlay_processor_ozone.cc b/components/viz/service/display/overlay_processor_ozone.cc
index 3ae5364..1266269 100644
--- a/components/viz/service/display/overlay_processor_ozone.cc
+++ b/components/viz/service/display/overlay_processor_ozone.cc
@@ -22,6 +22,7 @@
 #include "components/viz/service/display/overlay_strategy_underlay_cast.h"
 #include "gpu/command_buffer/client/shared_image_interface.h"
 #include "gpu/command_buffer/service/shared_image_manager.h"
+#include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
 namespace viz {
@@ -73,6 +74,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 bool AllowColorSpaceCombination(
+    gfx::BufferFormat source_format,
     const gfx::ColorSpace& source_color_space,
     const gfx::ColorSpace& destination_color_space) {
   // Allow invalid source color spaces because the assumption is that the
@@ -81,6 +83,35 @@
   if (!source_color_space.IsValid())
     return true;
 
+  // Since https://crrev.com/c/2336347, we force BT.601/narrow for the
+  // COLOR_ENCODING and COLOR_RANGE DRM/KMS properties. On the other hand, the
+  // compositor is able to handle different YUV encodings and ranges. Therefore,
+  // in theory, if we don't want to see a difference between overlays and
+  // compositing, we should not promote video frames to overlays unless they
+  // actually use BT.601/narrow.
+  //
+  // In practice, however, we expect to see lots of BT.709 video frames, and we
+  // don't want to reject all of them for overlays because the visual difference
+  // between BT.601/narrow and BT.709/narrow is not expected to be much.
+  // Therefore, in being consistent with the values we provide for
+  // EGL_YUV_COLOR_SPACE_HINT_EXT/EGL_SAMPLE_RANGE_HINT_EXT (see
+  // https://crrev.com/c/3662321), we'll only allow frames that use non-BT.2020
+  // with non-full range. In those cases, the compositor and the display
+  // controller are expected to render the frames equally (and decently - with
+  // the understanding that the final result may not be fully correct).
+  //
+  // TODO(b/233667677): Remove this when we've plumbed the YUV encoding and
+  // range to DRM/KMS. At that point, we need to ensure that
+  // EGL_YUV_COLOR_SPACE_HINT_EXT/EGL_SAMPLE_RANGE_HINT_EXT would also get the
+  // same values as DRM/KMS.
+  if ((source_format == gfx::BufferFormat::YUV_420_BIPLANAR ||
+       source_format == gfx::BufferFormat::YVU_420) &&
+      (source_color_space.GetPrimaryID() ==
+           gfx::ColorSpace::PrimaryID::BT2020 ||
+       source_color_space.GetRangeID() == gfx::ColorSpace::RangeID::FULL)) {
+    return false;
+  }
+
   // Allow color space mismatches as long as either a) the source color space is
   // SRGB; or b) both the source and destination color spaces have the same
   // color usage. It is possible that case (a) still allows for visible color
@@ -197,6 +228,7 @@
       // backend when we get an API for per-plane color management.
       if (!surface_iterator->requires_overlay &&
           !AllowColorSpaceCombination(
+              /*source_format=*/surface_iterator->format,
               /*source_color_space=*/surface_iterator->color_space,
               /*destination_color_space=*/primary_plane_color_space_)) {
         *ozone_surface_iterator = ui::OverlaySurfaceCandidate();
diff --git a/components/viz/service/display/skia_output_surface.h b/components/viz/service/display/skia_output_surface.h
index a6557e3..49eac33 100644
--- a/components/viz/service/display/skia_output_surface.h
+++ b/components/viz/service/display/skia_output_surface.h
@@ -125,6 +125,13 @@
                                          bool is_overlay,
                                          const gpu::Mailbox& mailbox) = 0;
 
+  // Create an overdraw recorder for the current paint which will be drawn on
+  // top of the current canvas when EndPaint() is called. Returns the new
+  // wrapped SkCanvas to be used by SkiaRenderer.
+  // This should be called for the root render pass only when
+  // debug_settings.show_overdraw_feedback = true.
+  virtual SkCanvas* RecordOverdrawForCurrentPaint() = 0;
+
   // Finish painting the current frame or current render pass, depends on which
   // BeginPaint function is called last. This method will schedule a GPU task to
   // play the DDL back on GPU thread on a cached SkSurface.
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index 19f38c19..919d6bb 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -979,6 +979,9 @@
 
 void SkiaRenderer::BindFramebufferToOutputSurface() {
   current_canvas_ = skia_output_surface_->BeginPaintCurrentFrame();
+  if (debug_settings_->show_overdraw_feedback) {
+    current_canvas_ = skia_output_surface_->RecordOverdrawForCurrentPaint();
+  }
 }
 
 void SkiaRenderer::BindFramebufferToTexture(
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc
index 2ca903a..d51fd17 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -372,28 +372,7 @@
   DCHECK(root_recorder_);
 
   current_paint_.emplace(&root_recorder_.value());
-
-  if (!debug_settings_->show_overdraw_feedback)
-    return current_paint_->recorder()->getCanvas();
-
-  DCHECK(!overdraw_surface_recorder_);
-  DCHECK(debug_settings_->show_overdraw_feedback);
-
-  nway_canvas_.emplace(characterization_.width(), characterization_.height());
-  nway_canvas_->addCanvas(current_paint_->recorder()->getCanvas());
-
-  SkSurfaceCharacterization characterization = CreateSkSurfaceCharacterization(
-      gfx::Size(characterization_.width(), characterization_.height()),
-      characterization_.colorType(),
-      /*mipmap=*/false, characterization_.refColorSpace(),
-      /*is_root_render_pass=*/false, /*is_overlay=*/false);
-  if (characterization.isValid()) {
-    overdraw_surface_recorder_.emplace(characterization);
-    overdraw_canvas_.emplace((overdraw_surface_recorder_->getCanvas()));
-    nway_canvas_->addCanvas(&overdraw_canvas_.value());
-  }
-
-  return &nway_canvas_.value();
+  return current_paint_->recorder()->getCanvas();
 }
 
 void SkiaOutputSurfaceImpl::MakePromiseSkImage(ImageContext* image_context) {
@@ -626,6 +605,30 @@
   return current_paint_->recorder()->getCanvas();
 }
 
+SkCanvas* SkiaOutputSurfaceImpl::RecordOverdrawForCurrentPaint() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  DCHECK(debug_settings_->show_overdraw_feedback);
+  DCHECK(current_paint_);
+  DCHECK(!overdraw_surface_recorder_);
+
+  nway_canvas_.emplace(characterization_.width(), characterization_.height());
+  nway_canvas_->addCanvas(current_paint_->recorder()->getCanvas());
+
+  SkSurfaceCharacterization characterization = CreateSkSurfaceCharacterization(
+      gfx::Size(characterization_.width(), characterization_.height()),
+      characterization_.colorType(),
+      /*mipmap=*/false, characterization_.refColorSpace(),
+      /*is_root_render_pass=*/false, /*is_overlay=*/false);
+  if (characterization.isValid()) {
+    overdraw_surface_recorder_.emplace(characterization);
+    overdraw_canvas_.emplace((overdraw_surface_recorder_->getCanvas()));
+    nway_canvas_->addCanvas(&overdraw_canvas_.value());
+  }
+
+  return &nway_canvas_.value();
+}
+
 void SkiaOutputSurfaceImpl::EndPaint(
     base::OnceClosure on_finished,
     base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb) {
@@ -633,6 +636,15 @@
   DCHECK(current_paint_);
   auto ddl = current_paint_->recorder()->detach();
 
+  sk_sp<SkDeferredDisplayList> overdraw_ddl;
+  if (overdraw_surface_recorder_) {
+    overdraw_ddl = overdraw_surface_recorder_->detach();
+    DCHECK(overdraw_ddl);
+    overdraw_canvas_.reset();
+    overdraw_surface_recorder_.reset();
+    nway_canvas_.reset();
+  }
+
   // If the current paint mailbox is empty, we are painting a frame, otherwise
   // we are painting a render pass. impl_on_gpu_ is released on the GPU thread
   // by a posted task from SkiaOutputSurfaceImpl::dtor, so it is safe to use
@@ -640,14 +652,6 @@
   if (current_paint_->mailbox().IsZero()) {
     // Draw on the root render pass.
     current_buffer_modified_ = true;
-    sk_sp<SkDeferredDisplayList> overdraw_ddl;
-    if (overdraw_surface_recorder_) {
-      overdraw_ddl = overdraw_surface_recorder_->detach();
-      DCHECK(overdraw_ddl);
-      overdraw_canvas_.reset();
-      overdraw_surface_recorder_.reset();
-    }
-    nway_canvas_.reset();
 
     auto task = base::BindOnce(
         &SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame,
@@ -662,9 +666,9 @@
     auto task = base::BindOnce(
         &SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass,
         base::Unretained(impl_on_gpu_.get()), current_paint_->mailbox(),
-        std::move(ddl), std::move(images_in_current_paint_),
-        resource_sync_tokens_, std::move(on_finished),
-        std::move(return_release_fence_cb));
+        std::move(ddl), std::move(overdraw_ddl),
+        std::move(images_in_current_paint_), resource_sync_tokens_,
+        std::move(on_finished), std::move(return_release_fence_cb));
     EnqueueGpuTask(std::move(task), std::move(resource_sync_tokens_),
                    /*make_current=*/true, /*need_framebuffer=*/false);
   }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h
index 2bf5bd4..f7ae89f 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -118,6 +118,7 @@
                                  sk_sp<SkColorSpace> color_space,
                                  bool is_overlay,
                                  const gpu::Mailbox& mailbox) override;
+  SkCanvas* RecordOverdrawForCurrentPaint() override;
   void EndPaint(base::OnceClosure on_finished,
                 base::OnceCallback<void(gfx::GpuFenceHandle)>
                     return_release_fence_cb) override;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 702b77f..f10f27db 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -410,6 +410,24 @@
   }
 }
 
+void SkiaOutputSurfaceImplOnGpu::DrawOverdraw(
+    sk_sp<SkDeferredDisplayList> overdraw_ddl,
+    SkCanvas& canvas) {
+  DCHECK(overdraw_ddl);
+
+  sk_sp<SkSurface> overdraw_surface = SkSurface::MakeRenderTarget(
+      gr_context(), overdraw_ddl->characterization(), SkBudgeted::kNo);
+  overdraw_surface->draw(overdraw_ddl);
+  destroy_after_swap_.push_back(std::move(overdraw_ddl));
+
+  SkPaint paint;
+  sk_sp<SkImage> overdraw_image = overdraw_surface->makeImageSnapshot();
+
+  paint.setColorFilter(SkiaHelper::MakeOverdrawColorFilter());
+  // TODO(xing.xu): move below to the thread where skia record happens.
+  canvas.drawImage(overdraw_image.get(), 0, 0, SkSamplingOptions(), &paint);
+}
+
 void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame(
     sk_sp<SkDeferredDisplayList> ddl,
     sk_sp<SkDeferredDisplayList> overdraw_ddl,
@@ -479,19 +497,8 @@
     destroy_after_swap_.emplace_back(std::move(ddl));
 
     if (overdraw_ddl) {
-      sk_sp<SkSurface> overdraw_surface = SkSurface::MakeRenderTarget(
-          gr_context(), overdraw_ddl->characterization(), SkBudgeted::kNo);
-      overdraw_surface->draw(overdraw_ddl);
-      destroy_after_swap_.emplace_back(std::move(overdraw_ddl));
-
-      SkPaint paint;
-      sk_sp<SkImage> overdraw_image = overdraw_surface->makeImageSnapshot();
-
-      sk_sp<SkColorFilter> colorFilter = SkiaHelper::MakeOverdrawColorFilter();
-      paint.setColorFilter(colorFilter);
-      // TODO(xing.xu): move below to the thread where skia record happens.
-      scoped_output_device_paint_->GetCanvas()->drawImage(
-          overdraw_image.get(), 0, 0, SkSamplingOptions(), &paint);
+      DrawOverdraw(std::move(overdraw_ddl),
+                   *scoped_output_device_paint_->GetCanvas());
     }
 
     auto end_paint_semaphores =
@@ -585,6 +592,7 @@
 void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
     const gpu::Mailbox& mailbox,
     sk_sp<SkDeferredDisplayList> ddl,
+    sk_sp<SkDeferredDisplayList> overdraw_ddl,
     std::vector<ImageContextImpl*> image_contexts,
     std::vector<gpu::SyncToken> sync_tokens,
     base::OnceClosure on_finished,
@@ -639,6 +647,10 @@
     backing_representation->SetCleared();
     destroy_after_swap_.emplace_back(std::move(ddl));
 
+    if (overdraw_ddl) {
+      DrawOverdraw(std::move(overdraw_ddl), *surface->getCanvas());
+    }
+
 #if BUILDFLAG(ENABLE_VULKAN)
     // Semaphores for release fences for vulkan should be created before flush.
     if (!return_release_fence_cb.is_null() && is_using_vulkan()) {
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
index 9b275500..47a81e17 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -172,6 +172,7 @@
   void FinishPaintRenderPass(
       const gpu::Mailbox& mailbox,
       sk_sp<SkDeferredDisplayList> ddl,
+      sk_sp<SkDeferredDisplayList> overdraw_ddl,
       std::vector<ImageContextImpl*> image_contexts,
       std::vector<gpu::SyncToken> sync_tokens,
       base::OnceClosure on_finished,
@@ -399,6 +400,10 @@
 #endif
   gfx::GpuFenceHandle CreateReleaseFenceForGL();
 
+  // Draws `overdraw_ddl` to the target `canvas`.
+  void DrawOverdraw(sk_sp<SkDeferredDisplayList> overdraw_ddl,
+                    SkCanvas& canvas);
+
   class ReleaseCurrent {
    public:
     ReleaseCurrent(scoped_refptr<gl::GLSurface> gl_surface,
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
index c9f2c23..648d66a 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -393,10 +393,14 @@
   DCHECK_GE(crop_version, crop_version_);
 
   target_ = target;
-  crop_version_ = crop_version;
 
-  // TODO(crbug.com/1266378): Use |crop_version_| to annotate frames delivered
-  // or dropped.
+  if (crop_version_ != crop_version) {
+    crop_version_ = crop_version;
+
+    if (consumer_) {
+      consumer_->OnNewCropVersion(crop_version);
+    }
+  }
 
   ResolveTarget();
 }
@@ -1318,11 +1322,16 @@
     scoped_refptr<VideoFrame> frame) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
+  // TODO(crbug.com/1332628): When capture fails because the crop version has
+  // changed, expedite the capture/delivery of a new frame.
+  const bool capture_was_successful =
+      frame && frame->metadata().crop_version == crop_version_;
   // The Oracle has the final say in whether frame delivery will proceed. It
   // also rewrites the media timestamp in terms of the smooth flow of the
   // original source content.
   base::TimeTicks media_ticks;
-  if (!oracle_->CompleteCapture(oracle_frame_number, !!frame, &media_ticks)) {
+  if (!oracle_->CompleteCapture(oracle_frame_number, capture_was_successful,
+                                &media_ticks)) {
     // Note: The following is used by
     // chrome/browser/media/cast_mirroring_performance_browsertest.cc, in
     // addition to the usual runtime tracing
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
index 20565f12..9144fa5 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -130,6 +130,7 @@
   MockConsumer() {}
 
   MOCK_METHOD0(OnFrameCapturedMock, void());
+  MOCK_METHOD1(OnNewCropVersion, void(uint32_t));
   MOCK_METHOD0(OnStopped, void());
   MOCK_METHOD1(OnLog, void(const std::string&));
 
diff --git a/components/viz/test/fake_skia_output_surface.cc b/components/viz/test/fake_skia_output_surface.cc
index b20aa542..eea760d 100644
--- a/components/viz/test/fake_skia_output_surface.cc
+++ b/components/viz/test/fake_skia_output_surface.cc
@@ -185,6 +185,11 @@
   return sk_surface->getCanvas();
 }
 
+SkCanvas* FakeSkiaOutputSurface::RecordOverdrawForCurrentPaint() {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
 void FakeSkiaOutputSurface::EndPaint(
     base::OnceClosure on_finished,
     base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb) {
diff --git a/components/viz/test/fake_skia_output_surface.h b/components/viz/test/fake_skia_output_surface.h
index 01b7f015..71bfd0c 100644
--- a/components/viz/test/fake_skia_output_surface.h
+++ b/components/viz/test/fake_skia_output_surface.h
@@ -72,6 +72,7 @@
                                  sk_sp<SkColorSpace> color_space,
                                  bool is_overlay,
                                  const gpu::Mailbox& mailbox) override;
+  SkCanvas* RecordOverdrawForCurrentPaint() override;
   void EndPaint(base::OnceClosure on_finished,
                 base::OnceCallback<void(gfx::GpuFenceHandle)>
                     return_release_fence_cb) override;
diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc
index 7e664a5..12ae17e5 100644
--- a/components/webdata/common/web_database_migration_unittest.cc
+++ b/components/webdata/common/web_database_migration_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <string>
 
+#include "base/containers/contains.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/guid.h"
@@ -35,11 +36,26 @@
 
 namespace {
 
-std::string RemoveQuotes(const std::string& has_quotes) {
-  std::string no_quotes;
-  // SQLite quotes: http://www.sqlite.org/lang_keywords.html
-  base::RemoveChars(has_quotes, "\"[]`", &no_quotes);
-  return no_quotes;
+// To make the comparison with golden files less whitespace sensitive:
+// - Remove SQLite quotes: http://www.sqlite.org/lang_keywords.html.
+// - Collapse multiple spaces into one.
+// - Ensure that there is no space before or after ',', '(' or ')'.
+std::string NormalizeSchemaForComparison(const std::string& schema) {
+  std::string normalized;
+  normalized.reserve(schema.size());
+  bool skip_following_spaces = false;
+  for (char c : schema) {
+    if (base::Contains("\"[]`", c))  // Quotes
+      continue;
+    if (c == ' ' && skip_following_spaces)
+      continue;
+    bool is_separator = base::Contains(",()", c);
+    if (is_separator && !normalized.empty() && normalized.back() == ' ')
+      normalized.pop_back();
+    normalized.push_back(c);
+    skip_following_spaces = c == ' ' || is_separator;
+  }
+  return normalized;
 }
 
 }  // anonymous namespace
@@ -143,16 +159,9 @@
   DoMigration();
   sql::Database connection;
   ASSERT_TRUE(connection.Open(GetDatabasePath()));
-  const std::string& expected_schema = RemoveQuotes(connection.GetSchema());
+  const std::string& expected_schema = connection.GetSchema();
   for (int i = WebDatabase::kDeprecatedVersionNumber + 1;
        i < kCurrentTestedVersionNumber; ++i) {
-    // We don't test version 52 because there's a slight discrepancy in the
-    // initialization code and the migration code (relating to schema
-    // formatting). Fixing the bug is possible, but would require updating every
-    // version_nn.sql file.
-    if (i == 52)
-      continue;
-
     connection.Raze();
     const base::FilePath& file_name = base::FilePath::FromUTF8Unsafe(
         "version_" + base::NumberToString(i) + ".sql");
@@ -160,7 +169,8 @@
         << "Failed to load " << file_name.MaybeAsASCII();
     DoMigration();
 
-    EXPECT_EQ(expected_schema, RemoveQuotes(connection.GetSchema()))
+    EXPECT_EQ(NormalizeSchemaForComparison(expected_schema),
+              NormalizeSchemaForComparison(connection.GetSchema()))
         << "For version " << i;
   }
 }
diff --git a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
index 6e4656b8..77b2058 100644
--- a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
+++ b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
@@ -2205,9 +2205,11 @@
 
 - (id)validRequestorForSendType:(NSString*)sendType
                      returnType:(NSString*)returnType {
+  NSString* const utf8Type = base::mac::CFToNSCast(kUTTypeUTF8PlainText);
+
   id requestor = nil;
-  BOOL sendTypeIsString = [sendType isEqual:NSStringPboardType];
-  BOOL returnTypeIsString = [returnType isEqual:NSStringPboardType];
+  BOOL sendTypeIsString = [sendType isEqualToString:utf8Type];
+  BOOL returnTypeIsString = [returnType isEqualToString:utf8Type];
   BOOL hasText = !_textSelectionRange.is_empty();
   BOOL takesText = _textInputType != ui::TEXT_INPUT_TYPE_NONE;
 
@@ -2316,21 +2318,24 @@
 @implementation RenderWidgetHostViewCocoa (NSServicesRequests)
 
 - (BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard types:(NSArray*)types {
-  // NB: The NSServicesMenuRequestor protocol has not (as of 10.14) been
+  // NB: The NSServicesMenuRequestor protocol has not (as of macOS 12) been
   // upgraded to request UTIs rather than obsolete PboardType constants. Handle
   // either for when it is upgraded.
-  DCHECK([types containsObject:NSStringPboardType] ||
-         [types containsObject:base::mac::CFToNSCast(kUTTypeUTF8PlainText)]);
-  if (_textSelectionRange.is_empty())
-    return NO;
+  bool wasAbleToWriteAtLeastOneType = false;
 
-  NSString* text = base::SysUTF16ToNSString([self selectedText]);
-  return [pboard writeObjects:@[ text ]];
+  if (([types containsObject:NSStringPboardType] ||
+       [types containsObject:base::mac::CFToNSCast(kUTTypeUTF8PlainText)]) &&
+      !_textSelectionRange.is_empty()) {
+    NSString* text = base::SysUTF16ToNSString([self selectedText]);
+    wasAbleToWriteAtLeastOneType |= [pboard writeObjects:@[ text ]];
+  }
+
+  return wasAbleToWriteAtLeastOneType;
 }
 
 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard {
-  NSArray* objects =
-      [pboard readObjectsForClasses:@[ [NSString class] ] options:0];
+  NSArray* objects = [pboard readObjectsForClasses:@[ [NSString class] ]
+                                           options:nil];
   if (![objects count])
     return NO;
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 67912374..89dd6c3 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1382,12 +1382,12 @@
     "portal/portal.h",
     "portal/portal_navigation_throttle.cc",
     "portal/portal_navigation_throttle.h",
-    "preloading_attempt_impl.cc",
-    "preloading_attempt_impl.h",
-    "preloading_data_impl.cc",
-    "preloading_data_impl.h",
-    "preloading_prediction.cc",
-    "preloading_prediction.h",
+    "preloading/preloading_attempt_impl.cc",
+    "preloading/preloading_attempt_impl.h",
+    "preloading/preloading_data_impl.cc",
+    "preloading/preloading_data_impl.h",
+    "preloading/preloading_prediction.cc",
+    "preloading/preloading_prediction.h",
     "prerender/prerender_attributes.cc",
     "prerender/prerender_attributes.h",
     "prerender/prerender_commit_deferring_condition.cc",
@@ -2174,8 +2174,6 @@
     "webtransport/web_transport_throttle_context.h",
     "webui/content_web_ui_configs.cc",
     "webui/content_web_ui_configs.h",
-    "webui/content_web_ui_controller_factory.cc",
-    "webui/content_web_ui_controller_factory.h",
     "webui/network_error_url_loader.cc",
     "webui/network_error_url_loader.h",
     "webui/shared_resources_data_source.cc",
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.h b/content/browser/accessibility/browser_accessibility_manager_mac.h
index 75ef598..bc103ac 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -78,6 +78,8 @@
   // Returns whether this page is a new tab page on Chrome.
   bool IsChromeNewTabPage();
 
+  bool ShouldFireLoadCompleteNotification();
+
   // Keeps track of any edits that have been made by the user during a tree
   // update. Used by NSAccessibilityValueChangedNotification.
   // Maps AXNode IDs to value attribute changes.
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm
index d6cb75b..f61b04b 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -21,6 +21,7 @@
 #include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
 #include "ui/accessibility/ax_role_properties.h"
 #include "ui/accessibility/platform/ax_private_webkit_constants_mac.h"
+#include "ui/base/cocoa/remote_accessibility_api.h"
 
 namespace {
 
@@ -250,25 +251,9 @@
       mac_notification = ui::NSAccessibilityLiveRegionCreatedNotification;
       break;
     case ui::AXEventGenerator::Event::LOAD_COMPLETE:
-      // On MacOS 10.15, firing AXLoadComplete causes focus to move to the
-      // webpage and read content, despite the "Automatically speak the webpage"
-      // checkbox in Voiceover utility being unchecked. The checkbox is
-      // unchecked by default in 10.15 so we don't fire AXLoadComplete events to
-      // support the default behavior.
-      if (base::mac::IsOS10_15())
+      if (!ShouldFireLoadCompleteNotification())
         return;
-
-      // |NSAccessibilityLoadCompleteNotification| should only be fired on the
-      // top document and when the document is not Chrome's new tab page.
-      if (IsRootTree() && !IsChromeNewTabPage()) {
-        mac_notification = ui::NSAccessibilityLoadCompleteNotification;
-      } else {
-        // Voiceover moves focus to the web content when it receives an
-        // AXLoadComplete event. On Chrome's new tab page, focus should stay
-        // in the omnibox, so we purposefully do not fire the AXLoadComplete
-        // event in this case.
-        return;
-      }
+      mac_notification = ui::NSAccessibilityLoadCompleteNotification;
       break;
     case ui::AXEventGenerator::Event::MENU_POPUP_END:
       // Calling NSAccessibilityPostNotification on a menu which is about to be
@@ -593,4 +578,66 @@
          url == GURL("chrome-search://local-ntp/local-ntp.html");
 }
 
+bool BrowserAccessibilityManagerMac::ShouldFireLoadCompleteNotification() {
+  // If it's not the top-level document, we shouldn't fire AXLoadComplete.
+  if (!IsRootTree())
+    return false;
+
+  // On MacOS 10.15, firing AXLoadComplete causes focus to move to the
+  // webpage and read content, despite the "Automatically speak the webpage"
+  // checkbox in Voiceover utility being unchecked. The checkbox is
+  // unchecked by default in 10.15 so we don't fire AXLoadComplete events to
+  // support the default behavior.
+  if (base::mac::IsOS10_15())
+    return false;
+
+  // Voiceover moves focus to the web content when it receives an
+  // AXLoadComplete event. On Chrome's new tab page, focus should stay
+  // in the omnibox, so we purposefully do not fire the AXLoadComplete
+  // event in this case.
+  if (IsChromeNewTabPage())
+    return false;
+
+  // We also check that the window is focused because VoiceOver responds
+  // to this notification by changing focus and possibly reading the entire
+  // page contents, sometimes even when the window is minimized or another
+  // Chrome window is active/focused.
+  id window = GetWindow();
+  if (!window)
+    return false;
+
+  if ([NSApp isActive])
+    return window == [NSApp accessibilityFocusedWindow];
+
+  // TODO(accessibility): We need a solution to the problem described below.
+  // If the window is NSAccessibilityRemoteUIElement, there are some challenges:
+  // 1. NSApp is the browser which spawned the PWA, and what it considers the
+  //    accessibilityFocusedWindow is the last browser window which was focused
+  //    prior to the PWA gaining focus; not the potentially-focused PWA window.
+  // 2. Unlike the BrowserNativeWidgetWindow, NSAccessibilityRemoteUIElement is
+  //    not an NSWindow and doesn't respond to the selector isKeyWindow. So we
+  //    cannot simply verify we have the key window for the currently running
+  //    application.
+  // 3. NSAccessibilityRemoteUIElement does not conform to the NSAccessibility
+  //    protocol, so we cannot ask it for any properties that might let us
+  //    verify this window is focused.
+  // 4. AppKit does not allow us to access the actual NSWindow instances of
+  //    other NSRunningApplications (i.e. the shim process); just window
+  //    information, which does not appear to include details regarding what
+  //    is active/focused.
+  // 5. Attempting to get at the accessibility tree of the shim process via
+  //    AXUIElementCreateApplication is possible, but the objects retrieved
+  //    in that fashion do not conform to the NSAccessibility protocol.
+  // For now we'll return true to preserve current behavior. Note, however,
+  // that this does not necessarily mean the event will be presented by
+  // VoiceOver in the same way it would present a normal browser window.
+  // This may be due to the issues described above, or the fact that one
+  // cannot ascend the accessibility tree all the way to the parent window
+  // from within the app shim content.
+  if ([window isKindOfClass:[NSAccessibilityRemoteUIElement class]])
+    return true;
+
+  return false;
+}
+
 }  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index ec9a17ec..b5a105c 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -186,7 +186,10 @@
       break;
     case ui::AXEventGenerator::Event::ALERT:
       FireWinAccessibilityEvent(EVENT_SYSTEM_ALERT, node);
-      FireUiaAccessibilityEvent(UIA_SystemAlertEventId, node);
+      // Generated 'ALERT' events come from role=alert nodes in the tree.
+      // These should just be treated as normal live region changed events,
+      // since we don't want web pages to be performing system-wide alerts.
+      FireUiaAccessibilityEvent(UIA_LiveRegionChangedEventId, node);
       break;
     case ui::AXEventGenerator::Event::ATOMIC_CHANGED:
       HandleAriaPropertiesChangedEvent(*node);
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 313c258..f93a4a6 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -317,13 +317,6 @@
                  "platform.";
     return;
   }
-#if BUILDFLAG(IS_FUCHSIA)
-  else {
-    LOG(INFO) << "No expectation file present, ignoring test on this "
-                 "platform.";
-    return;
-  }
-#endif
 
   // Get the test URL.
   GURL url(embedded_test_server()->GetURL(
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 369f8c77..464da90b 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1176,8 +1176,17 @@
   RunAriaTest(FILE_PATH_LITERAL("aria-owns-list.html"));
 }
 
+// TODO(crbug.com/1338211): test timeout on Fuchsia
+#if BUILDFLAG(IS_FUCHSIA)
+#define MAYBE_AccessibilityAriaOwnsWithRoleChange \
+  DISABLED_AccessibilityAriaOwnsWithRoleChange
+#else
+#define MAYBE_AccessibilityAriaOwnsWithRoleChange \
+  AccessibilityAriaOwnsWithRoleChange
+#endif  // BUILDFLAG(IS_FUCHSIA)
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
-                       AccessibilityAriaOwnsWithRoleChange) {
+                       MAYBE_AccessibilityAriaOwnsWithRoleChange) {
   RunAriaTest(FILE_PATH_LITERAL("aria-owns-with-role-change.html"));
 }
 
@@ -2755,7 +2764,15 @@
   RunHtmlTest(FILE_PATH_LITERAL("optgroup.html"));
 }
 
-IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityOpenModal) {
+// TODO(crbug.com/1338211): test timeouts on Fuchsia
+#if BUILDFLAG(IS_FUCHSIA)
+#define MAYBE_AccessibilityOpenModal DISABLED_AccessibilityOpenModal
+#else
+#define MAYBE_AccessibilityOpenModal AccessibilityOpenModal
+#endif  // BUILDFLAG(IS_FUCHSIA)
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+                       MAYBE_AccessibilityOpenModal) {
   RunHtmlTest(FILE_PATH_LITERAL("open-modal.html"));
 }
 
diff --git a/content/browser/aggregation_service/aggregation_service_storage_sql.cc b/content/browser/aggregation_service/aggregation_service_storage_sql.cc
index 5fb3a61..29b4b07 100644
--- a/content/browser/aggregation_service/aggregation_service_storage_sql.cc
+++ b/content/browser/aggregation_service/aggregation_service_storage_sql.cc
@@ -25,6 +25,7 @@
 #include "content/browser/aggregation_service/public_key.h"
 #include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "sql/database.h"
+#include "sql/meta_table.h"
 #include "sql/statement.h"
 #include "sql/transaction.h"
 #include "url/gurl.h"
@@ -437,19 +438,14 @@
   if (current_version == kCurrentVersionNumber)
     return true;
 
-  if (current_version <= kDeprecatedVersionNumber) {
-    // Note that this also razes the meta table, so it will need to be
-    // initialized again.
+  if (current_version <= kDeprecatedVersionNumber ||
+      meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
+    // The database version is either deprecated or is too new to be used. For
+    // the second case, the DB will never work until Chrome is re-upgraded.
+    // Assume the user will continue using this Chrome version and raze the DB
+    // to get aggregation service storage working.
     db_.Raze();
-    return CreateSchema();
-  }
-
-  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
-    // In this case the database version is too new to be used. The DB will
-    // never work until Chrome is re-upgraded. Assume the user will continue
-    // using this Chrome version and raze the DB to get aggregation service
-    // storage working.
-    db_.Raze();
+    meta_table_.Reset();
     return CreateSchema();
   }
 
diff --git a/content/browser/aggregation_service/aggregation_service_storage_sql_unittest.cc b/content/browser/aggregation_service/aggregation_service_storage_sql_unittest.cc
index 957f6c2..c62e5a41 100644
--- a/content/browser/aggregation_service/aggregation_service_storage_sql_unittest.cc
+++ b/content/browser/aggregation_service/aggregation_service_storage_sql_unittest.cc
@@ -17,6 +17,7 @@
 #include "content/browser/aggregation_service/aggregation_service_test_utils.h"
 #include "content/browser/aggregation_service/public_key.h"
 #include "sql/database.h"
+#include "sql/meta_table.h"
 #include "sql/test/test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -343,6 +344,33 @@
       keys_2, storage_->GetPublicKeys(url_2)));
 }
 
+TEST_F(AggregationServiceStorageSqlTest, VersionTooNew_RazesDB) {
+  OpenDatabase();
+
+  GURL url(kExampleUrl);
+  PublicKeyset keyset(kExampleKeys, /*fetch_time=*/clock_.Now(),
+                      /*expiry_time=*/base::Time::Max());
+  storage_->SetPublicKeys(url, keyset);
+  EXPECT_EQ(storage_->GetPublicKeys(url).size(), 1u);
+  CloseDatabase();
+
+  {
+    sql::Database raw_db;
+    EXPECT_TRUE(raw_db.Open(db_path()));
+
+    sql::MetaTable meta;
+    // The values here are irrelevant, as the meta table already exists.
+    ASSERT_TRUE(meta.Init(&raw_db, /*version=*/1, /*compatible_version=*/1));
+
+    meta.SetVersionNumber(meta.GetVersionNumber() + 1);
+    meta.SetCompatibleVersionNumber(meta.GetCompatibleVersionNumber() + 1);
+  }
+
+  // The DB should be razed because the version is too new.
+  ASSERT_NO_FATAL_FAILURE(OpenDatabase());
+  EXPECT_TRUE(storage_->GetPublicKeys(url).empty());
+}
+
 TEST_F(AggregationServiceStorageSqlInMemoryTest,
        DatabaseInMemoryReopened_DataNotPersisted) {
   OpenDatabase();
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
index f2b01e88..8177b2e 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
@@ -477,6 +477,16 @@
     return;
   }
 
+  absl::optional<AttributionFilterData> not_filters =
+      AttributionFilterData::FromTriggerFilterValues(
+          std::move(data->not_filters->filter_values));
+  if (!not_filters.has_value()) {
+    RecordTriggerDataHandleStatus(DataHandleStatus::kInvalidData);
+    mojo::ReportBadMessage(
+        "AttributionDataHost: Invalid top-level negated filters.");
+    return;
+  }
+
   if (data->event_triggers.size() > blink::kMaxAttributionEventTriggerData) {
     RecordTriggerDataHandleStatus(DataHandleStatus::kInvalidData);
     mojo::ReportBadMessage("AttributionDataHost: Too many event triggers.");
@@ -541,6 +551,7 @@
   AttributionTrigger trigger(
       /*destination_origin=*/context.context_origin,
       std::move(data->reporting_origin), std::move(*filters),
+      std::move(*not_filters),
       data->debug_key ? absl::make_optional(data->debug_key->value)
                       : absl::nullopt,
       std::move(event_triggers), std::move(*aggregatable_trigger_data),
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
index bdd6b61..484bf58 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
@@ -495,6 +495,7 @@
 
     trigger_data->filters = blink::mojom::AttributionFilterData::New(
         AttributionFilterData::FilterValues({{"a", {"b"}}}));
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     trigger_data->event_triggers.push_back(blink::mojom::EventTriggerData::New(
         /*data=*/1,
@@ -565,6 +566,7 @@
         url::Origin::Create(GURL(test_case.reporting_origin));
 
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     data_host_remote.data_host->TriggerDataAvailable(std::move(trigger_data));
     data_host_remote.data_host.FlushForTesting();
@@ -608,6 +610,7 @@
 
     trigger_data->filters =
         blink::mojom::AttributionFilterData::New(test_case.AsMap());
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     data_host_remote->TriggerDataAvailable(std::move(trigger_data));
     data_host_remote.FlushForTesting();
@@ -647,6 +650,7 @@
         url::Origin::Create(GURL("https://reporter.example"));
 
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     trigger_data->event_triggers.push_back(blink::mojom::EventTriggerData::New(
         /*data=*/0,
@@ -693,6 +697,7 @@
         url::Origin::Create(GURL("https://reporter.example"));
 
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     trigger_data->event_triggers.push_back(blink::mojom::EventTriggerData::New(
         /*data=*/0,
@@ -757,6 +762,7 @@
     }
 
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     data_host_remote->TriggerDataAvailable(std::move(trigger_data));
     data_host_remote.FlushForTesting();
@@ -803,6 +809,7 @@
         url::Origin::Create(GURL("https://reporter.example"));
 
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     for (size_t i = 0; i < test_case.size; ++i) {
       trigger_data->aggregatable_trigger_data.push_back(
@@ -857,6 +864,7 @@
         url::Origin::Create(GURL("https://reporter.example"));
 
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     for (size_t i = 0; i < test_case.size; ++i) {
       trigger_data->aggregatable_values.emplace(base::NumberToString(i), 1);
@@ -910,6 +918,7 @@
     auto trigger_data = blink::mojom::AttributionTriggerData::New();
     trigger_data->reporting_origin = reporting_origin;
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     data_host_remote.data_host->TriggerDataAvailable(trigger_data.Clone());
     data_host_remote.data_host.FlushForTesting();
@@ -1000,6 +1009,7 @@
       auto trigger_data = blink::mojom::AttributionTriggerData::New();
       trigger_data->reporting_origin = reporting_origin;
       trigger_data->filters = blink::mojom::AttributionFilterData::New();
+      trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
       data_host_remote.data_host->TriggerDataAvailable(std::move(trigger_data));
       data_host_remote.data_host.FlushForTesting();
@@ -1150,6 +1160,7 @@
     trigger_data->reporting_origin =
         url::Origin::Create(GURL("https://report.test"));
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
     trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
     trigger_data_host_remote.FlushForTesting();
 
@@ -1205,6 +1216,7 @@
   trigger_data->reporting_origin =
       url::Origin::Create(GURL("https://report.test"));
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
   trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   trigger_data_host_remote.FlushForTesting();
 
@@ -1388,6 +1400,7 @@
   auto trigger_data = blink::mojom::AttributionTriggerData::New();
   trigger_data->reporting_origin = reporter;
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
   trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   trigger_data_host_remote.FlushForTesting();
 
@@ -1445,6 +1458,7 @@
   trigger_data->reporting_origin =
       url::Origin::Create(GURL("https://report.test"));
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
   trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   trigger_data_host_remote.FlushForTesting();
 
@@ -1490,6 +1504,7 @@
   trigger_data->reporting_origin =
       url::Origin::Create(GURL("https://report.test"));
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
   trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   trigger_data_host_remote.FlushForTesting();
 
@@ -1518,6 +1533,7 @@
   trigger_data->reporting_origin =
       url::Origin::Create(GURL("https://report.test"));
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
   trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   trigger_data_host_remote.FlushForTesting();
 
@@ -1543,6 +1559,7 @@
   trigger_data->reporting_origin =
       url::Origin::Create(GURL("https://report.test"));
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
   trigger_data_host_remote1->TriggerDataAvailable(trigger_data.Clone());
   trigger_data_host_remote2->TriggerDataAvailable(std::move(trigger_data));
@@ -1591,6 +1608,7 @@
   trigger_data->reporting_origin =
       url::Origin::Create(GURL("https://report.test"));
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
   trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   trigger_data_host_remote.FlushForTesting();
 
@@ -1643,6 +1661,7 @@
     auto trigger_data = blink::mojom::AttributionTriggerData::New();
     trigger_data->reporting_origin = std::move(reporting_origin);
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
     trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   };
 
@@ -1688,6 +1707,7 @@
   trigger_data->reporting_origin =
       url::Origin::Create(GURL("https://report.test"));
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
   trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   trigger_data_host_remote.FlushForTesting();
 
@@ -1728,6 +1748,7 @@
     auto trigger_data = blink::mojom::AttributionTriggerData::New();
     trigger_data->reporting_origin = std::move(reporting_origin);
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
     trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   };
 
@@ -1799,6 +1820,7 @@
   trigger_data->reporting_origin =
       url::Origin::Create(GURL("https://report2.test"));
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
   trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   trigger_data_host_remote.FlushForTesting();
 
@@ -1860,6 +1882,7 @@
     trigger_data->reporting_origin =
         url::Origin::Create(GURL("https://report2.test"));
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
     trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data));
     trigger_data_host_remote.FlushForTesting();
 
@@ -1928,6 +1951,7 @@
         url::Origin::Create(GURL("https://reporter.example"));
 
     trigger_data->filters = blink::mojom::AttributionFilterData::New();
+    trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
     trigger_data->aggregatable_values = test_case.values;
 
@@ -1958,6 +1982,7 @@
   auto trigger_data = blink::mojom::AttributionTriggerData::New();
   trigger_data->reporting_origin = url::Origin::Create(GURL("https://r.test"));
   trigger_data->filters = blink::mojom::AttributionFilterData::New();
+  trigger_data->not_filters = blink::mojom::AttributionFilterData::New();
 
   data_host_remote->TriggerDataAvailable(std::move(trigger_data));
   data_host_remote.FlushForTesting();
diff --git a/content/browser/attribution_reporting/attribution_internals.mojom b/content/browser/attribution_reporting/attribution_internals.mojom
index 1b4172e..97a368a 100644
--- a/content/browser/attribution_reporting/attribution_internals.mojom
+++ b/content/browser/attribution_reporting/attribution_internals.mojom
@@ -144,6 +144,7 @@
   url.mojom.Origin destination_origin;
   url.mojom.Origin reporting_origin;
   map<string, array<string>> filters;
+  map<string, array<string>> not_filters;
   DebugKey? debug_key;
   array<WebUIEventTriggerData> event_triggers;
   array<WebUIAggregatableTriggerData> aggregatable_triggers;
diff --git a/content/browser/attribution_reporting/attribution_internals_browsertest.cc b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
index 6310ca26..4569ece 100644
--- a/content/browser/attribution_reporting/attribution_internals_browsertest.cc
+++ b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
@@ -874,7 +874,8 @@
   const AttributionTrigger trigger(
       url::Origin::Create(GURL("https://d.test")),
       url::Origin::Create(GURL("https://r.test")),
-      AttributionFilterData::CreateForTesting({{"a", {"b"}}}),
+      /*filters=*/AttributionFilterData::CreateForTesting({{"a", {"b"}}}),
+      /*not_filters=*/AttributionFilterData::CreateForTesting({{"g", {"h"}}}),
       /*debug_key=*/1,
       {
           AttributionTrigger::EventTriggerData(
@@ -925,9 +926,10 @@
             table.children[0].children[4].innerText === "https://r.test" &&
             table.children[0].children[5].innerText === "1" &&
             table.children[0].children[6].innerText === '{ "a": [  "b" ]}' &&
-            table.children[0].children[7].innerText === $2 &&
-            table.children[0].children[8].innerText === $3 &&
-            table.children[0].children[9].innerText === '{ "a": 123, "b": 456}') {
+            table.children[0].children[7].innerText === '{ "g": [  "h" ]}' &&
+            table.children[0].children[8].innerText === $2 &&
+            table.children[0].children[9].innerText === $3 &&
+            table.children[0].children[10].innerText === '{ "a": 123, "b": 456}') {
           obs.disconnect();
           document.title = $1;
         }
diff --git a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
index 0970d40c2..8bdb195 100644
--- a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
+++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
@@ -416,6 +416,7 @@
   web_ui_trigger->destination_origin = trigger.destination_origin();
   web_ui_trigger->reporting_origin = trigger.reporting_origin();
   web_ui_trigger->filters = trigger.filters().filter_values();
+  web_ui_trigger->not_filters = trigger.not_filters().filter_values();
   web_ui_trigger->debug_key = WebUIDebugKey(trigger.debug_key());
   web_ui_trigger->event_level_status =
       GetWebUITriggerStatus(result.event_level_status());
diff --git a/content/browser/attribution_reporting/attribution_src_browsertest.cc b/content/browser/attribution_reporting/attribution_src_browsertest.cc
index 7035e0a..08c71e6 100644
--- a/content/browser/attribution_reporting/attribution_src_browsertest.cc
+++ b/content/browser/attribution_reporting/attribution_src_browsertest.cc
@@ -378,6 +378,81 @@
             "/register_source?a=b&c=d");
 }
 
+// See crbug.com/1338698
+IN_PROC_BROWSER_TEST_F(AttributionSrcBrowserTest,
+                       AttributionSrcWindowOpen_RetainsOriginalURLCase) {
+  // Create a separate server as we cannot register a `ControllableHttpResponse`
+  // after the server starts.
+  auto https_server = std::make_unique<net::EmbeddedTestServer>(
+      net::EmbeddedTestServer::TYPE_HTTPS);
+  https_server->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
+  https_server->ServeFilesFromSourceDirectory(
+      "content/test/data/attribution_reporting");
+
+  auto register_response =
+      std::make_unique<net::test_server::ControllableHttpResponse>(
+          https_server.get(), "/register_source?a=B&C=d");
+  ASSERT_TRUE(https_server->Start());
+
+  GURL page_url =
+      https_server->GetURL("b.test", "/page_with_impression_creator.html");
+  EXPECT_TRUE(NavigateToURL(web_contents(), page_url));
+
+  TestNavigationObserver observer(web_contents());
+
+  // This attributionsrc will only be handled properly if the URL's original
+  // case is retained before being passed to the attributionsrc loader.
+  EXPECT_TRUE(ExecJs(web_contents(), R"(
+  window.open("page_with_conversion_redirect.html", "_top",
+  "attributionsrc=register_source%3Fa%3DB%26C%3Dd");)"));
+
+  register_response->WaitForRequest();
+  register_response->Done();
+
+  // TODO(crbug.com/1322525): Remove this once we use a pure mock.
+  observer.Wait();
+
+  EXPECT_EQ(register_response->http_request()->relative_url,
+            "/register_source?a=B&C=d");
+}
+
+// See crbug.com/1338698
+IN_PROC_BROWSER_TEST_F(AttributionSrcBrowserTest,
+                       AttributionSrcWindowOpen_NonAsciiUrl) {
+  // Create a separate server as we cannot register a `ControllableHttpResponse`
+  // after the server starts.
+  auto https_server = std::make_unique<net::EmbeddedTestServer>(
+      net::EmbeddedTestServer::TYPE_HTTPS);
+  https_server->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
+  https_server->ServeFilesFromSourceDirectory(
+      "content/test/data/attribution_reporting");
+
+  auto register_response =
+      std::make_unique<net::test_server::ControllableHttpResponse>(
+          https_server.get(), "/%F0%9F%98%80");
+  ASSERT_TRUE(https_server->Start());
+
+  GURL page_url =
+      https_server->GetURL("b.test", "/page_with_impression_creator.html");
+  EXPECT_TRUE(NavigateToURL(web_contents(), page_url));
+
+  TestNavigationObserver observer(web_contents());
+
+  // Ensure that the special handling of the original case for attributionsrc
+  // features works with non-ASCII characters.
+  EXPECT_TRUE(ExecJs(web_contents(), R"(
+  window.open("page_with_conversion_redirect.html", "_top",
+  "attributionsrc=😀");)"));
+
+  register_response->WaitForRequest();
+  register_response->Done();
+
+  // TODO(crbug.com/1322525): Remove this once we use a pure mock.
+  observer.Wait();
+
+  EXPECT_EQ(register_response->http_request()->relative_url, "/%F0%9F%98%80");
+}
+
 IN_PROC_BROWSER_TEST_F(
     AttributionSrcBrowserTest,
     AttributionSrcWindowOpenNoUserGesture_SourceNotRegistered) {
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate.h b/content/browser/attribution_reporting/attribution_storage_delegate.h
index bbdd5d9..005b05d 100644
--- a/content/browser/attribution_reporting/attribution_storage_delegate.h
+++ b/content/browser/attribution_reporting/attribution_storage_delegate.h
@@ -88,11 +88,11 @@
   virtual int GetMaxSourcesPerOrigin() const = 0;
 
   // Returns the maximum number of reports of the given type that can be in
-  // storage at any time for an attribution top-level origin. Note that since
+  // storage at any time for a destination site. Note that since
   // reporting origins are the actual entities that invoke attribution
   // registration, we could consider changing this limit to be keyed by an
   // <attribution origin, reporting origin> tuple.
-  virtual int GetMaxAttributionsPerOrigin(
+  virtual int GetMaxReportsPerDestination(
       AttributionReport::ReportType) const = 0;
 
   // Returns the maximum number of distinct attribution destinations that can
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc b/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
index a657e5b..44a01c3 100644
--- a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
+++ b/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
@@ -94,7 +94,7 @@
   return 1024;
 }
 
-int AttributionStorageDelegateImpl::GetMaxAttributionsPerOrigin(
+int AttributionStorageDelegateImpl::GetMaxReportsPerDestination(
     AttributionReport::ReportType) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return 1024;
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl.h b/content/browser/attribution_reporting/attribution_storage_delegate_impl.h
index 7abc5a3..44e1cb8d 100644
--- a/content/browser/attribution_reporting/attribution_storage_delegate_impl.h
+++ b/content/browser/attribution_reporting/attribution_storage_delegate_impl.h
@@ -52,7 +52,7 @@
   int GetMaxAttributionsPerSource(
       AttributionSourceType source_type) const override;
   int GetMaxSourcesPerOrigin() const override;
-  int GetMaxAttributionsPerOrigin(AttributionReport::ReportType) const override;
+  int GetMaxReportsPerDestination(AttributionReport::ReportType) const override;
   int GetMaxDestinationsPerSourceSiteReportingOrigin() const override;
   RateLimitConfig GetRateLimits() const override;
   base::TimeDelta GetDeleteExpiredSourcesFrequency() const override;
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc
index 646d5ca..25cf6cd 100644
--- a/content/browser/attribution_reporting/attribution_storage_sql.cc
+++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -819,8 +819,7 @@
 
   const bool top_level_filters_match = AttributionFiltersMatch(
       source_to_attribute->source.common_info().filter_data(),
-      trigger.filters(),
-      /*trigger_not_filters=*/AttributionFilterData());
+      trigger.filters(), trigger.not_filters());
 
   AttributionInfo attribution_info(std::move(source_to_attribute->source),
                                    trigger_time, trigger.debug_key());
@@ -1825,9 +1824,10 @@
   if (!statement.Step())
     return ConversionCapacityStatus::kError;
   int64_t count = statement.ColumnInt64(0);
-  return count < delegate_->GetMaxAttributionsPerOrigin(report_type)
-             ? ConversionCapacityStatus::kHasCapacity
-             : ConversionCapacityStatus::kNoCapacity;
+  int max = delegate_->GetMaxReportsPerDestination(report_type);
+  DCHECK_GT(max, 0);
+  return count < max ? ConversionCapacityStatus::kHasCapacity
+                     : ConversionCapacityStatus::kNoCapacity;
 }
 
 std::vector<StoredSource> AttributionStorageSql::GetActiveSources(int limit) {
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc b/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc
index 9c544ce..d5e7e73 100644
--- a/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc
@@ -542,9 +542,9 @@
   EXPECT_EQ(3u, rate_limit_rows);
 }
 
-TEST_F(AttributionStorageSqlTest, MaxAttributionsPerOrigin) {
+TEST_F(AttributionStorageSqlTest, MaxReportsPerDestination) {
   OpenDatabase();
-  delegate()->set_max_attributions_per_origin(
+  delegate()->set_max_reports_per_destination(
       AttributionReport::ReportType::kEventLevel, 2);
   storage()->StoreSource(SourceBuilder().Build());
   EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess,
diff --git a/content/browser/attribution_reporting/attribution_storage_unittest.cc b/content/browser/attribution_reporting/attribution_storage_unittest.cc
index 4e95342..f1d1222 100644
--- a/content/browser/attribution_reporting/attribution_storage_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_storage_unittest.cc
@@ -567,10 +567,10 @@
                           SourceEventIdIs(7u), SourceEventIdIs(11u)));
 }
 
-TEST_F(AttributionStorageTest, MaxEventLevelAttributionsPerOrigin) {
+TEST_F(AttributionStorageTest, MaxEventLevelReportsPerDestination) {
   SourceBuilder source_builder = TestAggregatableSourceProvider().GetBuilder();
 
-  delegate()->set_max_attributions_per_origin(
+  delegate()->set_max_reports_per_destination(
       AttributionReport::ReportType::kEventLevel, 1);
   storage()->StoreSource(source_builder.Build());
   storage()->StoreSource(source_builder.Build());
@@ -582,7 +582,7 @@
                     CreateReportAggregatableStatusIs(
                         AttributionTrigger::AggregatableResult::kSuccess)));
 
-  // Verify that MaxAttributionsPerOrigin is enforced.
+  // Verify that MaxReportsPerDestination is enforced.
   EXPECT_THAT(storage()->MaybeCreateAndStoreReport(
                   DefaultAggregatableTriggerBuilder().Build()),
               AllOf(CreateReportEventLevelStatusIs(
@@ -593,10 +593,10 @@
                     ReplacedEventLevelReportIs(absl::nullopt)));
 }
 
-TEST_F(AttributionStorageTest, MaxAggregatableAttributionsPerOrigin) {
+TEST_F(AttributionStorageTest, MaxAggregatableReportsPerDestination) {
   SourceBuilder source_builder = TestAggregatableSourceProvider().GetBuilder();
 
-  delegate()->set_max_attributions_per_origin(
+  delegate()->set_max_reports_per_destination(
       AttributionReport::ReportType::kAggregatableAttribution, 1);
   storage()->StoreSource(source_builder.Build());
   storage()->StoreSource(source_builder.Build());
@@ -608,7 +608,7 @@
                     CreateReportAggregatableStatusIs(
                         AttributionTrigger::AggregatableResult::kSuccess)));
 
-  // Verify that MaxAttributionsPerOrigin is enforced.
+  // Verify that MaxReportsPerDestination is enforced.
   EXPECT_THAT(storage()->MaybeCreateAndStoreReport(
                   DefaultAggregatableTriggerBuilder().Build()),
               AllOf(CreateReportEventLevelStatusIs(
@@ -2262,6 +2262,7 @@
             MaybeCreateAndStoreEventLevelReport(AttributionTrigger(
                 origin, origin,
                 /*filters=*/AttributionFilterData(),
+                /*not_filters=*/AttributionFilterData(),
                 /*debug_key=*/absl::nullopt,
                 {AttributionTrigger::EventTriggerData(
                     /*data=*/11,
@@ -2352,6 +2353,7 @@
             MaybeCreateAndStoreEventLevelReport(AttributionTrigger(
                 origin, origin,
                 /*filters=*/AttributionFilterData(),
+                /*not_filters=*/AttributionFilterData(),
                 /*debug_key=*/absl::nullopt, event_triggers,
                 /*aggregatable_trigger_data=*/{},
                 /*aggregatable_values=*/AttributionAggregatableValues())));
@@ -2391,6 +2393,7 @@
                               *AttributionFilterData::FromTriggerFilterValues({
                                   {"abc", {"456"}},
                               }),
+                              /*not_filters=*/AttributionFilterData(),
                               /*debug_key=*/absl::nullopt,
                               /*event_triggers=*/{}, aggregatable_trigger_data,
                               aggregatable_values);
@@ -2400,10 +2403,18 @@
                               *AttributionFilterData::FromTriggerFilterValues({
                                   {"abc", {"123"}},
                               }),
+                              /*not_filters=*/AttributionFilterData(),
                               /*debug_key=*/absl::nullopt,
-                              /*event_triggers=*/{},
-                              std::move(aggregatable_trigger_data),
-                              std::move(aggregatable_values));
+                              /*event_triggers=*/{}, aggregatable_trigger_data,
+                              aggregatable_values);
+
+  AttributionTrigger trigger3(
+      origin, origin,
+      /*filters=*/AttributionFilterData(),
+      /*not_filters=*/
+      AttributionFilterData::ForSourceType(AttributionSourceType::kNavigation),
+      /*debug_key=*/absl::nullopt,
+      /*event_triggers=*/{}, aggregatable_trigger_data, aggregatable_values);
 
   EXPECT_THAT(storage()->MaybeCreateAndStoreReport(trigger1),
               AllOf(CreateReportEventLevelStatusIs(
@@ -2412,6 +2423,7 @@
                     CreateReportAggregatableStatusIs(
                         AttributionTrigger::AggregatableResult::
                             kNoMatchingSourceFilterData)));
+
   EXPECT_THAT(
       storage()->MaybeCreateAndStoreReport(trigger2),
       AllOf(
@@ -2419,6 +2431,14 @@
               AttributionTrigger::EventLevelResult::kNoMatchingConfigurations),
           CreateReportAggregatableStatusIs(
               AttributionTrigger::AggregatableResult::kSuccess)));
+
+  EXPECT_THAT(storage()->MaybeCreateAndStoreReport(trigger3),
+              AllOf(CreateReportEventLevelStatusIs(
+                        AttributionTrigger::EventLevelResult::
+                            kNoMatchingSourceFilterData),
+                    CreateReportAggregatableStatusIs(
+                        AttributionTrigger::AggregatableResult::
+                            kNoMatchingSourceFilterData)));
 }
 
 TEST_F(AttributionStorageTest,
diff --git a/content/browser/attribution_reporting/attribution_test_utils.cc b/content/browser/attribution_reporting/attribution_test_utils.cc
index 6991e240..452dbe2a 100644
--- a/content/browser/attribution_reporting/attribution_test_utils.cc
+++ b/content/browser/attribution_reporting/attribution_test_utils.cc
@@ -151,14 +151,14 @@
   return max_sources_per_origin_;
 }
 
-int ConfigurableStorageDelegate::GetMaxAttributionsPerOrigin(
+int ConfigurableStorageDelegate::GetMaxReportsPerDestination(
     AttributionReport::ReportType report_type) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   switch (report_type) {
     case AttributionReport::ReportType::kEventLevel:
-      return max_event_level_attributions_per_origin_;
+      return max_event_level_reports_per_destination_;
     case AttributionReport::ReportType::kAggregatableAttribution:
-      return max_aggregatable_attributions_per_origin_;
+      return max_aggregatable_reports_per_destination_;
   }
 }
 
@@ -264,16 +264,16 @@
   max_sources_per_origin_ = max;
 }
 
-void ConfigurableStorageDelegate::set_max_attributions_per_origin(
+void ConfigurableStorageDelegate::set_max_reports_per_destination(
     AttributionReport::ReportType report_type,
     int max) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   switch (report_type) {
     case AttributionReport::ReportType::kEventLevel:
-      max_event_level_attributions_per_origin_ = max;
+      max_event_level_reports_per_destination_ = max;
       break;
     case AttributionReport::ReportType::kAggregatableAttribution:
-      max_aggregatable_attributions_per_origin_ = max;
+      max_aggregatable_reports_per_destination_ = max;
       break;
   }
 }
@@ -661,7 +661,8 @@
       /*not_filters=*/AttributionFilterData());
 
   return AttributionTrigger(destination_origin_, reporting_origin_,
-                            AttributionFilterData(), debug_key_,
+                            /*filters=*/AttributionFilterData(),
+                            /*not_filters=*/AttributionFilterData(), debug_key_,
                             std::move(event_triggers),
                             aggregatable_trigger_data_, aggregatable_values_);
 }
@@ -763,8 +764,8 @@
 bool operator==(const AttributionTrigger& a, const AttributionTrigger& b) {
   const auto tie = [](const AttributionTrigger& t) {
     return std::make_tuple(t.destination_origin(), t.reporting_origin(),
-                           t.filters(), t.debug_key(), t.event_triggers(),
-                           t.aggregatable_trigger_data(),
+                           t.filters(), t.not_filters(), t.debug_key(),
+                           t.event_triggers(), t.aggregatable_trigger_data(),
                            t.aggregatable_values());
   };
   return tie(a) == tie(b);
@@ -1048,7 +1049,8 @@
                          const AttributionTrigger& conversion) {
   out << "{destination_origin=" << conversion.destination_origin()
       << ",reporting_origin=" << conversion.reporting_origin()
-      << ",filters=" << conversion.filters() << ",debug_key="
+      << ",filters=" << conversion.filters()
+      << ",not_filters=" << conversion.not_filters() << ",debug_key="
       << (conversion.debug_key() ? base::NumberToString(*conversion.debug_key())
                                  : "null")
       << "event_triggers=[";
diff --git a/content/browser/attribution_reporting/attribution_test_utils.h b/content/browser/attribution_reporting/attribution_test_utils.h
index 7b3d829..9c13afc 100644
--- a/content/browser/attribution_reporting/attribution_test_utils.h
+++ b/content/browser/attribution_reporting/attribution_test_utils.h
@@ -204,7 +204,7 @@
   int GetMaxAttributionsPerSource(
       AttributionSourceType source_type) const override;
   int GetMaxSourcesPerOrigin() const override;
-  int GetMaxAttributionsPerOrigin(
+  int GetMaxReportsPerDestination(
       AttributionReport::ReportType report_type) const override;
   RateLimitConfig GetRateLimits() const override;
   int GetMaxDestinationsPerSourceSiteReportingOrigin() const override;
@@ -227,7 +227,7 @@
 
   void set_max_sources_per_origin(int max);
 
-  void set_max_attributions_per_origin(
+  void set_max_reports_per_destination(
       AttributionReport::ReportType report_type,
       int max);
 
@@ -267,8 +267,8 @@
  private:
   int max_attributions_per_source_ = INT_MAX;
   int max_sources_per_origin_ = INT_MAX;
-  int max_event_level_attributions_per_origin_ = INT_MAX;
-  int max_aggregatable_attributions_per_origin_ = INT_MAX;
+  int max_event_level_reports_per_destination_ = INT_MAX;
+  int max_aggregatable_reports_per_destination_ = INT_MAX;
   int max_destinations_per_source_site_reporting_origin_ = INT_MAX;
   int64_t aggregatable_budget_per_source_ = std::numeric_limits<int64_t>::max();
 
diff --git a/content/browser/attribution_reporting/attribution_trigger.cc b/content/browser/attribution_reporting/attribution_trigger.cc
index b0592c8..c5d025ed 100644
--- a/content/browser/attribution_reporting/attribution_trigger.cc
+++ b/content/browser/attribution_reporting/attribution_trigger.cc
@@ -28,6 +28,7 @@
     url::Origin destination_origin,
     url::Origin reporting_origin,
     AttributionFilterData filters,
+    AttributionFilterData not_filters,
     absl::optional<uint64_t> debug_key,
     std::vector<EventTriggerData> event_triggers,
     std::vector<AttributionAggregatableTriggerData> aggregatable_trigger_data,
@@ -35,6 +36,7 @@
     : destination_origin_(std::move(destination_origin)),
       reporting_origin_(std::move(reporting_origin)),
       filters_(std::move(filters)),
+      not_filters_(std::move(not_filters)),
       debug_key_(debug_key),
       event_triggers_(std::move(event_triggers)),
       aggregatable_trigger_data_(std::move(aggregatable_trigger_data)),
diff --git a/content/browser/attribution_reporting/attribution_trigger.h b/content/browser/attribution_reporting/attribution_trigger.h
index 94dcda73e..3766a24 100644
--- a/content/browser/attribution_reporting/attribution_trigger.h
+++ b/content/browser/attribution_reporting/attribution_trigger.h
@@ -104,6 +104,7 @@
       url::Origin destination_origin,
       url::Origin reporting_origin,
       AttributionFilterData filters,
+      AttributionFilterData not_filters,
       absl::optional<uint64_t> debug_key,
       std::vector<EventTriggerData> event_triggers,
       std::vector<AttributionAggregatableTriggerData> aggregatable_trigger_data,
@@ -121,6 +122,8 @@
 
   const AttributionFilterData& filters() const { return filters_; }
 
+  const AttributionFilterData& not_filters() const { return not_filters_; }
+
   absl::optional<uint64_t> debug_key() const { return debug_key_; }
 
   void ClearDebugKey() { debug_key_ = absl::nullopt; }
@@ -148,6 +151,8 @@
 
   AttributionFilterData filters_;
 
+  AttributionFilterData not_filters_;
+
   absl::optional<uint64_t> debug_key_;
 
   std::vector<EventTriggerData> event_triggers_;
diff --git a/content/browser/background_sync/background_sync_base_browsertest.cc b/content/browser/background_sync/background_sync_base_browsertest.cc
index 835a31b..7c1cf02 100644
--- a/content/browser/background_sync/background_sync_base_browsertest.cc
+++ b/content/browser/background_sync/background_sync_base_browsertest.cc
@@ -208,14 +208,15 @@
       StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
   uint32_t quota_storage_mask =
       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
-  GURL delete_origin = GURL();
+  blink::StorageKey delete_storage_key = blink::StorageKey();
   const base::Time delete_begin = base::Time();
   base::Time delete_end = base::Time::Max();
 
   base::RunLoop run_loop;
 
-  storage->ClearData(storage_partition_mask, quota_storage_mask, delete_origin,
-                     delete_begin, delete_end, run_loop.QuitClosure());
+  storage->ClearData(storage_partition_mask, quota_storage_mask,
+                     delete_storage_key, delete_begin, delete_end,
+                     run_loop.QuitClosure());
 
   run_loop.Run();
 }
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index 06b34e10..22af8b5 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -157,6 +157,15 @@
   partition_map->ForEach(std::move(callback));
 }
 
+void BrowserContext::DisposeStoragePartition(
+    StoragePartition* storage_partition) {
+  StoragePartitionImplMap* partition_map = impl()->storage_partition_map();
+  if (!partition_map)
+    return;
+
+  partition_map->DisposeInMemory(storage_partition);
+}
+
 size_t BrowserContext::GetStoragePartitionCount() {
   StoragePartitionImplMap* partition_map = impl()->storage_partition_map();
   return partition_map ? partition_map->size() : 0;
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index d0346093..6691ddf 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -96,7 +96,6 @@
 #include "content/browser/utility_process_host.h"
 #include "content/browser/webrtc/webrtc_internals.h"
 #include "content/browser/webui/content_web_ui_configs.h"
-#include "content/browser/webui/content_web_ui_controller_factory.h"
 #include "content/browser/webui/url_data_manager.h"
 #include "content/common/content_switches_internal.h"
 #include "content/common/skia_utils.h"
@@ -676,8 +675,6 @@
   {
     TRACE_EVENT0("startup",
                  "BrowserMainLoop::Subsystem:ContentWebUIController");
-    WebUIControllerFactory::RegisterFactory(
-        ContentWebUIControllerFactory::GetInstance());
     RegisterContentWebUIConfigs();
   }
 
diff --git a/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc b/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
index 6efa22c..036ce6d8 100644
--- a/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
+++ b/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
@@ -159,7 +159,7 @@
 
   void ClearData(uint32_t remove_mask,
                  uint32_t quota_storage_remove_mask,
-                 const GURL& storage_origin,
+                 const blink::StorageKey& storage_key,
                  const base::Time begin,
                  const base::Time end,
                  base::OnceClosure callback) override {
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc
index d7051ec..215ed5b 100644
--- a/content/browser/devtools/devtools_instrumentation.cc
+++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -25,6 +25,7 @@
 #include "content/browser/devtools/protocol/page_handler.h"
 #include "content/browser/devtools/protocol/security_handler.h"
 #include "content/browser/devtools/protocol/target_handler.h"
+#include "content/browser/devtools/protocol/tracing_handler.h"
 #include "content/browser/devtools/render_frame_devtools_agent_host.h"
 #include "content/browser/devtools/service_worker_devtools_agent_host.h"
 #include "content/browser/devtools/worker_devtools_agent_host.h"
@@ -1033,6 +1034,17 @@
   agent_host->DidCreateFencedFrame(fenced_frame);
 }
 
+void DidCreateProcessForAuctionWorklet(RenderFrameHostImpl* owner,
+                                       base::ProcessId pid) {
+  // TracingHandler lives on the very root, not local root.
+  // TODO(morlovich): This may not be right for fenced frames, though
+  // that should not currently matter.
+  FrameTreeNode* node = owner->GetMainFrame()->frame_tree_node();
+  if (!node)
+    return;
+  DispatchToAgents(node, &protocol::TracingHandler::AddProcess, pid);
+}
+
 void WillStartDragging(FrameTreeNode* main_frame_tree_node,
                        const blink::mojom::DragDataPtr drag_data,
                        blink::DragOperationsMask drag_operations_mask,
diff --git a/content/browser/devtools/devtools_instrumentation.h b/content/browser/devtools/devtools_instrumentation.h
index 1407ec64..6547c85e 100644
--- a/content/browser/devtools/devtools_instrumentation.h
+++ b/content/browser/devtools/devtools_instrumentation.h
@@ -245,6 +245,11 @@
     base::SafeRef<RenderFrameHostImpl> owner_render_frame_host,
     FencedFrame* fenced_frame);
 
+// Tells tracing that process `pid` is being used for an auction worklet
+// associated to `owner`.
+void DidCreateProcessForAuctionWorklet(RenderFrameHostImpl* owner,
+                                       base::ProcessId pid);
+
 void ReportCookieIssue(
     RenderFrameHostImpl* render_frame_host_impl,
     const network::mojom::CookieOrLineWithAccessResultPtr& excluded_cookie,
diff --git a/content/browser/devtools/devtools_video_consumer.h b/content/browser/devtools/devtools_video_consumer.h
index a8154429..c60de08 100644
--- a/content/browser/devtools/devtools_video_consumer.h
+++ b/content/browser/devtools/devtools_video_consumer.h
@@ -72,6 +72,7 @@
       const gfx::Rect& content_rect,
       mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
           callbacks) override;
+  void OnNewCropVersion(uint32_t crop_version) override {}
   void OnFrameWithEmptyRegionCapture() override {}
   void OnStopped() override;
   void OnLog(const std::string& /*message*/) override {}
diff --git a/content/browser/devtools/protocol/devtools_download_manager_delegate.cc b/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
index 0619bd0..bb29d906 100644
--- a/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
+++ b/content/browser/devtools/protocol/devtools_download_manager_delegate.cc
@@ -81,7 +81,6 @@
         download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
         download::DownloadItem::MixedContentStatus::UNKNOWN, empty_path,
         empty_path, std::string() /*mime_type*/,
-        absl::nullopt /*download_schedule*/,
         download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
     return true;
   }
@@ -164,7 +163,6 @@
       download::DownloadItem::MixedContentStatus::UNKNOWN,
       suggested_path.AddExtension(FILE_PATH_LITERAL(".crdownload")),
       suggested_path.BaseName(), std::string(),
-      absl::nullopt /*download_schedule*/,
       download::DOWNLOAD_INTERRUPT_REASON_NONE);
 }
 
diff --git a/content/browser/devtools/protocol/devtools_mhtml_helper.cc b/content/browser/devtools/protocol/devtools_mhtml_helper.cc
index 5d76cd5..ab46b2c 100644
--- a/content/browser/devtools/protocol/devtools_mhtml_helper.cc
+++ b/content/browser/devtools/protocol/devtools_mhtml_helper.cc
@@ -40,6 +40,7 @@
 void DevToolsMHTMLHelper::Capture(
     base::WeakPtr<PageHandler> page_handler,
     std::unique_ptr<PageHandler::CaptureSnapshotCallback> callback) {
+  DCHECK(!page_handler->AssureTopLevelActiveFrame().IsError());
   scoped_refptr<DevToolsMHTMLHelper> helper =
       new DevToolsMHTMLHelper(page_handler, std::move(callback));
   base::ThreadPool::PostTask(
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc
index d2e95db..2513d99 100644
--- a/content/browser/devtools/protocol/page_handler.cc
+++ b/content/browser/devtools/protocol/page_handler.cc
@@ -181,26 +181,11 @@
   *top_controls_visible_height = *frame.metadata().top_controls_visible_height;
 }
 
-Response AssureTopLevelActiveFrame(RenderFrameHost* host) {
-  if (!host)
-    return Response::ServerError(kErrorNotAttached);
-
-  if (host->GetParentOrOuterDocument())
-    return Response::ServerError(kCommandIsOnlyAvailableAtTopTarget);
-
-  if (!host->IsActive())
-    return Response::ServerError(kErrorInactivePage);
-
-  return Response::Success();
-}
-
 template <typename ProtocolCallback>
 bool CanExecuteGlobalCommands(
-    RenderFrameHost* host,
+    PageHandler* page_handler,
     const std::unique_ptr<ProtocolCallback>& callback) {
-  if (!host)
-    return true;
-  Response response = AssureTopLevelActiveFrame(host);
+  Response response = page_handler->AssureTopLevelActiveFrame();
   if (!response.IsError())
     return true;
   callback->sendFailure(response);
@@ -392,7 +377,7 @@
 
   if (!pending_dialog_.is_null()) {
     // Only a top level frame can have a dialog.
-    DCHECK(!AssureTopLevelActiveFrame(host_).IsError());
+    DCHECK(!AssureTopLevelActiveFrame().IsError());
 
     WebContents* web_contents = WebContents::FromRenderFrameHost(host_);
     // Leave dialog hanging if there is a manager that can take care of it,
@@ -424,7 +409,7 @@
 }
 
 Response PageHandler::Close() {
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError())
     return response;
 
@@ -436,7 +421,7 @@
 void PageHandler::Reload(Maybe<bool> bypassCache,
                          Maybe<std::string> script_to_evaluate_on_load,
                          std::unique_ptr<ReloadCallback> callback) {
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError()) {
     callback->sendFailure(response);
     return;
@@ -707,7 +692,7 @@
 Response PageHandler::GetNavigationHistory(
     int* current_index,
     std::unique_ptr<NavigationEntries>* entries) {
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError())
     return response;
 
@@ -729,7 +714,7 @@
 }
 
 Response PageHandler::NavigateToHistoryEntry(int entry_id) {
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError())
     return response;
 
@@ -749,7 +734,7 @@
 }
 
 Response PageHandler::ResetNavigationHistory() {
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError())
     return response;
 
@@ -761,7 +746,7 @@
 void PageHandler::CaptureSnapshot(
     Maybe<std::string> format,
     std::unique_ptr<CaptureSnapshotCallback> callback) {
-  if (!CanExecuteGlobalCommands(host_, callback))
+  if (!CanExecuteGlobalCommands(this, callback))
     return;
   std::string snapshot_format = format.fromMaybe(kMhtml);
   if (snapshot_format != kMhtml) {
@@ -783,7 +768,7 @@
     callback->sendFailure(Response::InternalError());
     return;
   }
-  if (!CanExecuteGlobalCommands(host_, callback))
+  if (!CanExecuteGlobalCommands(this, callback))
     return;
   if (clip.isJust()) {
     if (clip.fromJust()->GetWidth() == 0) {
@@ -941,7 +926,7 @@
                                       Maybe<int> max_width,
                                       Maybe<int> max_height,
                                       Maybe<int> every_nth_frame) {
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError())
     return response;
   RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost();
@@ -1007,7 +992,7 @@
 
 Response PageHandler::HandleJavaScriptDialog(bool accept,
                                              Maybe<std::string> prompt_text) {
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError())
     return response;
 
@@ -1051,7 +1036,7 @@
   if (!browser_context)
     return Response::ServerError("Could not fetch browser context");
 
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError())
     return response;
   if (!browser_handler_)
@@ -1062,7 +1047,7 @@
 
 void PageHandler::GetAppManifest(
     std::unique_ptr<GetAppManifestCallback> callback) {
-  if (!CanExecuteGlobalCommands(host_, callback))
+  if (!CanExecuteGlobalCommands(this, callback))
     return;
   ManifestManagerHost::GetOrCreateForPage(host_->GetPage())
       ->RequestManifestDebugInfo(base::BindOnce(&PageHandler::GotManifest,
@@ -1283,7 +1268,7 @@
 }
 
 Response PageHandler::StopLoading() {
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError())
     return response;
 
@@ -1295,7 +1280,7 @@
 Response PageHandler::SetWebLifecycleState(const std::string& state) {
   // Inactive pages(e.g., a prerendered or back-forward cached page) should not
   // affect the state.
-  Response response = AssureTopLevelActiveFrame(host_);
+  Response response = AssureTopLevelActiveFrame();
   if (response.IsError())
     return response;
 
@@ -1965,6 +1950,19 @@
   return Response::ServerError("Permission denied");
 }
 
+Response PageHandler::AssureTopLevelActiveFrame() {
+  if (!host_)
+    return Response::ServerError(kErrorNotAttached);
+
+  if (host_->GetParentOrOuterDocument())
+    return Response::ServerError(kCommandIsOnlyAvailableAtTopTarget);
+
+  if (!host_->IsActive())
+    return Response::ServerError(kErrorInactivePage);
+
+  return Response::Success();
+}
+
 void PageHandler::BackForwardCacheNotUsed(
     const NavigationRequest* navigation,
     const BackForwardCacheCanStoreDocumentResult* result,
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h
index d74a47e..801bf36 100644
--- a/content/browser/devtools/protocol/page_handler.h
+++ b/content/browser/devtools/protocol/page_handler.h
@@ -180,6 +180,8 @@
   Response AddCompilationCache(const std::string& url,
                                const Binary& data) override;
 
+  Response AssureTopLevelActiveFrame();
+
  private:
   enum EncodingFormat { PNG, JPEG };
 
diff --git a/content/browser/devtools/protocol/storage_handler.cc b/content/browser/devtools/protocol/storage_handler.cc
index 42a35d27..b1afa3e0 100644
--- a/content/browser/devtools/protocol/storage_handler.cc
+++ b/content/browser/devtools/protocol/storage_handler.cc
@@ -417,7 +417,8 @@
 
   storage_partition_->ClearData(
       remove_mask, StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
-      GURL(origin), base::Time(), base::Time::Max(),
+      blink::StorageKey(url::Origin::Create(GURL(origin))), base::Time(),
+      base::Time::Max(),
       base::BindOnce(&ClearDataForOriginCallback::sendSuccess,
                      std::move(callback)));
 }
diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc
index 9c6402c..bb1f21a 100644
--- a/content/browser/devtools/protocol/tracing_handler.cc
+++ b/content/browser/devtools/protocol/tracing_handler.cc
@@ -782,6 +782,7 @@
       buffer_usage_reporting_interval.fromMaybe(0);
   did_initiate_recording_ = true;
   trace_config_ = std::move(trace_config);
+  pids_being_traced_.clear();
 
   GpuProcessHost* gpu_process_host =
       GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED,
@@ -820,21 +821,21 @@
     return;
 
   base::ProcessId browser_pid = base::Process::Current().Pid();
-  std::unordered_set<base::ProcessId> included_process_ids({browser_pid});
+  pids_being_traced_.insert(browser_pid);
 
   if (gpu_pid != base::kNullProcessId)
-    included_process_ids.insert(gpu_pid);
+    pids_being_traced_.insert(gpu_pid);
 
   if (new_render_frame_host)
-    AppendProcessId(new_render_frame_host, &included_process_ids);
+    AppendProcessId(new_render_frame_host, &pids_being_traced_);
 
   DCHECK(!frame_host_->GetParent());
   for (FrameTreeNode* node : frame_host_->frame_tree()->Nodes()) {
     if (RenderFrameHost* frame_host = node->current_frame_host())
-      AppendProcessId(frame_host, &included_process_ids);
+      AppendProcessId(frame_host, &pids_being_traced_);
   }
 
-  AddPidsToProcessFilter(included_process_ids, trace_config_);
+  AddPidsToProcessFilter(pids_being_traced_, trace_config_);
 }
 
 void TracingHandler::AppendProcessId(
@@ -851,13 +852,17 @@
 }
 
 void TracingHandler::OnProcessReady(RenderProcessHost* process_host) {
+  AddProcess(process_host->GetProcess().Pid());
+}
+
+void TracingHandler::AddProcess(base::ProcessId pid) {
   if (!did_initiate_recording_)
     return;
-  std::unordered_set<base::ProcessId> included_process_ids(
-      {process_host->GetProcess().Pid()});
-
-  AddPidsToProcessFilter(included_process_ids, trace_config_);
-  session_->ChangeTraceConfig(trace_config_);
+  if (!pids_being_traced_.insert(pid).second)
+    return;
+  AddPidsToProcessFilter({pid}, trace_config_);
+  if (session_)
+    session_->ChangeTraceConfig(trace_config_);
 }
 
 void TracingHandler::AttemptAdoptStartupSession(
diff --git a/content/browser/devtools/protocol/tracing_handler.h b/content/browser/devtools/protocol/tracing_handler.h
index 48ecb286..dfa2178 100644
--- a/content/browser/devtools/protocol/tracing_handler.h
+++ b/content/browser/devtools/protocol/tracing_handler.h
@@ -57,6 +57,9 @@
 
   static std::vector<TracingHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
 
+  // Adds an additional process to tracing configuration, if tracing is active.
+  void AddProcess(base::ProcessId pid);
+
   // DevToolsDomainHandler implementation.
   void SetRenderer(int process_host_id,
                    RenderFrameHostImpl* frame_host) override;
@@ -160,6 +163,7 @@
   std::unique_ptr<DevToolsVideoConsumer> video_consumer_;
   int number_of_screenshots_from_video_consumer_ = 0;
   perfetto::TraceConfig trace_config_;
+  std::unordered_set<base::ProcessId> pids_being_traced_;
   std::unique_ptr<PerfettoTracingSession> session_;
   base::WeakPtrFactory<TracingHandler> weak_factory_{this};
 
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 057c0ec..cdf8b27 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -193,8 +193,7 @@
         start_time, end_time, etag, last_modified, received_bytes, total_bytes,
         auto_resume_count, hash, state, danger_type, interrupt_reason,
         false /* paused */, false /* allow_metered */, opened, last_access_time,
-        transient, received_slices, reroute_info,
-        absl::nullopt /*download_schedule*/, download::kInvalidRange,
+        transient, received_slices, reroute_info, download::kInvalidRange,
         download::kInvalidRange, nullptr /* download_entry */);
   }
 
@@ -501,7 +500,6 @@
         download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
         download::DownloadItem::MixedContentStatus::UNKNOWN, target_path,
         base::FilePath(), std::string() /*mime_type*/,
-        absl::nullopt /*download_schedule*/,
         download::DOWNLOAD_INTERRUPT_REASON_NONE);
   }
 }
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index bdd7f8c..f812b1d 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -541,7 +541,6 @@
       const base::FilePath& intermediate_path,
       const base::FilePath& display_name,
       const std::string& mime_type,
-      absl::optional<download::DownloadSchedule> download_schedule,
       download::DownloadInterruptReason interrupt_reason) {
     callback_called_ = true;
     target_path_ = target_path;
@@ -549,7 +548,6 @@
     danger_type_ = danger_type;
     intermediate_path_ = intermediate_path;
     mime_type_ = mime_type;
-    download_schedule_ = std::move(download_schedule);
     interrupt_reason_ = interrupt_reason;
   }
 
@@ -587,7 +585,6 @@
   download::DownloadDangerType danger_type_;
   std::string mime_type_;
   base::FilePath intermediate_path_;
-  absl::optional<download::DownloadSchedule> download_schedule_;
   download::DownloadInterruptReason interrupt_reason_;
 
   std::vector<GURL> download_urls_;
@@ -797,9 +794,8 @@
       download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, false, false, false,
       base::Time::Now(), true,
       std::vector<download::DownloadItem::ReceivedSlice>(),
-      download::DownloadItemRerouteInfo(), absl::nullopt /*download_schedule*/,
-      download::kInvalidRange, download::kInvalidRange,
-      nullptr /* download_entry */);
+      download::DownloadItemRerouteInfo(), download::kInvalidRange,
+      download::kInvalidRange, nullptr /* download_entry */);
   in_progress_manager->AddDownloadItem(std::move(in_progress_item));
   SetInProgressDownloadManager(std::move(in_progress_manager));
   EXPECT_CALL(GetMockObserver(), OnDownloadCreated(download_manager_.get(), _))
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc
index 6483a33..988c0d60 100644
--- a/content/browser/download/save_package.cc
+++ b/content/browser/download/save_package.cc
@@ -1072,9 +1072,6 @@
 
       // Calculate the relative path for referring to the |save_item|.
       base::FilePath local_path(base::FilePath::kCurrentDirectory);
-      // TODO(crbug.com/1314749): With MPArch there may be multiple main frames
-      // and so IsMainFrame should not be used to identify subframes. Follow up
-      // to confirm correctness.
       if (target_tree_node->IsOutermostMainFrame()) {
         local_path = local_path.Append(saved_main_directory_path_.BaseName());
       }
diff --git a/content/browser/fenced_frame/fenced_frame_browsertest.cc b/content/browser/fenced_frame/fenced_frame_browsertest.cc
index 29317ba..61d493e0f 100644
--- a/content/browser/fenced_frame/fenced_frame_browsertest.cc
+++ b/content/browser/fenced_frame/fenced_frame_browsertest.cc
@@ -688,9 +688,10 @@
 }
 
 // Test that when the documents inside the fenced frame tree are loading, then
-// `WebContents::IsLoading`, `FrameTree::IsLoading`, and
-// `FrameTreeNode::IsLoading` should return true. Primary `FrameTree::IsLoading`
-// value should reflect the loading state of descendant fenced frames.
+// `WebContents::IsLoading`, `FrameTree::IsLoadingIncludingInnerFrameTrees`, and
+// `FrameTreeNode::IsLoading` should return true. Primary
+// `FrameTree::IsLoadingIncludingInnerFrameTrees` value should reflect the
+// loading state of descendant fenced frames.
 IN_PROC_BROWSER_TEST_F(FencedFrameBrowserTest, IsLoading) {
   // Create a HTTP response to control fenced frame navigation.
   net::test_server::ControllableHttpResponse fenced_frame_response(
@@ -719,14 +720,16 @@
       inner_fenced_frame_rfh->frame_tree_node();
   FrameTree* fenced_frame_tree = fenced_frame_root_node->frame_tree();
 
-  // All WebContents::IsLoading, FrameTree::IsLoading, and
-  // FrameTreeNode::IsLoading should return true when the fenced frame is
-  // loading along with primary FrameTree::IsLoading as we check for inner frame
-  // trees loading state.
+  // All WebContents::IsLoading, FrameTree::IsLoadingIncludingInnerFrameTrees,
+  // and FrameTreeNode::IsLoading should return true when the fenced frame is
+  // loading along with primary FrameTree::IsLoadingIncludingInnerFrameTrees as
+  // we check for inner frame trees loading state.
   EXPECT_TRUE(web_contents()->IsLoading());
-  EXPECT_TRUE(primary_main_frame_host()->frame_tree()->IsLoading());
+  EXPECT_TRUE(primary_main_frame_host()
+                  ->frame_tree()
+                  ->IsLoadingIncludingInnerFrameTrees());
   EXPECT_TRUE(fenced_frame_root_node->IsLoading());
-  EXPECT_TRUE(fenced_frame_tree->IsLoading());
+  EXPECT_TRUE(fenced_frame_tree->IsLoadingIncludingInnerFrameTrees());
 
   // Complete the fenced frame response and finish fenced frame navigation.
   fenced_frame_response.WaitForRequest();
@@ -741,9 +744,11 @@
   // frame stops loading.
   EXPECT_TRUE(WaitForLoadStop(web_contents()));
   EXPECT_FALSE(web_contents()->IsLoading());
-  EXPECT_FALSE(primary_main_frame_host()->frame_tree()->IsLoading());
+  EXPECT_FALSE(primary_main_frame_host()
+                   ->frame_tree()
+                   ->IsLoadingIncludingInnerFrameTrees());
   EXPECT_FALSE(fenced_frame_root_node->IsLoading());
-  EXPECT_FALSE(fenced_frame_tree->IsLoading());
+  EXPECT_FALSE(fenced_frame_tree->IsLoadingIncludingInnerFrameTrees());
 }
 
 // Test that when the documents inside the fenced frame tree are loading,
diff --git a/content/browser/interest_group/auction_runner_unittest.cc b/content/browser/interest_group/auction_runner_unittest.cc
index f536ecc3..19be0a2a 100644
--- a/content/browser/interest_group/auction_runner_unittest.cc
+++ b/content/browser/interest_group/auction_runner_unittest.cc
@@ -1693,6 +1693,8 @@
     StorageInterestGroup storage_group;
     storage_group.interest_group = blink::InterestGroup(
         base::Time::Max(), std::move(owner), std::move(name), /*priority=*/1.0,
+        /*execution_mode=*/
+        blink::InterestGroup::ExecutionMode::kCompatibilityMode,
         std::move(bidding_url),
         /*bidding_wasm_helper_url=*/absl::nullopt,
         /*update_url=*/absl::nullopt, std::move(trusted_bidding_signals_url),
diff --git a/content/browser/interest_group/debuggable_auction_worklet.cc b/content/browser/interest_group/debuggable_auction_worklet.cc
index 0e69303..c90c715 100644
--- a/content/browser/interest_group/debuggable_auction_worklet.cc
+++ b/content/browser/interest_group/debuggable_auction_worklet.cc
@@ -5,6 +5,7 @@
 #include "content/browser/interest_group/debuggable_auction_worklet.h"
 
 #include "base/strings/strcat.h"
+#include "content/browser/devtools/devtools_instrumentation.h"
 #include "content/browser/interest_group/debuggable_auction_worklet_tracker.h"
 #include "content/services/auction_worklet/public/mojom/bidder_worklet.mojom.h"
 #include "content/services/auction_worklet/public/mojom/seller_worklet.mojom.h"
@@ -32,11 +33,6 @@
   }
 }
 
-absl::optional<base::ProcessId> DebuggableAuctionWorklet::GetPid(
-    PidCallback callback) {
-  return process_handle_->GetPid(std::move(callback));
-}
-
 DebuggableAuctionWorklet::DebuggableAuctionWorklet(
     RenderFrameHostImpl* owning_frame,
     AuctionProcessManager::ProcessHandle* process_handle,
@@ -48,6 +44,7 @@
       worklet_(bidder_worklet) {
   DebuggableAuctionWorkletTracker::GetInstance()->NotifyCreated(
       this, should_pause_on_start_);
+  RequestPid();
 }
 
 DebuggableAuctionWorklet::DebuggableAuctionWorklet(
@@ -61,10 +58,24 @@
       worklet_(seller_worklet) {
   DebuggableAuctionWorkletTracker::GetInstance()->NotifyCreated(
       this, should_pause_on_start_);
+  RequestPid();
 }
 
 DebuggableAuctionWorklet::~DebuggableAuctionWorklet() {
   DebuggableAuctionWorkletTracker::GetInstance()->NotifyDestroyed(this);
 }
 
+void DebuggableAuctionWorklet::RequestPid() {
+  absl::optional<base::ProcessId> maybe_pid = process_handle_->GetPid(
+      base::BindOnce(&DebuggableAuctionWorklet::OnHavePid,
+                     weak_ptr_factory_.GetWeakPtr()));
+  if (maybe_pid.has_value())
+    OnHavePid(maybe_pid.value());
+}
+
+void DebuggableAuctionWorklet::OnHavePid(base::ProcessId process_id) {
+  devtools_instrumentation::DidCreateProcessForAuctionWorklet(owning_frame_,
+                                                              process_id);
+}
+
 }  // namespace content
diff --git a/content/browser/interest_group/debuggable_auction_worklet.h b/content/browser/interest_group/debuggable_auction_worklet.h
index 4c29dc2e..9a510e22c 100644
--- a/content/browser/interest_group/debuggable_auction_worklet.h
+++ b/content/browser/interest_group/debuggable_auction_worklet.h
@@ -47,11 +47,6 @@
   // Returns true if the worklet should start in the paused state.
   bool should_pause_on_start() const { return should_pause_on_start_; }
 
-  // Looks up the PID the worklet is running in. If it's available immediately,
-  // it's returned. If not, nullopt is returned and |callback| will be invoked
-  // when it's available.
-  absl::optional<base::ProcessId> GetPid(PidCallback callback);
-
  private:
   friend class AuctionRunner;
   friend class AuctionWorkletManager;
@@ -77,6 +72,9 @@
   // NotifyDestroyed() observers.
   ~DebuggableAuctionWorklet();
 
+  void RequestPid();
+  void OnHavePid(base::ProcessId process_id);
+
   const raw_ptr<RenderFrameHostImpl> owning_frame_ = nullptr;
   const raw_ptr<AuctionProcessManager::ProcessHandle> process_handle_ = nullptr;
   const GURL url_;
@@ -86,6 +84,8 @@
   absl::variant<auction_worklet::mojom::BidderWorklet*,
                 auction_worklet::mojom::SellerWorklet*>
       worklet_;
+
+  base::WeakPtrFactory<DebuggableAuctionWorklet> weak_ptr_factory_{this};
 };
 
 }  // namespace content
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index cbc631e..ac8e52ae 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -588,6 +588,8 @@
       const url::Origin& owner,
       const std::string& name,
       double priority,
+      blink::InterestGroup::ExecutionMode execution_mode =
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
       absl::optional<GURL> bidding_url = absl::nullopt,
       absl::optional<std::vector<blink::InterestGroup::Ad>> ads = absl::nullopt,
       absl::optional<std::vector<blink::InterestGroup::Ad>> ad_components =
@@ -595,7 +597,7 @@
       absl::optional<ToRenderFrameHost> execution_target = absl::nullopt) {
     return JoinInterestGroupAndVerify(
         blink::InterestGroup(
-            /*expiry=*/base::Time(), owner, name, priority,
+            /*expiry=*/base::Time(), owner, name, priority, execution_mode,
             std::move(bidding_url),
             /*bidding_wasm_helper_url=*/absl::nullopt,
             /*daily_update_url=*/absl::nullopt,
@@ -1102,7 +1104,8 @@
         JoinInterestGroupAndVerify(
             /*owner=*/url::Origin::Create(test_url),
             /*name=*/"cars",
-            /*priority=*/0.0,
+            /*priority=*/0.0, /*execution_mode=*/
+            blink::InterestGroup::ExecutionMode::kCompatibilityMode,
             /*bidding_url=*/
             https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
             /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}},
@@ -1328,6 +1331,8 @@
           /*owner=*/test_origin_a,
           /*name=*/"bicycles",
           /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/GURL("https://bid.a.test"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
           /*daily_update_url=*/absl::nullopt,
@@ -1352,6 +1357,8 @@
           /*owner=*/test_origin_a,
           /*name=*/"tricycles",
           /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/absl::nullopt,
           /*bidding_wasm_helper_url=*/absl::nullopt,
           /*daily_update_url=*/GURL("https://update.a.test"),
@@ -1375,7 +1382,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/test_origin_a,
                 /*name=*/"four-wheelers",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/absl::nullopt,
                 /*bidding_wasm_helper_url=*/absl::nullopt,
                 /*daily_update_url=*/absl::nullopt,
@@ -1419,7 +1427,8 @@
           /*expiry=*/base::Time::Now() + base::Seconds(300),
           /*owner=*/test_origin_d,
           /*name=*/"candy",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/absl::nullopt,
           /*bidding_wasm_helper_url=*/absl::nullopt,
           /*daily_update_url=*/absl::nullopt,
@@ -1482,11 +1491,14 @@
   RenderFrameHost* iframe = parent->child_at(0)->current_frame_host();
 
   // Both joining and leaving should work.
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          group_origin, kGroup,
-                          /*priority=*/0, /*bidding_url=*/absl::nullopt,
-                          /*ads=*/absl::nullopt,
-                          /*ad_components=*/absl::nullopt, iframe));
+  EXPECT_EQ(kSuccess,
+            JoinInterestGroupAndVerify(
+                group_origin, kGroup,
+                /*priority=*/0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+                /*bidding_url=*/absl::nullopt,
+                /*ads=*/absl::nullopt,
+                /*ad_components=*/absl::nullopt, iframe));
   EXPECT_EQ(kSuccess,
             LeaveInterestGroupAndVerify(group_origin, kGroup, iframe));
 }
@@ -1571,11 +1583,14 @@
   RenderFrameHost* iframe = parent->child_at(0)->current_frame_host();
 
   // Joining a group cross-origin should succeed.
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          allow_join_origin, kGroup,
-                          /*priority=*/0, /*bidding_url=*/absl::nullopt,
-                          /*ads=*/absl::nullopt,
-                          /*ad_components=*/absl::nullopt, iframe));
+  EXPECT_EQ(kSuccess,
+            JoinInterestGroupAndVerify(
+                allow_join_origin, kGroup,
+                /*priority=*/0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+                /*bidding_url=*/absl::nullopt,
+                /*ads=*/absl::nullopt,
+                /*ad_components=*/absl::nullopt, iframe));
 
   // Leaving the group should fail.
   EXPECT_EQ("NotAllowedError: Permission to leave interest group denied.",
@@ -1618,13 +1633,15 @@
   // Try to join an `allow_leave_origin` group from the iframe, which should
   // fail.
   EXPECT_EQ("NotAllowedError: Permission to join interest group denied.",
-            JoinInterestGroupAndVerify(allow_leave_origin, kJoinFailsGroup,
-                                       /*priority=*/0.0,
-                                       /*bidding_url=*/absl::nullopt,
-                                       /*ads=*/absl::nullopt,
-                                       /*ad_components=*/
-                                       absl::nullopt,
-                                       /*execution_target=*/iframe));
+            JoinInterestGroupAndVerify(
+                allow_leave_origin, kJoinFailsGroup,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+                /*bidding_url=*/absl::nullopt,
+                /*ads=*/absl::nullopt,
+                /*ad_components=*/
+                absl::nullopt,
+                /*execution_target=*/iframe));
 
   // Leaving the group from the iframe that was successfully joined earlier
   // should succeed.
@@ -2778,7 +2795,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin_a,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -2860,7 +2878,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL(test_url.host(),
                                 "/interest_group/bidding_logic.js"),
@@ -2916,7 +2935,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -3047,14 +3067,16 @@
                .spec());
   GURL expected_ad_url = https_server_->GetURL("c.test", "/echo?render_cars");
 
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/test_origin,
-                          /*name=*/"cars",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              "a.test", "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url, "{ad:'metadata', here:[1,2]}"}}}));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/test_origin,
+          /*name=*/"cars",
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          /*bidding_url=*/
+          https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
+          /*ads=*/{{{ad_url, "{ad:'metadata', here:[1,2]}"}}}));
 
   std::string auction_config = JsReplace(
       R"({
@@ -3105,7 +3127,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -3148,7 +3171,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test",
                                 "/interest_group/bidding_logic_use_wasm.js"),
@@ -3187,7 +3211,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/test_origin,
                 /*name=*/"winner",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
@@ -3204,7 +3229,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/test_origin,
                 /*name=*/"bikes",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
@@ -3221,7 +3247,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/test_origin,
                 /*name=*/"shoes",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
@@ -3323,7 +3350,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/test_origin,
                 /*name=*/"shoes",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test", "/interest_group/bidding_logic_loop_forever.js"),
@@ -3339,7 +3367,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/test_origin,
                 /*name=*/"bikes",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test", "/interest_group/bidding_logic_throws.js"),
@@ -3413,7 +3442,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -3552,7 +3582,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -3633,7 +3664,8 @@
               /*expiry=*/base::Time(),
               /*owner=*/test_origin,
               /*name=*/"cars",
-              /*priority=*/0.0,
+              /*priority=*/0.0, /*execution_mode=*/
+              blink::InterestGroup::ExecutionMode::kCompatibilityMode,
               /*bidding_url=*/
               https_server_->GetURL(
                   "a.test",
@@ -3661,7 +3693,8 @@
               /*expiry=*/base::Time(),
               /*owner=*/test_origin,
               /*name=*/"trucks",
-              /*priority=*/0.0,
+              /*priority=*/0.0, /*execution_mode=*/
+              blink::InterestGroup::ExecutionMode::kCompatibilityMode,
               /*bidding_url=*/
               https_server_->GetURL("a.test",
                                     "/interest_group/bidding_logic.js"),
@@ -3756,7 +3789,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -3814,7 +3848,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -3857,7 +3892,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/bidder_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL(kBidder, "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -3950,7 +3986,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4004,7 +4041,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/other_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL(
               kOtherHost,
@@ -4097,14 +4135,17 @@
 
   GURL ad_url = https_server_->GetURL(
       kAdHost, "/set-header?Supports-Loading-Mode: fenced-frame");
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/bidder_origin,
-                          /*name=*/"cars",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              kBidderHost, "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(kSuccess,
+            JoinInterestGroupAndVerify(
+                /*owner=*/bidder_origin,
+                /*name=*/"cars",
+                /*priority=*/0.0,
+                /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+                /*bidding_url=*/
+                https_server_->GetURL(kBidderHost,
+                                      "/interest_group/bidding_logic.js"),
+                /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
 
   GURL main_frame_url = https_server_->GetURL(
       kTopFrameHost,
@@ -4152,7 +4193,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/test_origin,
                 /*name=*/"cars",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
@@ -4170,7 +4212,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"bikes",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4188,7 +4231,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"shoes",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4235,6 +4279,8 @@
           /*owner=*/test_origin,
           /*name=*/"cars",
           /*priority=*/2.3,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4251,6 +4297,8 @@
           /*owner=*/test_origin,
           /*name=*/"bikes",
           /*priority=*/2.2,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4269,6 +4317,8 @@
           /*owner=*/test_origin,
           /*name=*/"shoes",
           /*priority=*/2.1,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4316,6 +4366,8 @@
                 /*owner=*/test_origin,
                 /*name=*/"cars",
                 /*priority=*/3,
+                /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
@@ -4334,6 +4386,8 @@
           /*owner=*/test_origin,
           /*name=*/"bikes",
           /*priority=*/2,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4352,6 +4406,8 @@
           /*owner=*/test_origin,
           /*name=*/"shoes",
           /*priority=*/1,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4370,6 +4426,8 @@
           /*owner=*/test_origin2,
           /*name=*/"cars",
           /*priority=*/3,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("b.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4386,6 +4444,8 @@
           /*owner=*/test_origin2,
           /*name=*/"bikes",
           /*priority=*/2,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("b.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4404,6 +4464,8 @@
           /*owner=*/test_origin2,
           /*name=*/"shoes",
           /*priority=*/1,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("b.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4457,6 +4519,8 @@
                 /*owner=*/test_origin,
                 /*name=*/"cars",
                 /*priority=*/3,
+                /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
@@ -4475,6 +4539,8 @@
           /*owner=*/test_origin,
           /*name=*/"bikes",
           /*priority=*/2,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4493,6 +4559,8 @@
           /*owner=*/test_origin,
           /*name=*/"shoes",
           /*priority=*/1,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4511,6 +4579,8 @@
           /*owner=*/test_origin2,
           /*name=*/"cars",
           /*priority=*/3,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("b.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4527,6 +4597,8 @@
           /*owner=*/test_origin2,
           /*name=*/"bikes",
           /*priority=*/2,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("b.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4545,6 +4617,8 @@
           /*owner=*/test_origin2,
           /*name=*/"shoes",
           /*priority=*/1,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("b.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4596,7 +4670,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/origin,
                 /*name=*/"cars",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
@@ -4619,7 +4694,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/origin2,
           /*name=*/"shoes",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("b.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -4760,7 +4836,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/origin_a,
                 /*name=*/"cars",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
@@ -4782,7 +4859,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/origin_b,
                 /*name=*/"shoes",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "b.test",
@@ -4834,7 +4912,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/origin_c,
                 /*name=*/"cars",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "c.test",
@@ -5020,7 +5099,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL(
               "a.test", "/interest_group/bidding_logic_invalid_ad_url.js"),
@@ -5058,15 +5138,18 @@
 
   GURL ad_url =
       https_server_->GetURL("c.test", "/fenced_frames/opaque_ads.html");
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/url::Origin::Create(test_url),
-                          /*name=*/"cars",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              "a.test", "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}},
-                          /*ad_components=*/absl::nullopt));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/url::Origin::Create(test_url),
+          /*name=*/"cars",
+          /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          /*bidding_url=*/
+          https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
+          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}},
+          /*ad_components=*/absl::nullopt));
 
   ASSERT_NO_FATAL_FAILURE(RunAuctionAndNavigateFencedFrame(
       ad_url, JsReplace(
@@ -5232,16 +5315,19 @@
 
   GURL ad_url =
       https_server_->GetURL("c.test", "/fenced_frames/opaque_ads.html");
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/url::Origin::Create(test_url),
-                          /*name=*/"cars",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              "a.test", "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}},
-                          /*ad_components=*/
-                          {{{ad_component_url, /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/url::Origin::Create(test_url),
+          /*name=*/"cars",
+          /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          /*bidding_url=*/
+          https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
+          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}},
+          /*ad_components=*/
+          {{{ad_component_url, /*metadata=*/absl::nullopt}}}));
 
   content::EvalJsResult urn_url_string = RunAuctionAndWait(JsReplace(
       R"(
@@ -5335,11 +5421,13 @@
 
   GURL ad_url =
       https_server_->GetURL("c.test", "/fenced_frames/opaque_ads.html");
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/url::Origin::Create(test_url),
-                          /*name=*/"cars", /*priority=*/0.0, bidding_url,
-                          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}},
-                          ad_components));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/url::Origin::Create(test_url),
+          /*name=*/"cars", /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode, bidding_url,
+          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}, ad_components));
 
   ASSERT_NO_FATAL_FAILURE(RunAuctionAndNavigateFencedFrame(
       ad_url, JsReplace(
@@ -5391,7 +5479,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test",
                                 "/interest_group/bidding_logic_throws.js"),
@@ -5429,14 +5518,17 @@
   url::Origin test_origin = url::Origin::Create(test_url);
   GURL ad_url = https_server_->GetURL("c.test", "/echo?render_cars");
 
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/test_origin,
-                          /*name=*/"cars",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              "a.test", "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/test_origin,
+          /*name=*/"cars",
+          /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          /*bidding_url=*/
+          https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
+          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
 
   std::string auction_config = JsReplace(
       R"({
@@ -5469,14 +5561,17 @@
   url::Origin test_origin = url::Origin::Create(test_url);
   GURL ad_url = https_server_->GetURL("c.test", "/echo?render_cars");
 
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/test_origin,
-                          /*name=*/"cars",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              "a.test", "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/test_origin,
+          /*name=*/"cars",
+          /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          /*bidding_url=*/
+          https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
+          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
 
   std::string auction_config = JsReplace(
       R"({
@@ -5508,14 +5603,17 @@
   url::Origin test_origin = url::Origin::Create(test_url);
   GURL ad_url = https_server_->GetURL("c.test", "/echo?render_cars");
 
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/test_origin,
-                          /*name=*/"cars",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              "a.test", "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/test_origin,
+          /*name=*/"cars",
+          /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          /*bidding_url=*/
+          https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
+          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
 
   std::string auction_config = JsReplace(
       R"({
@@ -5545,14 +5643,17 @@
   url::Origin test_origin = url::Origin::Create(test_url);
   GURL ad_url = https_server_->GetURL("c.test", "/echo?render_cars");
 
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/test_origin,
-                          /*name=*/"cars",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              "a.test", "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/test_origin,
+          /*name=*/"cars",
+          /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          /*bidding_url=*/
+          https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
+          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
 
   std::string auction_config = JsReplace(
       R"({
@@ -5597,6 +5698,8 @@
                 /*owner=*/second_bidder_origin,
                 /*name=*/"boats",
                 /*priority=*/0.0,
+                /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(kSecondBidderHost,
                                       "/interest_group/bidding_logic.js"),
@@ -5617,7 +5720,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/bidder_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL(
               kBidderHost, "/interest_group/bidding_argument_validator.js"),
@@ -5696,7 +5800,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/bidder_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL(
               kBidderHost,
@@ -5790,7 +5895,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -5989,7 +6095,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/hanging_origin,
                 /*name=*/"cars",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/hanging_url,
                 /*bidding_wasm_helper_url=*/absl::nullopt,
                 /*daily_update_url=*/absl::nullopt,
@@ -6045,7 +6152,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -6070,7 +6178,10 @@
             if (groups.size() != 1)
               return false;
             const auto& group = groups[0].interest_group;
-            return group.name == "cars" && group.bidding_url.has_value() &&
+            return group.name == "cars" && group.priority == 0.0 &&
+                   group.execution_mode == blink::InterestGroup::ExecutionMode::
+                                               kCompatibilityMode &&
+                   group.bidding_url.has_value() &&
                    group.bidding_url->path() ==
                        "/interest_group/new_bidding_logic.js" &&
                    group.trusted_bidding_signals_url.has_value() &&
@@ -6112,7 +6223,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -6172,14 +6284,17 @@
   ASSERT_TRUE(NavigateToURL(shell(), bidder_b_url));
 
   GURL ad_url_b = https_server_->GetURL(kHostB, "/echo?render_shoes");
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/bidder_b_origin,
-                          /*name=*/"shoes",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              kHostB, "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url_b, /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/bidder_b_origin,
+          /*name=*/"shoes",
+          /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          /*bidding_url=*/
+          https_server_->GetURL(kHostB, "/interest_group/bidding_logic.js"),
+          /*ads=*/{{{ad_url_b, /*metadata=*/absl::nullopt}}}));
 
   GURL bidder_a_url = https_server_->GetURL(kHostA, "/page_with_iframe.html");
   ASSERT_TRUE(NavigateToURL(shell(), bidder_a_url));
@@ -6192,6 +6307,8 @@
                 /*owner=*/bidder_a_origin,
                 /*name=*/"cars",
                 /*priority=*/0.0,
+                /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     kHostA, "/interest_group/bidding_logic_loop_forever.js"),
@@ -6200,7 +6317,8 @@
             JoinInterestGroupAndVerify(
                 /*owner=*/bidder_a_origin,
                 /*name=*/"bikes",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     kHostA, "/interest_group/bidding_logic_loop_forever.js"),
@@ -6241,14 +6359,17 @@
   url::Origin test_origin = url::Origin::Create(test_url);
   GURL ad_url = https_server_->GetURL(kHostA, "/echo?render_cars");
 
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/test_origin,
-                          /*name=*/"cars",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          https_server_->GetURL(
-                              kHostA, "/interest_group/bidding_logic.js"),
-                          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/test_origin,
+          /*name=*/"cars",
+          /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          /*bidding_url=*/
+          https_server_->GetURL(kHostA, "/interest_group/bidding_logic.js"),
+          /*ads=*/{{{ad_url, /*metadata=*/absl::nullopt}}}));
 
   // The auction fails, since seller's scoreAd() script times out after 1 ms.
   EXPECT_EQ(
@@ -6281,7 +6402,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/bidder_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL(kBidder, "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -6346,7 +6468,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/bidder_origin,
           /*name=*/"cars",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL(kBidder, "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -6371,7 +6494,8 @@
           /*expiry=*/base::Time(),
           /*owner=*/bidder2_origin,
           /*name=*/"cars_and_trucks",
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL(kBidder2, "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -6446,12 +6570,15 @@
       https_server_->GetURL("b.test", "/interest_group/bidding_logic.js");
   ASSERT_TRUE(NavigateToURL(shell(), https_server_->GetURL("b.test", "/echo")));
   url::Origin bidder_origin = url::Origin::Create(bidder_url);
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/bidder_origin,
-                          /*name=*/"Cthulhu", /*priority=*/0.0, bidder_url,
-                          /*ads=*/
-                          {{{GURL("https://example.com/render"),
-                             /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(
+      kSuccess,
+      JoinInterestGroupAndVerify(
+          /*owner=*/bidder_origin,
+          /*name=*/"Cthulhu", /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode, bidder_url,
+          /*ads=*/
+          {{{GURL("https://example.com/render"),
+             /*metadata=*/absl::nullopt}}}));
 
   // Use `remote_test_server_` for all other URLs.
   GURL test_url = remote_test_server_.GetURL("a.test", "/echo");
@@ -6503,16 +6630,18 @@
   // AdAuctionServiceImpl's URLLoaderFactory.
   URLLoaderMonitor url_loader_monitor;
 
-  EXPECT_EQ(kSuccess, JoinInterestGroupAndVerify(
-                          /*owner=*/test_origin,
-                          /*name=*/"Cthulhu",
-                          /*priority=*/0.0,
-                          /*bidding_url=*/
-                          remote_test_server_.GetURL(
-                              "a.test", "/interest_group/bidding_logic.js"),
-                          /*ads=*/
-                          {{{GURL("https://example.com/render"),
-                             /*metadata=*/absl::nullopt}}}));
+  EXPECT_EQ(kSuccess,
+            JoinInterestGroupAndVerify(
+                /*owner=*/test_origin,
+                /*name=*/"Cthulhu",
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+                /*bidding_url=*/
+                remote_test_server_.GetURL("a.test",
+                                           "/interest_group/bidding_logic.js"),
+                /*ads=*/
+                {{{GURL("https://example.com/render"),
+                   /*metadata=*/absl::nullopt}}}));
 
   EXPECT_EQ(nullptr,
             RunAuctionAndWait(JsReplace(
@@ -6568,7 +6697,8 @@
       JoinInterestGroupAndVerify(
           /*owner=*/test_origin,
           /*name=*/bidder_report_to_url.spec(),
-          /*priority=*/0.0,
+          /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           remote_test_server_.GetURL(
               "a.test", "/interest_group/bidding_logic_report_to_name.js"),
@@ -6660,7 +6790,9 @@
       JoinInterestGroupAndVerify(blink::InterestGroup(
           /*expiry=*/base::Time(),
           /*owner=*/test_origin,
-          /*name=*/bidder_report_to_url.spec(), /*priority=*/0.0, bidder_url,
+          /*name=*/bidder_report_to_url.spec(), /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode, bidder_url,
           /*bidding_wasm_helper_url=*/absl::nullopt,
           /*daily_update_url=*/absl::nullopt, trusted_bidding_signals_url,
           /*trusted_bidding_signals_keys=*/{{"key1"}},
@@ -6767,7 +6899,9 @@
               JoinInterestGroupAndVerify(blink::InterestGroup(
                   /*expiry=*/base::Time(),
                   /*owner=*/url::Origin::Create(test_url), group_name,
-                  /*priority=*/0.0, initial_bidding_url,
+                  /*priority=*/0.0, /*execution_mode=*/
+                  blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+                  initial_bidding_url,
                   /*bidding_wasm_helper_url=*/absl::nullopt, update_url,
                   /*trusted_bidding_signals_url=*/absl::nullopt,
                   /*trusted_bidding_signals_keys=*/absl::nullopt,
@@ -6897,7 +7031,9 @@
       JoinInterestGroupAndVerify(blink::InterestGroup(
           /*expiry=*/base::Time(),
           /*owner=*/url::Origin::Create(initial_bidding_url_a),
-          kLocallyUpdateGroupName, /*priority=*/0.0, initial_bidding_url_a,
+          kLocallyUpdateGroupName, /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          initial_bidding_url_a,
           /*bidding_wasm_helper_url=*/absl::nullopt, update_url_a,
           /*trusted_bidding_signals_url=*/absl::nullopt,
           /*trusted_bidding_signals_keys=*/absl::nullopt,
@@ -6923,7 +7059,9 @@
       JoinInterestGroupAndVerify(blink::InterestGroup(
           /*expiry=*/base::Time(),
           /*owner=*/url::Origin::Create(initial_bidding_url_b),
-          kPubliclyUpdateGroupName, /*priority=*/0.0, initial_bidding_url_b,
+          kPubliclyUpdateGroupName, /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          initial_bidding_url_b,
           /*bidding_wasm_helper_url=*/absl::nullopt, update_url_b,
           /*trusted_bidding_signals_url=*/absl::nullopt,
           /*trusted_bidding_signals_keys=*/absl::nullopt,
@@ -6943,7 +7081,9 @@
       JoinInterestGroupAndVerify(blink::InterestGroup(
           /*expiry=*/base::Time(),
           /*owner=*/url::Origin::Create(initial_bidding_url_c),
-          kLocallyUpdateGroupName, /*priority=*/0.0, initial_bidding_url_c,
+          kLocallyUpdateGroupName, /*priority=*/0.0, /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
+          initial_bidding_url_c,
           /*bidding_wasm_helper_url=*/absl::nullopt, update_url_c,
           /*trusted_bidding_signals_url=*/absl::nullopt,
           /*trusted_bidding_signals_keys=*/absl::nullopt,
@@ -7057,7 +7197,8 @@
             /*expiry=*/base::Time(),
             /*owner=*/test_origin_a,
             /*name=*/group_name,
-            /*priority=*/0.0,
+            /*priority=*/0.0, /*execution_mode=*/
+            blink::InterestGroup::ExecutionMode::kCompatibilityMode,
             /*bidding_url=*/
             https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
             /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -7077,7 +7218,8 @@
             /*expiry=*/base::Time(),
             /*owner=*/test_origin_b,
             /*name=*/group_name,
-            /*priority=*/0.0,
+            /*priority=*/0.0, /*execution_mode=*/
+            blink::InterestGroup::ExecutionMode::kCompatibilityMode,
             /*bidding_url=*/
             https_server_->GetURL("b.test", "/interest_group/bidding_logic.js"),
             /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -7257,7 +7399,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/origin,
                 /*name=*/"cars",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(host, "/interest_group/bidding_logic.js"),
                 /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -7432,7 +7575,8 @@
                 /*expiry=*/base::Time(),
                 /*owner=*/origin,
                 /*name=*/"cars",
-                /*priority=*/0.0,
+                /*priority=*/0.0, /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(host, "/interest_group/bidding_logic.js"),
                 /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -7550,7 +7694,8 @@
                     /*expiry=*/base::Time(),
                     /*owner=*/other_origin,
                     /*name=*/"cars",
-                    /*priority=*/0.0,
+                    /*priority=*/0.0, /*execution_mode=*/
+                    blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                     /*bidding_url=*/
                     https_server_->GetURL("b.test",
                                           "/interest_group/bidding_logic.js"),
@@ -7644,6 +7789,8 @@
           /*owner=*/test_origin,
           /*name=*/"cars",
           /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -7721,6 +7868,8 @@
           /*owner=*/test_origin,
           /*name=*/"cars",
           /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -7801,6 +7950,8 @@
           /*owner=*/test_origin,
           /*name=*/"cars",
           /*priority=*/0.0,
+          /*execution_mode=*/
+          blink::InterestGroup::ExecutionMode::kCompatibilityMode,
           /*bidding_url=*/
           https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"),
           /*bidding_wasm_helper_url=*/absl::nullopt,
@@ -7887,6 +8038,8 @@
                 /*owner=*/test_origin,
                 /*name=*/"winner",
                 /*priority=*/0.0,
+                /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
@@ -7904,6 +8057,8 @@
                 /*owner=*/test_origin,
                 /*name=*/"bikes",
                 /*priority=*/0.0,
+                /*execution_mode=*/
+                blink::InterestGroup::ExecutionMode::kCompatibilityMode,
                 /*bidding_url=*/
                 https_server_->GetURL(
                     "a.test",
diff --git a/content/browser/interest_group/interest_group_storage.cc b/content/browser/interest_group/interest_group_storage.cc
index 3c39e71..6fe0f5c 100644
--- a/content/browser/interest_group/interest_group_storage.cc
+++ b/content/browser/interest_group/interest_group_storage.cc
@@ -55,6 +55,8 @@
 // Version 4 - 2021/10 - crrev.com/c/3172863
 // Version 5 - 2021/10 - crrev.com/c/3067804
 // Version 6 - 2021/12 - crrev.com/c/3330516
+// Version 7 - 2022/03 - crrev.com/c/3517534
+// Version 8 - 2022/06 - crrev.com/c/3696265
 //
 // Version 1 adds a table for interest groups.
 // Version 2 adds a column for rate limiting interest group updates.
@@ -63,7 +65,8 @@
 // Version 5 adds k-anonymity tables and fields.
 // Version 6 adds WebAssembly helper url.
 // Version 7 changes an index, adds interest group priority.
-const int kCurrentVersionNumber = 7;
+// Version 8 adds the execution_mode field to interest groups.
+const int kCurrentVersionNumber = 8;
 
 // Earliest version of the code which can use a |kCurrentVersionNumber|
 // database without failing.
@@ -184,7 +187,7 @@
 
 // Initializes the tables, returning true on success.
 // The tables cannot exist when calling this function.
-bool CreateV7Schema(sql::Database& db) {
+bool CreateV8Schema(sql::Database& db) {
   DCHECK(!db.DoesTableExist("interest_groups"));
   static const char kInterestGroupTableSql[] =
       // clang-format off
@@ -196,6 +199,7 @@
         "joining_origin TEXT NOT NULL,"
         "name TEXT NOT NULL,"
         "priority DOUBLE NOT NULL,"
+        "execution_mode INTEGER NOT NULL,"
         "joining_url TEXT NOT NULL,"
         "bidding_url TEXT NOT NULL,"
         "bidding_wasm_helper_url TEXT NOT NULL,"
@@ -339,6 +343,14 @@
   return true;
 }
 
+bool UpgradeV7SchemaToV8(sql::Database& db, sql::MetaTable& meta_table) {
+  static const char kInterestGroupsAddExecutionModeSql[] =
+      "ALTER TABLE interest_groups ADD COLUMN execution_mode INTEGER DEFAULT 0";
+  if (!db.Execute(kInterestGroupsAddExecutionModeSql))
+    return false;
+  return true;
+}
+
 bool UpgradeV6SchemaToV7(sql::Database& db, sql::MetaTable& meta_table) {
   // Index on group expiration by owner.
   DCHECK(db.DoesIndexExist("interest_group_owner"));
@@ -515,6 +527,7 @@
             "joining_origin,"
             "name,"
             "priority,"
+            "execution_mode,"
             "joining_url,"
             "bidding_url,"
             "bidding_wasm_helper_url,"
@@ -524,7 +537,7 @@
             "user_bidding_signals,"  // opaque data
             "ads,"
             "ad_components) "
-          "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+          "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
 
   // clang-format on
   if (!join_group.is_valid())
@@ -538,19 +551,22 @@
   join_group.BindString(4, Serialize(joining_origin));
   join_group.BindString(5, data.name);
   join_group.BindDouble(6, data.priority.value_or(0));
-  join_group.BindString(7, Serialize(joining_url));
-  join_group.BindString(8, Serialize(data.bidding_url));
-  join_group.BindString(9, Serialize(data.bidding_wasm_helper_url));
-  join_group.BindString(10, Serialize(data.daily_update_url));
-  join_group.BindString(11, Serialize(data.trusted_bidding_signals_url));
-  join_group.BindString(12, Serialize(data.trusted_bidding_signals_keys));
+  join_group.BindInt(
+      7, static_cast<int>(data.execution_mode.value_or(
+             blink::InterestGroup::ExecutionMode::kCompatibilityMode)));
+  join_group.BindString(8, Serialize(joining_url));
+  join_group.BindString(9, Serialize(data.bidding_url));
+  join_group.BindString(10, Serialize(data.bidding_wasm_helper_url));
+  join_group.BindString(11, Serialize(data.daily_update_url));
+  join_group.BindString(12, Serialize(data.trusted_bidding_signals_url));
+  join_group.BindString(13, Serialize(data.trusted_bidding_signals_keys));
   if (data.user_bidding_signals) {
-    join_group.BindString(13, data.user_bidding_signals.value());
+    join_group.BindString(14, data.user_bidding_signals.value());
   } else {
-    join_group.BindNull(13);
+    join_group.BindNull(14);
   }
-  join_group.BindString(14, Serialize(data.ads));
-  join_group.BindString(15, Serialize(data.ad_components));
+  join_group.BindString(15, Serialize(data.ads));
+  join_group.BindString(16, Serialize(data.ad_components));
 
   if (!join_group.Run())
     return false;
@@ -592,6 +608,7 @@
           "joining_origin,"
           "last_updated,"
           "priority,"
+          "execution_mode,"
           "bidding_url,"
           "bidding_wasm_helper_url,"
           "update_url,"
@@ -622,16 +639,18 @@
   if (last_updated)
     *last_updated = load.ColumnTime(2);
   group.priority = load.ColumnDouble(3);
-  group.bidding_url = DeserializeURL(load.ColumnString(4));
-  group.bidding_wasm_helper_url = DeserializeURL(load.ColumnString(5));
-  group.daily_update_url = DeserializeURL(load.ColumnString(6));
-  group.trusted_bidding_signals_url = DeserializeURL(load.ColumnString(7));
+  group.execution_mode =
+      static_cast<blink::InterestGroup::ExecutionMode>(load.ColumnInt(4));
+  group.bidding_url = DeserializeURL(load.ColumnString(5));
+  group.bidding_wasm_helper_url = DeserializeURL(load.ColumnString(6));
+  group.daily_update_url = DeserializeURL(load.ColumnString(7));
+  group.trusted_bidding_signals_url = DeserializeURL(load.ColumnString(8));
   group.trusted_bidding_signals_keys =
-      DeserializeStringVector(load.ColumnString(8));
-  if (load.GetColumnType(9) != sql::ColumnType::kNull)
-    group.user_bidding_signals = load.ColumnString(9);
-  group.ads = DeserializeInterestGroupAdVector(load.ColumnString(10));
-  group.ad_components = DeserializeInterestGroupAdVector(load.ColumnString(11));
+      DeserializeStringVector(load.ColumnString(9));
+  if (load.GetColumnType(10) != sql::ColumnType::kNull)
+    group.user_bidding_signals = load.ColumnString(10);
+  group.ads = DeserializeInterestGroupAdVector(load.ColumnString(11));
+  group.ad_components = DeserializeInterestGroupAdVector(load.ColumnString(12));
 
   return true;
 }
@@ -646,6 +665,7 @@
           "SET last_updated=?,"
             "next_update_after=?,"
             "priority=?,"
+            "execution_mode=?,"
             "bidding_url=?,"
             "bidding_wasm_helper_url=?,"
             "update_url=?,"
@@ -664,15 +684,18 @@
   store_group.BindTime(
       1, now + InterestGroupStorage::kUpdateSucceededBackoffPeriod);
   store_group.BindDouble(2, group.priority.value_or(0));
-  store_group.BindString(3, Serialize(group.bidding_url));
-  store_group.BindString(4, Serialize(group.bidding_wasm_helper_url));
-  store_group.BindString(5, Serialize(group.daily_update_url));
-  store_group.BindString(6, Serialize(group.trusted_bidding_signals_url));
-  store_group.BindString(7, Serialize(group.trusted_bidding_signals_keys));
-  store_group.BindString(8, Serialize(group.ads));
-  store_group.BindString(9, Serialize(group.ad_components));
-  store_group.BindString(10, Serialize(group.owner));
-  store_group.BindString(11, group.name);
+  store_group.BindInt(
+      3, static_cast<int>(group.execution_mode.value_or(
+             blink::InterestGroup::ExecutionMode::kCompatibilityMode)));
+  store_group.BindString(4, Serialize(group.bidding_url));
+  store_group.BindString(5, Serialize(group.bidding_wasm_helper_url));
+  store_group.BindString(6, Serialize(group.daily_update_url));
+  store_group.BindString(7, Serialize(group.trusted_bidding_signals_url));
+  store_group.BindString(8, Serialize(group.trusted_bidding_signals_keys));
+  store_group.BindString(9, Serialize(group.ads));
+  store_group.BindString(10, Serialize(group.ad_components));
+  store_group.BindString(11, Serialize(group.owner));
+  store_group.BindString(12, group.name);
 
   return store_group.Run();
 }
@@ -705,6 +728,8 @@
     return false;
   if (update.priority)
     stored_group.priority = update.priority;
+  if (update.execution_mode)
+    stored_group.execution_mode = update.execution_mode;
   if (update.bidding_url)
     stored_group.bidding_url = update.bidding_url;
   if (update.bidding_wasm_helper_url)
@@ -1639,7 +1664,7 @@
     return false;
 
   if (new_db)
-    return CreateV7Schema(*db_);
+    return CreateV8Schema(*db_);
 
   const int db_version = meta_table.GetVersionNumber();
 
@@ -1654,9 +1679,21 @@
   // Older versions - should be migrated.
   // db_version < kCurrentVersionNumber
   // db_version > kDeprecatedVersionNumber
-  if (db_version == 6) {
-    meta_table.SetVersionNumber(7);
-    return UpgradeV6SchemaToV7(*db_, meta_table);
+  {
+    sql::Transaction transaction(db_.get());
+    if (!transaction.Begin())
+      return false;
+    switch (db_version) {
+      case 6:
+        if (!UpgradeV6SchemaToV7(*db_, meta_table))
+          return false;
+        ABSL_FALLTHROUGH_INTENDED;
+      case 7:
+        if (!UpgradeV7SchemaToV8(*db_, meta_table))
+          return false;
+        meta_table.SetVersionNumber(8);
+    }
+    return transaction.Commit();
   }
 
   NOTREACHED();  // Only V6 should have passed RazeIfIncompatible.
diff --git a/content/browser/interest_group/interest_group_storage_unittest.cc b/content/browser/interest_group/interest_group_storage_unittest.cc
index 9c4bc37..a27a5c3 100644
--- a/content/browser/interest_group/interest_group_storage_unittest.cc
+++ b/content/browser/interest_group/interest_group_storage_unittest.cc
@@ -71,6 +71,8 @@
     result.owner = owner;
     result.name = name;
     result.expiry = base::Time::Now() + base::Days(30);
+    result.execution_mode =
+        blink::InterestGroup::ExecutionMode::kCompatibilityMode;
     return result;
   }
 
@@ -730,6 +732,7 @@
   InterestGroup full(
       /*expiry=*/base::Time::Now() + base::Days(30), /*owner=*/full_origin,
       /*name=*/"full", /*priority=*/1.0,
+      /*execution_mode=*/InterestGroup::ExecutionMode::kCompatibilityMode,
       /*bidding_url=*/GURL("https://full.example.com/bid"),
       /*bidding_wasm_helper_url=*/GURL("https://full.example.com/bid_wasm"),
       /*daily_update_url=*/GURL("https://full.example.com/update"),
diff --git a/content/browser/interest_group/interest_group_update_manager.cc b/content/browser/interest_group/interest_group_update_manager.cc
index 327866f..2da503c 100644
--- a/content/browser/interest_group/interest_group_update_manager.cc
+++ b/content/browser/interest_group/interest_group_update_manager.cc
@@ -95,6 +95,23 @@
   return true;
 }
 
+// Copies the execution_mode JSON field into `interest_group_update`, returns
+// true iff the JSON is valid and the copy completed.
+[[nodiscard]] bool TryToCopyExecutionmode(
+    blink::InterestGroup& interest_group_update,
+    const base::Value::Dict& dict) {
+  const std::string* maybe_execution_mode = dict.FindString("execution_mode");
+  if (!maybe_execution_mode)
+    return true;
+  if (*maybe_execution_mode == "compatibility") {
+    interest_group_update.execution_mode =
+        blink::InterestGroup::ExecutionMode::kCompatibilityMode;
+  } else {
+    return false;
+  }
+  return true;
+}
+
 // Copies the trustedBiddingSignals list JSON field into
 // `interest_group_update`, returns true iff the JSON is valid and the copy
 // completed.
@@ -203,6 +220,9 @@
       return absl::nullopt;
     interest_group_update.priority = maybe_priority_value->GetDouble();
   }
+  if (!TryToCopyExecutionmode(interest_group_update, *dict)) {
+    return absl::nullopt;
+  }
   const std::string* maybe_bidding_url = dict->FindString("biddingLogicUrl");
   if (maybe_bidding_url)
     interest_group_update.bidding_url = GURL(*maybe_bidding_url);
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 719a0bf..0dd961b2 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -376,10 +376,10 @@
   DCHECK(mojo::Equals(lhs->origin_agent_cluster, rhs->origin_agent_cluster));
   DCHECK(mojo::Equals(lhs->accept_ch, rhs->accept_ch));
   DCHECK(mojo::Equals(lhs->critical_ch, rhs->critical_ch));
-  DCHECK(mojo::Equals(lhs->xfo, rhs->xfo));
+  DCHECK_EQ(lhs->xfo, rhs->xfo);
   DCHECK(mojo::Equals(lhs->link_headers, rhs->link_headers));
   DCHECK(mojo::Equals(lhs->timing_allow_origin, rhs->timing_allow_origin));
-  DCHECK(mojo::Equals(lhs->bfcache_opt_in_unload, rhs->bfcache_opt_in_unload));
+  DCHECK_EQ(lhs->bfcache_opt_in_unload, rhs->bfcache_opt_in_unload);
   DCHECK(mojo::Equals(lhs->reporting_endpoints, rhs->reporting_endpoints));
   DCHECK(mojo::Equals(lhs->variants_headers, rhs->variants_headers));
   DCHECK(mojo::Equals(lhs->content_language, rhs->content_language));
diff --git a/content/browser/media/capture/fake_video_capture_stack.cc b/content/browser/media/capture/fake_video_capture_stack.cc
index 5515600f..dff280c 100644
--- a/content/browser/media/capture/fake_video_capture_stack.cc
+++ b/content/browser/media/capture/fake_video_capture_stack.cc
@@ -166,6 +166,8 @@
 
   void OnFrameDropped(media::VideoCaptureFrameDropReason) override {}
 
+  void OnNewCropVersion(uint32_t crop_version) override {}
+
   void OnFrameWithEmptyRegionCapture() override {}
 
   void OnLog(const std::string& message) override {
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.cc b/content/browser/media/capture/frame_sink_video_capture_device.cc
index bf96950e..68f9ef3 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device.cc
+++ b/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -411,6 +411,16 @@
       {});
 }
 
+void FrameSinkVideoCaptureDevice::OnNewCropVersion(uint32_t crop_version) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!receiver_) {
+    return;
+  }
+
+  receiver_->OnNewCropVersion(crop_version);
+}
+
 void FrameSinkVideoCaptureDevice::OnFrameWithEmptyRegionCapture() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.h b/content/browser/media/capture/frame_sink_video_capture_device.h
index 191b2bc..26d1377 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device.h
+++ b/content/browser/media/capture/frame_sink_video_capture_device.h
@@ -99,6 +99,7 @@
       const gfx::Rect& content_rect,
       mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
           callbacks) override;
+  void OnNewCropVersion(uint32_t crop_version) final;
   void OnFrameWithEmptyRegionCapture() final;
   void OnStopped() final;
   void OnLog(const std::string& message) final;
diff --git a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
index 11d02cb..55a9d79c 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
+++ b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
@@ -215,6 +215,7 @@
   MOCK_METHOD1(OnBufferRetired, void(int buffer_id));
   MOCK_METHOD1(OnError, void(media::VideoCaptureError error));
   MOCK_METHOD1(OnFrameDropped, void(media::VideoCaptureFrameDropReason reason));
+  MOCK_METHOD1(OnNewCropVersion, void(uint32_t crop_version));
   MOCK_METHOD0(OnFrameWithEmptyRegionCapture, void());
   MOCK_METHOD1(OnLog, void(const std::string& message));
   MOCK_METHOD0(OnStarted, void());
diff --git a/content/browser/media/capture/receiver_media_to_crosapi_adapter.cc b/content/browser/media/capture/receiver_media_to_crosapi_adapter.cc
index f25dcab..662f22f 100644
--- a/content/browser/media/capture/receiver_media_to_crosapi_adapter.cc
+++ b/content/browser/media/capture/receiver_media_to_crosapi_adapter.cc
@@ -79,6 +79,10 @@
   handler_->OnFrameDropped(reason);
 }
 
+void ReceiverMediaToCrosapiAdapter::OnNewCropVersion(uint32_t crop_version) {
+  handler_->OnNewCropVersion(crop_version);
+}
+
 void ReceiverMediaToCrosapiAdapter::OnFrameWithEmptyRegionCapture() {
   handler_->OnFrameWithEmptyRegionCapture();
 }
diff --git a/content/browser/media/capture/receiver_media_to_crosapi_adapter.h b/content/browser/media/capture/receiver_media_to_crosapi_adapter.h
index 64400eb5..7948463 100644
--- a/content/browser/media/capture/receiver_media_to_crosapi_adapter.h
+++ b/content/browser/media/capture/receiver_media_to_crosapi_adapter.h
@@ -44,6 +44,7 @@
                                 scaled_buffers) override;
   void OnBufferRetired(int buffer_id) override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnStarted() override;
   void OnStartedUsingGpuDecode() override;
diff --git a/content/browser/net/trust_token_browsertest.cc b/content/browser/net/trust_token_browsertest.cc
index 0a368c28..5a763a0 100644
--- a/content/browser/net/trust_token_browsertest.cc
+++ b/content/browser/net/trust_token_browsertest.cc
@@ -1676,6 +1676,48 @@
               Optional(ReflectsSigningFailure()));
 }
 
+IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertest, FetchEndToEndWithServiceWorker) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  const char* const hostname = "a.test";
+  ProvideRequestHandlerKeyCommitmentsToNetworkService({hostname});
+  const std::string origin = IssuanceOriginFromHost(hostname);
+  const GURL create_sw_url =
+      server_.GetURL(hostname, "/service_worker/create_service_worker.html");
+  EXPECT_TRUE(NavigateToURL(shell(), create_sw_url));
+  // call register function defined in create_sw_url with the service worker js
+  // file path
+  EXPECT_EQ("DONE",
+            EvalJs(shell(), "register('fetch_event_respond_with_fetch.js');"));
+  // Following navigate to empty html page makes fetch requests go through
+  // service worker. Requests do not go through service workers when commented
+  // out.
+  const GURL empty_page_url =
+      server_.GetURL(hostname, "/service_worker/empty.html");
+  EXPECT_TRUE(NavigateToURL(shell(), empty_page_url));
+  const std::string trust_token_fetch_snippet = R"(
+  (async () => {
+    if (navigator.serviceWorker.controller === null) return "NotServiceWorker";
+    await fetch("/issue", {trustToken: {type: 'token-request'}});
+    await fetch("/redeem", {trustToken: {type: 'token-redemption'}});
+    await fetch("/sign", {trustToken: {type: 'send-redemption-record',
+                                  signRequestData: 'include',
+                                  issuers: [$1]}});
+    return "TTSuccess"; })(); )";
+
+  EXPECT_EQ("TTSuccess",
+            EvalJs(shell(), JsReplace(trust_token_fetch_snippet, origin)));
+
+  EXPECT_THAT(
+      request_handler_.last_incoming_signed_request(),
+      Optional(AllOf(
+          Not(HasHeader(network::kTrustTokensRequestHeaderSecTime)),
+          HasHeader(network::kTrustTokensRequestHeaderSecRedemptionRecord),
+          HasHeader(network::kTrustTokensSecTrustTokenVersionHeader),
+          SignaturesAreWellFormedAndVerify(),
+          SecSignatureHeaderKeyHashes(IsSubsetOf(
+              request_handler_.hashes_of_redemption_bound_public_keys())))));
+}
+
 class TrustTokenBrowsertestWithPlatformIssuance : public TrustTokenBrowsertest {
  public:
   TrustTokenBrowsertestWithPlatformIssuance() {
diff --git a/content/browser/payments/payment_app_browsertest.cc b/content/browser/payments/payment_app_browsertest.cc
index 08d2603..7053b9c 100644
--- a/content/browser/payments/payment_app_browsertest.cc
+++ b/content/browser/payments/payment_app_browsertest.cc
@@ -21,6 +21,7 @@
 #include "content/shell/browser/shell.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
 
@@ -191,8 +192,9 @@
                                            ->GetBrowserContext()
                                            ->GetDefaultStoragePartition())
         ->ClearData(StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS,
-                    StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
-                    base::Time(), base::Time::Max(), run_loop.QuitClosure());
+                    StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+                    blink::StorageKey(), base::Time(), base::Time::Max(),
+                    run_loop.QuitClosure());
 
     run_loop.Run();
   }
diff --git a/content/browser/preloading/OWNERS b/content/browser/preloading/OWNERS
new file mode 100644
index 0000000..e04727b3
--- /dev/null
+++ b/content/browser/preloading/OWNERS
@@ -0,0 +1,3 @@
+nhiroki@chromium.org
+ryansturm@chromium.org
+spelchat@chromium.org
diff --git a/content/browser/preloading_attempt_impl.cc b/content/browser/preloading/preloading_attempt_impl.cc
similarity index 98%
rename from content/browser/preloading_attempt_impl.cc
rename to content/browser/preloading/preloading_attempt_impl.cc
index 4e25f47..b772885 100644
--- a/content/browser/preloading_attempt_impl.cc
+++ b/content/browser/preloading/preloading_attempt_impl.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 "content/browser/preloading_attempt_impl.h"
+#include "content/browser/preloading/preloading_attempt_impl.h"
 
 #include "content/common/state_transitions.h"
 #include "content/public/browser/preloading.h"
diff --git a/content/browser/preloading_attempt_impl.h b/content/browser/preloading/preloading_attempt_impl.h
similarity index 94%
rename from content/browser/preloading_attempt_impl.h
rename to content/browser/preloading/preloading_attempt_impl.h
index d02417a..0020031 100644
--- a/content/browser/preloading_attempt_impl.h
+++ b/content/browser/preloading/preloading_attempt_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_PRELOADING_ATTEMPT_IMPL_H_
-#define CONTENT_BROWSER_PRELOADING_ATTEMPT_IMPL_H_
+#ifndef CONTENT_BROWSER_PRELOADING_PRELOADING_ATTEMPT_IMPL_H_
+#define CONTENT_BROWSER_PRELOADING_PRELOADING_ATTEMPT_IMPL_H_
 
 #include "content/public/browser/preloading.h"
 #include "content/public/browser/preloading_data.h"
@@ -83,4 +83,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_PRELOADING_ATTEMPT_IMPL_H_
+#endif  // CONTENT_BROWSER_PRELOADING_PRELOADING_ATTEMPT_IMPL_H_
diff --git a/content/browser/preloading_data_impl.cc b/content/browser/preloading/preloading_data_impl.cc
similarity index 95%
rename from content/browser/preloading_data_impl.cc
rename to content/browser/preloading/preloading_data_impl.cc
index 56db477..58cd8d7 100644
--- a/content/browser/preloading_data_impl.cc
+++ b/content/browser/preloading/preloading_data_impl.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/preloading_data_impl.h"
+#include "content/browser/preloading/preloading_data_impl.h"
 
-#include "content/browser/preloading_attempt_impl.h"
-#include "content/browser/preloading_prediction.h"
+#include "content/browser/preloading/preloading_attempt_impl.h"
+#include "content/browser/preloading/preloading_prediction.h"
 #include "content/public/browser/page.h"
 #include "content/public/browser/web_contents.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
diff --git a/content/browser/preloading_data_impl.h b/content/browser/preloading/preloading_data_impl.h
similarity index 93%
rename from content/browser/preloading_data_impl.h
rename to content/browser/preloading/preloading_data_impl.h
index 997686297..473dd3e2 100644
--- a/content/browser/preloading_data_impl.h
+++ b/content/browser/preloading/preloading_data_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_PRELOADING_DATA_IMPL_H_
-#define CONTENT_BROWSER_PRELOADING_DATA_IMPL_H_
+#ifndef CONTENT_BROWSER_PRELOADING_PRELOADING_DATA_IMPL_H_
+#define CONTENT_BROWSER_PRELOADING_PRELOADING_DATA_IMPL_H_
 
 #include <memory>
 #include <vector>
@@ -73,4 +73,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_PRELOADING_DATA_IMPL_H_
+#endif  // CONTENT_BROWSER_PRELOADING_PRELOADING_DATA_IMPL_H_
diff --git a/content/browser/preloading_prediction.cc b/content/browser/preloading/preloading_prediction.cc
similarity index 96%
rename from content/browser/preloading_prediction.cc
rename to content/browser/preloading/preloading_prediction.cc
index f97093cf..a00cb3f2 100644
--- a/content/browser/preloading_prediction.cc
+++ b/content/browser/preloading/preloading_prediction.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 "content/browser/preloading_prediction.h"
+#include "content/browser/preloading/preloading_prediction.h"
 
 #include "content/public/browser/page.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
diff --git a/content/browser/preloading_prediction.h b/content/browser/preloading/preloading_prediction.h
similarity index 92%
rename from content/browser/preloading_prediction.h
rename to content/browser/preloading/preloading_prediction.h
index 54ee759..3a71897 100644
--- a/content/browser/preloading_prediction.h
+++ b/content/browser/preloading/preloading_prediction.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_PRELOADING_PREDICTION_H_
-#define CONTENT_BROWSER_PRELOADING_PREDICTION_H_
+#ifndef CONTENT_BROWSER_PRELOADING_PRELOADING_PREDICTION_H_
+#define CONTENT_BROWSER_PRELOADING_PRELOADING_PREDICTION_H_
 
 #include "content/public/browser/preloading_data.h"
 
@@ -60,4 +60,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_PRELOADING_PREDICTION_H_
+#endif  // CONTENT_BROWSER_PRELOADING_PRELOADING_PREDICTION_H_
diff --git a/content/browser/prerender/prerender_browsertest.cc b/content/browser/prerender/prerender_browsertest.cc
index 0079dc8..8ef4239d 100644
--- a/content/browser/prerender/prerender_browsertest.cc
+++ b/content/browser/prerender/prerender_browsertest.cc
@@ -1291,8 +1291,9 @@
     int current_request_count = GetRequestCount(k2ndUrl);
     ASSERT_EQ(nullptr, EvalJs(prerender_frame_host, "history.back()"));
     // Make sure that loading is not happening.
-    EXPECT_FALSE(
-        FrameTreeNode::GloballyFindByID(host_id)->frame_tree()->IsLoading());
+    EXPECT_FALSE(FrameTreeNode::GloballyFindByID(host_id)
+                     ->frame_tree()
+                     ->IsLoadingIncludingInnerFrameTrees());
 
     TestNavigationHistory(k2ndUrl, /*expected_history_index=*/1,
                           /*expected_history_length=*/2);
@@ -1306,8 +1307,9 @@
     int current_request_count = GetRequestCount(k2ndUrl);
     ASSERT_EQ(nullptr, EvalJs(prerender_frame_host, "history.forward()"));
     // Make sure that loading is not happening.
-    EXPECT_FALSE(
-        FrameTreeNode::GloballyFindByID(host_id)->frame_tree()->IsLoading());
+    EXPECT_FALSE(FrameTreeNode::GloballyFindByID(host_id)
+                     ->frame_tree()
+                     ->IsLoadingIncludingInnerFrameTrees());
 
     TestNavigationHistory(k2ndUrl, /*expected_history_index=*/1,
                           /*expected_history_length=*/2);
diff --git a/content/browser/prerender/prerender_host.cc b/content/browser/prerender/prerender_host.cc
index f8a33c35..87d5b3b 100644
--- a/content/browser/prerender/prerender_host.cc
+++ b/content/browser/prerender/prerender_host.cc
@@ -290,7 +290,7 @@
   PrerenderHost::LoadingOutcome WaitForLoadCompletionForTesting() {
     PrerenderHost::LoadingOutcome status =
         PrerenderHost::LoadingOutcome::kLoadingCompleted;
-    if (!frame_tree_->IsLoading())
+    if (!frame_tree_->IsLoadingIncludingInnerFrameTrees())
       return status;
 
     base::RunLoop loop;
diff --git a/content/browser/renderer_host/back_forward_cache_metrics.cc b/content/browser/renderer_host/back_forward_cache_metrics.cc
index 846fcc65..61e20ef0 100644
--- a/content/browser/renderer_host/back_forward_cache_metrics.cc
+++ b/content/browser/renderer_host/back_forward_cache_metrics.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/renderer_host/back_forward_cache_metrics.h"
 
+#include "base/debug/crash_logging.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/metrics_hashes.h"
@@ -160,6 +161,41 @@
           DebugScenario::kDebugBackForwardCacheMetricsMismatch);
     }
 
+    // TODO(https://crbug.com/1338089): Remove this.
+    if (served_from_bfcache_not_match) {
+      SCOPED_CRASH_KEY_BOOL("BFCacheMismatch", "did_store", did_store);
+      SCOPED_CRASH_KEY_BOOL("BFCacheMismatch", "can_restore", can_restore);
+      SCOPED_CRASH_KEY_NUMBER(
+          "BFCacheMismatch", "not_restored",
+          page_store_result_->not_restored_reasons().ToEnumBitmask());
+      SCOPED_CRASH_KEY_NUMBER(
+          "BFCacheMismatch", "bi_swap",
+          page_store_result_->browsing_instance_swap_result().has_value()
+              ? static_cast<int>(
+                    page_store_result_->browsing_instance_swap_result().value())
+              : -1);
+      SCOPED_CRASH_KEY_NUMBER(
+          "BFCacheMismatch", "not_restored",
+          page_store_result_->blocklisted_features().ToEnumBitmask());
+      SCOPED_CRASH_KEY_NUMBER("BFCacheMismatch", "disabled",
+                              page_store_result_->disabled_reasons().size());
+      SCOPED_CRASH_KEY_NUMBER(
+          "BFCacheMismatch", "disallow_activation",
+          page_store_result_->disallow_activation_reasons().size());
+      SCOPED_CRASH_KEY_NUMBER("BFCacheMismatch", "navigation_type",
+                              navigation->navigation_type());
+      SCOPED_CRASH_KEY_BOOL("BFCacheMismatch", "did_replace",
+                            navigation->DidReplaceEntry());
+      SCOPED_CRASH_KEY_NUMBER("BFCacheMismatch", "restore_type",
+                              static_cast<int>(navigation->GetRestoreType()));
+      SCOPED_CRASH_KEY_STRING256("BFCacheMismatch", "url",
+                                 navigation->GetURL().spec());
+      SCOPED_CRASH_KEY_STRING256(
+          "BFCacheMismatch", "previous_url",
+          navigation->GetPreviousPrimaryMainFrameURL().spec());
+      base::debug::DumpWithoutCrashing();
+    }
+
     TRACE_EVENT1("navigation", "HistoryNavigationOutcome", "outcome",
                  page_store_result_->ToString());
     RecordHistoryNavigationUMA(navigation, back_forward_cache_allowed);
diff --git a/content/browser/renderer_host/frame_tree.cc b/content/browser/renderer_host/frame_tree.cc
index 95c8b8a..08d17a6 100644
--- a/content/browser/renderer_host/frame_tree.cc
+++ b/content/browser/renderer_host/frame_tree.cc
@@ -659,7 +659,7 @@
   return root_->current_frame_host()->GetPage().load_progress();
 }
 
-bool FrameTree::IsLoading() const {
+bool FrameTree::IsLoadingIncludingInnerFrameTrees() const {
   for (const FrameTreeNode* node :
        const_cast<FrameTree*>(this)->CollectNodesForIsLoading()) {
     if (node->IsLoading())
@@ -794,12 +794,12 @@
   if (was_previously_loading)
     return;
 
-  root()->render_manager()->SetIsLoading(IsLoading());
+  root()->render_manager()->SetIsLoading(IsLoadingIncludingInnerFrameTrees());
   delegate_->DidStartLoading(&node, should_show_loading_ui);
 }
 
 void FrameTree::DidStopLoadingNode(FrameTreeNode& node) {
-  if (IsLoading())
+  if (IsLoadingIncludingInnerFrameTrees())
     return;
 
   root()->render_manager()->SetIsLoading(false);
diff --git a/content/browser/renderer_host/frame_tree.h b/content/browser/renderer_host/frame_tree.h
index 796fffe..afdbe7db 100644
--- a/content/browser/renderer_host/frame_tree.h
+++ b/content/browser/renderer_host/frame_tree.h
@@ -147,9 +147,10 @@
     virtual void DidChangeLoadProgress() = 0;
 
     // Returns the delegate's top loading tree, which should be used to infer
-    // the values of loading-related states. The state of IsLoading() is a
-    // WebContents level concept and LoadingTree would return the frame tree to
-    // which loading events should be directed.
+    // the values of loading-related states. The state of
+    // IsLoadingIncludingInnerFrameTrees() is a WebContents level concept and
+    // LoadingTree would return the frame tree to which loading events should be
+    // directed.
     //
     // TODO(crbug.com/1261928): Remove this method and directly rely on
     // GetOutermostMainFrame() once portals and guest views are migrated to
@@ -435,10 +436,7 @@
 
   // Returns true if at least one of the nodes in this frame tree or nodes in
   // any inner frame tree of the same WebContents is loading.
-  //
-  // TODO(crbug.com/1293846): Rename to IsLoadingIncludingInnerFrameTrees() to
-  // adapt to new logic.
-  bool IsLoading() const;
+  bool IsLoadingIncludingInnerFrameTrees() const;
 
   // Set page-level focus in all SiteInstances involved in rendering
   // this FrameTree, not including the current main frame's
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
index 456176534..667dd12 100644
--- a/content/browser/renderer_host/frame_tree_node.cc
+++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -569,7 +569,8 @@
   DCHECK(!navigation_request->common_params().url.SchemeIs(
       url::kJavaScriptScheme));
 
-  bool was_previously_loading = frame_tree()->LoadingTree()->IsLoading();
+  bool was_previously_loading =
+      frame_tree()->LoadingTree()->IsLoadingIncludingInnerFrameTrees();
 
   // There's no need to reset the state: there's still an ongoing load, and the
   // RenderFrameHostManager will take care of updates to the speculative
diff --git a/content/browser/renderer_host/input/fling_scheduler_unittest.cc b/content/browser/renderer_host/input/fling_scheduler_unittest.cc
index 1b45630..3d83c0e 100644
--- a/content/browser/renderer_host/input/fling_scheduler_unittest.cc
+++ b/content/browser/renderer_host/input/fling_scheduler_unittest.cc
@@ -15,6 +15,10 @@
 #include "content/test/test_render_widget_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if BUILDFLAG(IS_WIN)
+#include "ui/display/win/test/scoped_screen_win.h"
+#endif
+
 namespace content {
 
 class FakeFlingScheduler : public FlingScheduler {
@@ -135,6 +139,10 @@
   scoped_refptr<SiteInstanceGroup> site_instance_group_;
   std::unique_ptr<TestRenderWidgetHostView> view_;
   std::unique_ptr<MockRenderWidgetHostDelegate> delegate_;
+#if BUILDFLAG(IS_WIN)
+  // This is necessary for static methods of `display::ScreenWin`.
+  display::win::test::ScopedScreenWin scoped_screen_win_;
+#endif
 };
 
 TEST_F(FlingSchedulerTest, ScheduleNextFlingProgress) {
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index d95b8bf..0f0ede19 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -739,6 +739,7 @@
         requested_audio_device_id, requested_video_device_id, audio_type_,
         video_type_, controls.disable_local_echo,
         controls.request_pan_tilt_zoom_permission);
+    ui_request_->exclude_system_audio = controls.exclude_system_audio;
   }
 
   // Creates a tab capture specific MediaStreamRequest object that is used by
@@ -753,6 +754,7 @@
         salt_and_origin.origin.GetURL(), user_gesture, request_type_, "", "",
         audio_type_, video_type_, controls.disable_local_echo,
         /*request_pan_tilt_zoom_permission=*/false);
+    ui_request_->exclude_system_audio = controls.exclude_system_audio;
   }
 
   bool HasUIRequest() const { return ui_request_.get() != nullptr; }
diff --git a/content/browser/renderer_host/media/video_capture_browsertest.cc b/content/browser/renderer_host/media/video_capture_browsertest.cc
index 141c8e2..56b553c 100644
--- a/content/browser/renderer_host/media/video_capture_browsertest.cc
+++ b/content/browser/renderer_host/media/video_capture_browsertest.cc
@@ -52,6 +52,8 @@
                     int buffer_id));
   MOCK_METHOD2(OnBufferDestroyed,
                void(const VideoCaptureControllerID&, int buffer_id));
+  MOCK_METHOD2(OnNewCropVersion,
+               void(const VideoCaptureControllerID&, uint32_t crop_version));
   MOCK_METHOD3(OnBufferReady,
                void(const VideoCaptureControllerID& id,
                     const ReadyBuffer& fullsized_buffer,
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index cbe971a..e0aa812 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -655,6 +655,18 @@
   LogVideoFrameDrop(reason, stream_type_);
 }
 
+void VideoCaptureController::OnNewCropVersion(uint32_t crop_version) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  EmitLogMessage(base::StringPrintf("%s(%u)", __func__, crop_version), 3);
+  for (const auto& client : controller_clients_) {
+    if (client->session_closed) {
+      continue;
+    }
+    client->event_handler->OnNewCropVersion(client->controller_id,
+                                            crop_version);
+  }
+}
+
 void VideoCaptureController::OnFrameWithEmptyRegionCapture() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   EmitLogMessage(__func__, 3);
diff --git a/content/browser/renderer_host/media/video_capture_controller.h b/content/browser/renderer_host/media/video_capture_controller.h
index 89f4cfd..d3fd56f 100644
--- a/content/browser/renderer_host/media/video_capture_controller.h
+++ b/content/browser/renderer_host/media/video_capture_controller.h
@@ -127,6 +127,7 @@
   void OnBufferRetired(int buffer_id) override;
   void OnError(media::VideoCaptureError error) override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnLog(const std::string& message) override;
   void OnStarted() override;
diff --git a/content/browser/renderer_host/media/video_capture_controller_event_handler.h b/content/browser/renderer_host/media/video_capture_controller_event_handler.h
index 44ba7d39..91f6f3f 100644
--- a/content/browser/renderer_host/media/video_capture_controller_event_handler.h
+++ b/content/browser/renderer_host/media/video_capture_controller_event_handler.h
@@ -63,6 +63,11 @@
       const ReadyBuffer& buffer,
       const std::vector<ReadyBuffer>& scaled_buffers) = 0;
 
+  // All subsequent buffers are guaranteed to have a crop version whose value
+  // is at least |crop_version|.
+  virtual void OnNewCropVersion(const VideoCaptureControllerID& id,
+                                uint32_t crop_version) = 0;
+
   virtual void OnFrameWithEmptyRegionCapture(
       const VideoCaptureControllerID& id) = 0;
 
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
index 7625bac..41f4532b 100644
--- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -106,6 +106,8 @@
                void(const VideoCaptureControllerID&, media::VideoCaptureError));
   MOCK_METHOD1(OnStarted, void(const VideoCaptureControllerID&));
   MOCK_METHOD1(OnStartedUsingGpuDecode, void(const VideoCaptureControllerID&));
+  MOCK_METHOD2(OnNewCropVersion,
+               void(const VideoCaptureControllerID&, uint32_t));
 
   void OnError(const VideoCaptureControllerID& id,
                media::VideoCaptureError error) override {
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc
index 1240091..0f6f57b4 100644
--- a/content/browser/renderer_host/media/video_capture_host.cc
+++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -396,6 +396,19 @@
     controller->OnFrameDropped(reason);
 }
 
+void VideoCaptureHost::OnNewCropVersion(const base::UnguessableToken& device_id,
+                                        uint32_t crop_version) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  const VideoCaptureControllerID controller_id(device_id);
+  if (!base::Contains(controllers_, controller_id) ||
+      !base::Contains(device_id_to_observer_map_, controller_id)) {
+    return;
+  }
+
+  device_id_to_observer_map_[controller_id]->OnNewCropVersion(crop_version);
+}
+
 void VideoCaptureHost::OnLog(const base::UnguessableToken& device_id,
                              const std::string& message) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/content/browser/renderer_host/media/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h
index f5c689a..1d2f2c7a 100644
--- a/content/browser/renderer_host/media/video_capture_host.h
+++ b/content/browser/renderer_host/media/video_capture_host.h
@@ -103,6 +103,8 @@
                              GetDeviceFormatsInUseCallback callback) override;
   void OnFrameDropped(const base::UnguessableToken& device_id,
                       media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(const base::UnguessableToken& device_id,
+                        uint32_t crop_version) override;
   void OnLog(const base::UnguessableToken& device_id,
              const std::string& message) override;
 
diff --git a/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index 1cb48dc7..c44e2b31 100644
--- a/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -187,6 +187,8 @@
   void OnBufferReady(const VideoCaptureControllerID& id,
                      const ReadyBuffer& buffer,
                      const std::vector<ReadyBuffer>& scaled_buffers) override {}
+  void OnNewCropVersion(const VideoCaptureControllerID& id,
+                        uint32_t crop_version) override {}
   void OnFrameWithEmptyRegionCapture(const VideoCaptureControllerID&) override {
   }
   void OnEnded(const VideoCaptureControllerID& id) override {}
diff --git a/content/browser/renderer_host/media/video_capture_unittest.cc b/content/browser/renderer_host/media/video_capture_unittest.cc
index 9db3221ea..1a51a18f 100644
--- a/content/browser/renderer_host/media/video_capture_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -207,6 +207,7 @@
   }
   MOCK_METHOD1(DoOnBufferReady, void(int32_t));
   MOCK_METHOD1(OnBufferDestroyed, void(int32_t));
+  MOCK_METHOD1(OnNewCropVersion, void(uint32_t));
 
   void StartCapture() {
     base::RunLoop run_loop;
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 722942ea..382b56b 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -4326,7 +4326,7 @@
   // We may have left a failed browser-initiated navigation in the address bar
   // to let the user edit it and try again.  Clear it now that content might
   // show up underneath it.
-  if (!frame_tree_.IsLoading() && GetPendingEntry())
+  if (!frame_tree_.IsLoadingIncludingInnerFrameTrees() && GetPendingEntry())
     DiscardPendingEntry(false);
 
   // Update the URL display.
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index d2e9926..8ea7d28 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -2938,15 +2938,46 @@
   // Note 1: For normal document created from a navigation, the policy container
   // is computed from the NavigationRequest and assigned in
   // DidCommitNewDocument().
-  if (GetParentOrOuterDocument()) {
+  if (parent_) {
+    SetPolicyContainerHost(parent_->policy_container_host()->Clone());
+  } else if (GetParentOrOuterDocument()) {
+    // In the MPArch implementation of FencedFrame, this RenderFrameHost's
+    // SiteInstance has been adjusted to match its parent. During navigations,
+    // COOP and COEP are used to determine the SiteInstance. It means that if
+    // SiteInstance has been inherited, COOP/COEP must also be inherited to
+    // avoid creating inconsistencies. See:
+    // https://chromium-review.googlesource.com/c/chromium/src/+/3645368
+    //
+    // TODO(https://crbug.com/1338603): What makes sense for GuestView?
+    // TODO(https://crbug.com/1338601): What makes sense for Portals?
+    const PolicyContainerPolicies& parent_policies =
+        GetParentOrOuterDocument()->policy_container_host()->policies();
+
+    // Note: the full constructor is used, to force developers to make an
+    // explicit decision when adding new fields to the PolicyContainer.
     SetPolicyContainerHost(
-        GetParentOrOuterDocument()->policy_container_host()->Clone());
+        base::MakeRefCounted<PolicyContainerHost>(PolicyContainerPolicies(
+            network::mojom::ReferrerPolicy::kDefault,
+            network::mojom::IPAddressSpace::kUnknown,
+            /*is_web_secure_context=*/false,
+            std::vector<network::mojom::ContentSecurityPolicyPtr>(),
+            parent_policies.cross_origin_opener_policy,
+            parent_policies.cross_origin_embedder_policy,
+            network::mojom::WebSandboxFlags::kNone,
+            /*anonymous=*/false)));
   } else if (frame_tree_node_->opener()) {
+    // During a `window.open(...)` without `noopener`, a new popup is created
+    // and always starts from the initial empty document. The opener has
+    // synchronous access toward its openee. So they must both share the same
+    // policies.
     SetPolicyContainerHost(frame_tree_node_->opener()
                                ->current_frame_host()
                                ->policy_container_host()
                                ->Clone());
   } else {
+    // In all the other cases, there is no environment to inherit policies
+    // from. This is "probably" a new top-level about:blank document created by
+    // the browser directly (omnibox, bookmarks, ...).
     PolicyContainerPolicies policies;
 
     // Main frames created by the browser are treated as belonging the `local`
@@ -8989,7 +9020,8 @@
   // the renderer process is done handling the URL.
   // TODO(crbug.com/1254130): Remove the test dependency on this behavior.
   if (!url.SchemeIs(url::kJavaScriptScheme)) {
-    bool was_loading = frame_tree()->LoadingTree()->IsLoading();
+    bool was_loading =
+        frame_tree()->LoadingTree()->IsLoadingIncludingInnerFrameTrees();
     is_loading_ = true;
     frame_tree_node()->DidStartLoading(true /* should_show_loading_ui */,
                                        was_loading);
@@ -11344,7 +11376,8 @@
             blink::mojom::SameDocumentNavigationType::
                 kNavigationApiTransitionWhile;
 
-    bool was_loading = frame_tree()->LoadingTree()->IsLoading();
+    bool was_loading =
+        frame_tree()->LoadingTree()->IsLoadingIncludingInnerFrameTrees();
     is_loading_ = true;
     frame_tree_node()->DidStartLoading(should_show_loading_ui, was_loading);
   }
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
index 6e1a105..0323826 100644
--- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -3809,8 +3809,9 @@
                 .party_context());
 }
 
-IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
-                       ComputeIsolationInfoForNavigationSiteForCookies) {
+IN_PROC_BROWSER_TEST_F(
+    RenderFrameHostImplBrowserTest,
+    DISABLED_ComputeIsolationInfoForNavigationSiteForCookies) {
   // Start second server for HTTPS.
   https_server()->ServeFilesFromSourceDirectory(GetTestDataFilePath());
   ASSERT_TRUE(https_server()->Start());
@@ -4912,7 +4913,9 @@
   EXPECT_TRUE(web_contents->IsDocumentOnLoadCompletedInPrimaryMainFrame());
 }
 
-IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, GetUkmSourceIds) {
+// Flaky on all platforms. crbug/1336851
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+                       DISABLED_GetUkmSourceIds) {
   ukm::TestAutoSetUkmRecorder recorder;
   // This test site has one cross-site iframe.
   GURL main_frame_url(
diff --git a/content/browser/resources/attribution_reporting/attribution_internals.ts b/content/browser/resources/attribution_reporting/attribution_internals.ts
index dd4ad77..9f48af7c0 100644
--- a/content/browser/resources/attribution_reporting/attribution_internals.ts
+++ b/content/browser/resources/attribution_reporting/attribution_internals.ts
@@ -284,6 +284,7 @@
   destinationOrigin: string;
   reportingOrigin: string;
   filters: string;
+  notFilters: string;
   debugKey: string;
   eventTriggers: string;
   eventLevelStatus: string;
@@ -296,6 +297,7 @@
     this.destinationOrigin = originToText(mojo.destinationOrigin);
     this.reportingOrigin = originToText(mojo.reportingOrigin);
     this.filters = JSON.stringify(mojo.filters, null, ' ');
+    this.notFilters = JSON.stringify(mojo.notFilters, null, ' ');
     this.debugKey = mojo.debugKey ? mojo.debugKey.value.toString() : '';
 
     this.eventTriggers = JSON.stringify(
@@ -354,9 +356,12 @@
       new ValueColumn<Trigger, string>('Report To', (e) => e.reportingOrigin),
       new ValueColumn<Trigger, string>('Debug Key', (e) => e.debugKey),
       new CodeColumn<Trigger>('Filters', (e) => e.filters),
+      new CodeColumn<Trigger>('Negated Filters', (e) => e.notFilters),
       new CodeColumn<Trigger>('Event Triggers', (e) => e.eventTriggers),
-      new CodeColumn<Trigger>('Aggregatable Triggers', (e) => e.aggregatableTriggers),
-      new CodeColumn<Trigger>('Aggregatable Values', (e) => e.aggregatableValues),
+      new CodeColumn<Trigger>(
+          'Aggregatable Triggers', (e) => e.aggregatableTriggers),
+      new CodeColumn<Trigger>(
+          'Aggregatable Values', (e) => e.aggregatableValues),
     ];
 
     this.emptyRowText = 'No triggers.';
diff --git a/content/browser/resources/quota/quota_internals.html b/content/browser/resources/quota/quota_internals.html
index 4e75af7..b09f9465 100644
--- a/content/browser/resources/quota/quota_internals.html
+++ b/content/browser/resources/quota/quota_internals.html
@@ -56,14 +56,13 @@
 
         <div id="usage-tabpanel" slot="panel">
           <!-- Usage and Quota -->
-          <h2>Host Usage Data</h2>
+          <h2>Bucket Usage Data</h2>
           <table>
             <thead>
-              <th>Host</th>
-              <th>Total Usage</th>
-              <th>Storage Type</th>
               <th>Storage Key</th>
+              <th>Storage Type</th>
               <th>Bucket</th>
+              <th>Usage (B)</th>
               <th>Use Count</th>
               <th>Last Accessed</th>
               <th>Last Modified</th>
@@ -93,11 +92,10 @@
     </template>
     <template id="usage-and-quota-row">
         <tr class="usage-and-quota-template-row">
-          <td class="host"></td>
-          <td class="total-usage"></td>
-          <td class="storage-type"></td>
           <td class="storage-key"></td>
+          <td class="storage-type"></td>
           <td class="bucket"></td>
+          <td class="usage"></td>
           <td class="use-count"></td>
           <td class="last-accessed"></td>
           <td class="last-modified"></td>
diff --git a/content/browser/resources/quota/quota_internals.ts b/content/browser/resources/quota/quota_internals.ts
index a595e3c..71eb8e7 100644
--- a/content/browser/resources/quota/quota_internals.ts
+++ b/content/browser/resources/quota/quota_internals.ts
@@ -11,9 +11,9 @@
 type BucketTableEntry = {
   'bucketId': bigint,
   'storageKey': string,
-  'host': string,
   'type': string,
   'name': string,
+  'usage': bigint,
   'useCount': bigint,
   'lastAccessed': Time,
   'lastModified': Time,
@@ -23,33 +23,30 @@
   entries: BucketTableEntry[],
 };
 
-type HostAndStorageTypeBucketTableEntry = {
+type StorageTypeBucketTableEntry = {
   'bucketId': string,
-  'storageKey': string,
   'name': string,
+  'usage': string,
   'useCount': string,
   'lastAccessed': string,
   'lastModified': string,
 };
 
-type StorageTypeHostUsageAndEntries = {
-  'hostUsage': string,
-  'entries': HostAndStorageTypeBucketTableEntry[],
-};
+type EntriesForStorageType = StorageTypeBucketTableEntry[];
 
 type StorageTypeEntries = {
   // key = storageType
-  [key: string]: StorageTypeHostUsageAndEntries,
+  [key: string]: EntriesForStorageType,
 };
 
-type HostData = {
+type StorageKeyData = {
   'bucketCount': number,
-  'hostEntries': StorageTypeEntries,
+  'storageKeyEntries': StorageTypeEntries,
 };
 
-type BucketTableEntriesByHost = {
-  // key = host
-  [key: string]: HostData,
+type BucketTableEntriesByStorageKey = {
+  // key = storageKey
+  [key: string]: StorageKeyData,
 };
 
 // Converts a mojo time to a JS time.
@@ -75,12 +72,6 @@
   return QuotaInternalsBrowserProxy.getInstance();
 }
 
-async function getHostUsageString(host: string, type: string): Promise<string> {
-  const currentTotalUsageObj =
-      await getProxy().getHostUsageForInternals(host, type);
-  return currentTotalUsageObj.hostUsage.toString();
-}
-
 async function renderDiskAvailabilityAndTempPoolSize() {
   const result = await getProxy().getDiskAvailabilityAndTempPoolSize();
 
@@ -148,24 +139,20 @@
   const bucketTable: RetrieveBucketsTableResult =
       await getProxy().retrieveBucketsTable();
   const bucketTableEntries: BucketTableEntry[] = bucketTable.entries;
-  const bucketTableEntriesByHost: BucketTableEntriesByHost = {};
+  const bucketTableEntriesByStorageKey: BucketTableEntriesByStorageKey = {};
 
-  /* Re-structure bucketTableEntries data to be accessible by a host key.
-   * bucketTableEntriesByHost = {
-   *   <host_string>: {
+  /* Re-structure bucketTableEntries data to be accessible by a storage key.
+   * bucketTableEntriesByStorageKey = {
+   *   <storage_key_string>: {
    *     bucketCount: <number>,
-   *     hostEntries: {
-   *       <storage_type_string>: {
-   *         hostUsage: <string>,
-   *         entries: [{
-   *           bucketId: <bigint>,
-   *           storageKey: <string>,
-   *           host: <string>,
-   *           type: <string>,
-   *           name: <string>,
-   *           useCount: <bigint>,
-   *           lastAccessed: <Time>,
-   *           lastModified: <Time>
+   *     storageKeyEntries: {
+   *       <storage_type_string>: [{
+   *         bucketId: <bigint>,
+   *         name: <string>,
+   *         usage: <bigint>,
+   *         useCount: <bigint>,
+   *         lastAccessed: <Time>,
+   *         lastModified: <Time>
    *          }]
    *        }
    *      }
@@ -174,10 +161,10 @@
 
   for (let i = 0; i < bucketTableEntries.length; i++) {
     const entry = bucketTableEntries[i];
-    const bucketTableEntryObj: HostAndStorageTypeBucketTableEntry = {
+    const bucketTableEntryObj: StorageTypeBucketTableEntry = {
       bucketId: entry.bucketId.toString(),
-      storageKey: entry.storageKey,
       name: entry.name,
+      usage: entry.usage.toString(),
       useCount: entry.useCount.toString(),
       lastAccessed: convertMojoTimeToJS(entry.lastAccessed)
                         .toLocaleString('en-US', {timeZoneName: 'short'}),
@@ -185,51 +172,53 @@
                         .toLocaleString('en-US', {timeZoneName: 'short'}),
     };
 
-    if (!(entry.host in bucketTableEntriesByHost)) {
-      bucketTableEntriesByHost[entry.host] = {
+    if (!(entry.storageKey in bucketTableEntriesByStorageKey)) {
+      bucketTableEntriesByStorageKey[entry.storageKey] = {
         'bucketCount': 0,
-        'hostEntries': {}
+        'storageKeyEntries': {}
       };
     }
-    if (!(entry.type in bucketTableEntriesByHost[entry.host]['hostEntries'])) {
-      bucketTableEntriesByHost[entry.host]['hostEntries'][entry.type] = {
-        'hostUsage': await getHostUsageString(entry.host, entry.type),
-        'entries': [bucketTableEntryObj]
-      };
-      bucketTableEntriesByHost[entry.host]['bucketCount'] += 1;
+    if (!(entry.type in bucketTableEntriesByStorageKey[entry.storageKey]
+                                                      ['storageKeyEntries'])) {
+      bucketTableEntriesByStorageKey
+          [entry.storageKey]['storageKeyEntries'][entry.type] =
+              [bucketTableEntryObj];
+      bucketTableEntriesByStorageKey[entry.storageKey]['bucketCount'] += 1;
     } else {
-      bucketTableEntriesByHost[entry.host]['hostEntries'][entry.type]['entries']
-          .push(bucketTableEntryObj);
-      bucketTableEntriesByHost[entry.host]['bucketCount'] += 1;
+      bucketTableEntriesByStorageKey
+          [entry.storageKey]['storageKeyEntries'][entry.type]
+              .push(bucketTableEntryObj);
+      bucketTableEntriesByStorageKey[entry.storageKey]['bucketCount'] += 1;
     }
   }
 
-  const hostKeys: string[] = Object.keys(bucketTableEntriesByHost);
+  const storageKeys: string[] = Object.keys(bucketTableEntriesByStorageKey);
 
   /* Populate the rows of the Usage and Quota table by iterating over:
-   * each host in bucketTableEntryByHost,
-   * each host's storage type(s),
+   * each storage key in bucketTableEntriesByStorageKey,
+   * each storage key's storage type(s),
    * and each storage type's bucket(s). */
 
-  // Iterate over each host key in bucketTableEntriesByHost.
-  for (let i = 0; i < hostKeys.length; i++) {
-    const host: string = hostKeys[i];
-    const hostRowSpan = bucketTableEntriesByHost[host]['bucketCount'];
-    const hostStorageTypes: StorageTypeEntries =
-        bucketTableEntriesByHost[host]['hostEntries'];
-    const storageTypes: string[] = Object.keys(hostStorageTypes);
+  // Iterate over each storageKey in bucketTableEntriesByStorageKey.
+  for (let i = 0; i < storageKeys.length; i++) {
+    const storageKey: string = storageKeys[i];
+    const storageKeyRowSpan =
+        bucketTableEntriesByStorageKey[storageKey]['bucketCount'];
+    const bucketsByStorageType: StorageTypeEntries =
+        bucketTableEntriesByStorageKey[storageKey]['storageKeyEntries'];
+    const storageTypes: string[] = Object.keys(bucketsByStorageType);
 
-    // Iterate over each storageType key for a given host.
+    // Iterate over each storageType for a given storage key.
     for (let j = 0; j < storageTypes.length; j++) {
       const storageType: string = storageTypes[j];
-      const bucketsForStorageType: HostAndStorageTypeBucketTableEntry[] =
-          hostStorageTypes[storageType]['entries'];
-      const usageAndStorageTypeRowSpan: number =
-          hostStorageTypes[storageType]['entries'].length;
+      const bucketsForStorageType: StorageTypeBucketTableEntry[] =
+          bucketsByStorageType[storageType];
+      const storageTypeRowSpan: number =
+          bucketsByStorageType[storageType].length;
 
-      // Iterate over each bucket for a given host and storageType.
+      // Iterate over each bucket for a given storageKey and storageType.
       for (let k = 0; k < bucketsForStorageType.length; k++) {
-        const isFirstHostRow: boolean = (j === 0 && k === 0);
+        const isFirstStorageKeyRow: boolean = (j === 0 && k === 0);
         const isFirstStorageType: boolean = (k === 0);
 
         // Initialize a Usage and Quota table row template.
@@ -243,21 +232,18 @@
             rowTemplate.cloneNode(true) as HTMLTemplateElement;
         const usageAndQuotaRow = usageAndQuotaRowTemplate.content;
 
-        usageAndQuotaRow.querySelector('.host')!.textContent = host;
-        usageAndQuotaRow.querySelector('.host')!.setAttribute(
-            'rowspan', `${hostRowSpan}`);
-        usageAndQuotaRow.querySelector('.total-usage')!.textContent =
-            hostStorageTypes[storageType]['hostUsage'];
-        usageAndQuotaRow.querySelector('.total-usage')!.setAttribute(
-            'rowspan', `${usageAndStorageTypeRowSpan}`);
+        usageAndQuotaRow.querySelector('.storage-key')!.textContent =
+            storageKey;
+        usageAndQuotaRow.querySelector('.storage-key')!.setAttribute(
+            'rowspan', `${storageKeyRowSpan}`);
         usageAndQuotaRow.querySelector('.storage-type')!.textContent =
             storageType;
         usageAndQuotaRow.querySelector('.storage-type')!.setAttribute(
-            'rowspan', `${usageAndStorageTypeRowSpan}`);
-        usageAndQuotaRow.querySelector('.storage-key')!.textContent =
-            bucketsForStorageType[k].storageKey;
+            'rowspan', `${storageTypeRowSpan}`);
         usageAndQuotaRow.querySelector('.bucket')!.textContent =
-            bucketsForStorageType[k].bucketId;
+            bucketsForStorageType[k].name;
+        usageAndQuotaRow.querySelector('.usage')!.textContent =
+            bucketsForStorageType[k].usage;
         usageAndQuotaRow.querySelector('.use-count')!.textContent =
             bucketsForStorageType[k].useCount;
         usageAndQuotaRow.querySelector('.last-accessed')!.textContent =
@@ -265,20 +251,20 @@
         usageAndQuotaRow.querySelector('.last-modified')!.textContent =
             bucketsForStorageType[k].lastModified;
 
-        /* If the current row is not the first of its kind for a given host,
-         * remove the host cell when appending the row to the table body.
-         * This creates a nested row to the right of the host cell. */
-        if (!isFirstHostRow) {
-          usageAndQuotaRow.querySelector('.host')!.remove();
+        /* If the current row is not the first of its kind for a given storage
+         * key, remove the storage key cell when appending the row to the table
+         * body. This creates a nested row to the right of the storage key cell.
+         */
+        if (!isFirstStorageKeyRow) {
+          usageAndQuotaRow.querySelector('.storage-key')!.remove();
         }
 
         /* If the current storage type (temporary, persistent, syncable) is not
-         * the first of its kind for a given host and storage type,
-         * remove the Total Usage and Storage Type cells from the row before
+         * the first of its kind for a given storage key and storage type,
+         * remove the Storage Type cells from the row before
          * appending the row to the table body.
          * This creates a nested row to the right of the Storage Type cell. */
         if (!isFirstStorageType) {
-          usageAndQuotaRow.querySelector('.total-usage')!.remove();
           usageAndQuotaRow.querySelector('.storage-type')!.remove();
         }
         tableBody.appendChild(usageAndQuotaRow);
diff --git a/content/browser/resources/quota/quota_internals_browser_proxy.ts b/content/browser/resources/quota/quota_internals_browser_proxy.ts
index 448f30a..88262b9 100644
--- a/content/browser/resources/quota/quota_internals_browser_proxy.ts
+++ b/content/browser/resources/quota/quota_internals_browser_proxy.ts
@@ -10,9 +10,9 @@
 type BucketTableEntry = {
   'bucketId': bigint,
   'storageKey': string,
-  'host': string,
   'type': string,
   'name': string,
+  'usage': bigint,
   'useCount': bigint,
   'lastAccessed': Time,
   'lastModified': Time,
@@ -24,10 +24,6 @@
   tempPoolSize: bigint,
 };
 
-type GetHostUsageForInternalsResult = {
-  'hostUsage': bigint,
-};
-
 type GetGlobalUsageResult = {
   usage: bigint,
   unlimitedUsage: bigint,
@@ -105,13 +101,6 @@
     return this.handler.retrieveBucketsTable();
   }
 
-  async getHostUsageForInternals(host: string, storageType: string):
-      Promise<GetHostUsageForInternalsResult> {
-    const totalUsage = await this.handler.getHostUsageForInternals(
-        host, enumerateStorageType(storageType));
-    return totalUsage;
-  }
-
   static getInstance(): QuotaInternalsBrowserProxy {
     return instance || (instance = new QuotaInternalsBrowserProxy());
   }
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc
index 333e930b..cbf35d2 100644
--- a/content/browser/site_instance_impl_unittest.cc
+++ b/content/browser/site_instance_impl_unittest.cc
@@ -27,7 +27,6 @@
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/site_info.h"
 #include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/webui/content_web_ui_controller_factory.h"
 #include "content/browser/webui/web_ui_controller_factory_registry.h"
 #include "content/public/browser/browser_or_resource_context.h"
 #include "content/public/browser/site_isolation_policy.h"
@@ -117,9 +116,6 @@
 
   int site_instance_delete_count_ = 0;
   int browsing_instance_delete_count_ = 0;
-
-  ScopedWebUIControllerFactoryRegistration factory_registration_{
-      ContentWebUIControllerFactory::GetInstance()};
 };
 
 class SiteInstanceTest : public testing::Test {
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 69df47d..0051814 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -2156,7 +2156,7 @@
 void StoragePartitionImpl::ClearDataImpl(
     uint32_t remove_mask,
     uint32_t quota_storage_remove_mask,
-    const GURL& storage_origin,
+    const blink::StorageKey& storage_key,
     OriginMatcherFunction origin_matcher,
     CookieDeletionFilterPtr cookie_deletion_filter,
     bool perform_storage_cleanup,
@@ -2165,7 +2165,6 @@
     base::OnceClosure callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  const blink::StorageKey storage_key(url::Origin::Create(storage_origin));
   for (auto& observer : data_removal_observers_) {
     auto filter = CreateGenericOriginMatcher(storage_key, origin_matcher,
                                              special_storage_policy_);
@@ -2566,24 +2565,25 @@
   CookieDeletionFilterPtr deletion_filter = CookieDeletionFilter::New();
   if (!storage_origin.host().empty())
     deletion_filter->host_name = storage_origin.host();
-  ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin,
+  ClearDataImpl(remove_mask, quota_storage_remove_mask,
+                blink::StorageKey(url::Origin::Create(storage_origin)),
                 OriginMatcherFunction(), std::move(deletion_filter), false,
                 base::Time(), base::Time::Max(), std::move(callback));
 }
 
 void StoragePartitionImpl::ClearData(uint32_t remove_mask,
                                      uint32_t quota_storage_remove_mask,
-                                     const GURL& storage_origin,
+                                     const blink::StorageKey& storage_key,
                                      const base::Time begin,
                                      const base::Time end,
                                      base::OnceClosure callback) {
   DCHECK(initialized_);
   CookieDeletionFilterPtr deletion_filter = CookieDeletionFilter::New();
-  if (!storage_origin.host().empty())
-    deletion_filter->host_name = storage_origin.host();
+  if (!storage_key.origin().host().empty())
+    deletion_filter->host_name = storage_key.origin().host();
   bool perform_storage_cleanup =
-      begin.is_null() && end.is_max() && storage_origin.is_empty();
-  ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin,
+      begin.is_null() && end.is_max() && storage_key.origin().opaque();
+  ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_key,
                 OriginMatcherFunction(), std::move(deletion_filter),
                 perform_storage_cleanup, begin, end, std::move(callback));
 }
@@ -2598,7 +2598,7 @@
     const base::Time end,
     base::OnceClosure callback) {
   DCHECK(initialized_);
-  ClearDataImpl(remove_mask, quota_storage_remove_mask, GURL(),
+  ClearDataImpl(remove_mask, quota_storage_remove_mask, blink::StorageKey(),
                 std::move(origin_matcher), std::move(cookie_deletion_filter),
                 perform_storage_cleanup, begin, end, std::move(callback));
 }
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index b0ddd571..b30c2a51 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -208,7 +208,7 @@
                           base::OnceClosure callback) override;
   void ClearData(uint32_t remove_mask,
                  uint32_t quota_storage_remove_mask,
-                 const GURL& storage_origin,
+                 const blink::StorageKey& storage_key,
                  const base::Time begin,
                  const base::Time end,
                  base::OnceClosure callback) override;
@@ -566,11 +566,12 @@
   // state.
   void OnStorageServiceDisconnected();
 
-  // We will never have both remove_origin be populated and a cookie_matcher.
+  // Clears the data specified by the `storage_key` or `origin_matcher`.
+  // We will never have both `storage_key` be populated and a `origin_matcher`.
   void ClearDataImpl(
       uint32_t remove_mask,
       uint32_t quota_storage_remove_mask,
-      const GURL& remove_origin,
+      const blink::StorageKey& storage_key,
       OriginMatcherFunction origin_matcher,
       network::mojom::CookieDeletionFilterPtr cookie_deletion_filter,
       bool perform_storage_cleanup,
diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc
index 1d2471e..aded50d836 100644
--- a/content/browser/storage_partition_impl_map.cc
+++ b/content/browser/storage_partition_impl_map.cc
@@ -45,6 +45,7 @@
 #include "crypto/sha2.h"
 #include "services/network/public/cpp/features.h"
 #include "storage/browser/blob/blob_storage_context.h"
+#include "third_party/blink/public/common/storage_key/storage_key.h"
 
 namespace content {
 
@@ -393,8 +394,8 @@
     active_partition->ClearData(
         // All except shader cache.
         ~StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE,
-        StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(), base::Time(),
-        base::Time::Max(), subtask_done_callback);
+        StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, blink::StorageKey(),
+        base::Time(), base::Time::Max(), subtask_done_callback);
   }
 
   // Start a best-effort delete of the on-disk storage excluding paths that are
@@ -444,6 +445,17 @@
   }
 }
 
+void StoragePartitionImplMap::DisposeInMemory(StoragePartition* partition) {
+  for (PartitionMap::const_iterator it = partitions_.begin();
+       it != partitions_.end(); ++it) {
+    if (it->second.get() == partition) {
+      DCHECK(it->first.in_memory());
+      partitions_.erase(it);
+      return;
+    }
+  }
+}
+
 void StoragePartitionImplMap::PostCreateInitialization(
     StoragePartitionImpl* partition,
     bool in_memory) {
diff --git a/content/browser/storage_partition_impl_map.h b/content/browser/storage_partition_impl_map.h
index d0a696d..8d508ffc 100644
--- a/content/browser/storage_partition_impl_map.h
+++ b/content/browser/storage_partition_impl_map.h
@@ -62,6 +62,9 @@
 
   void ForEach(BrowserContext::StoragePartitionCallback callback);
 
+  // Disposes the given in-memory storage partition.
+  void DisposeInMemory(StoragePartition* partition);
+
   size_t size() const { return partitions_.size(); }
 
  private:
diff --git a/content/browser/storage_partition_impl_map_unittest.cc b/content/browser/storage_partition_impl_map_unittest.cc
index 2faf0414..fda3e36 100644
--- a/content/browser/storage_partition_impl_map_unittest.cc
+++ b/content/browser/storage_partition_impl_map_unittest.cc
@@ -86,4 +86,40 @@
   }
 }
 
+TEST(StoragePartitionImplMapTest, Dispose) {
+  BrowserTaskEnvironment task_environment;
+  TestBrowserContext browser_context;
+  StoragePartitionImplMap map(&browser_context);
+
+  // Start with no partitions.
+  ASSERT_EQ(map.size(), 0u);
+
+  // Create 1 in-memory partition.
+  const auto kInMemoryConfig = content::StoragePartitionConfig::Create(
+      &browser_context, "foo", /*partition_name=*/"", /*in_memory=*/true);
+  auto* partition = map.Get(kInMemoryConfig, /*can_create=*/true);
+  ASSERT_TRUE(partition);
+
+  // Dispose the in-memory partition.
+  map.DisposeInMemory(partition);
+  EXPECT_EQ(map.size(), 0u);
+
+  // No op to dispose the already disposed partition.
+  map.DisposeInMemory(partition);
+  EXPECT_EQ(map.size(), 0u);
+
+  // No op to dispose nullptr.
+  map.DisposeInMemory(nullptr);
+  EXPECT_EQ(map.size(), 0u);
+
+#if !BUILDFLAG(IS_ANDROID) && DCHECK_IS_ON()
+  // Death test for non-android and when DCHECK is on.
+  // Disposing an on-disk storage partition is not supported.
+  const auto kOnDiskConfig = content::StoragePartitionConfig::Create(
+      &browser_context, "foo", /*partition_name=*/"", /*in_memory=*/false);
+  auto* on_disk_partition = map.Get(kOnDiskConfig, /*can_create=*/true);
+  EXPECT_DEATH_IF_SUPPORTED(map.DisposeInMemory(on_disk_partition), "");
+#endif
+}
+
 }  // namespace content
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index 91449bd..24cd851 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -791,9 +791,10 @@
 
 void ClearQuotaData(content::StoragePartition* partition,
                     base::RunLoop* loop_to_quit) {
-  partition->ClearData(
-      kAllQuotaRemoveMask, StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
-      GURL(), base::Time(), base::Time::Max(), loop_to_quit->QuitClosure());
+  partition->ClearData(kAllQuotaRemoveMask,
+                       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+                       blink::StorageKey(), base::Time(), base::Time::Max(),
+                       loop_to_quit->QuitClosure());
 }
 
 void ClearQuotaDataWithOriginMatcher(
@@ -811,10 +812,10 @@
                              const GURL& remove_origin,
                              const base::Time delete_begin,
                              base::RunLoop* loop_to_quit) {
-  partition->ClearData(kAllQuotaRemoveMask,
-                       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
-                       remove_origin, delete_begin, base::Time::Max(),
-                       loop_to_quit->QuitClosure());
+  partition->ClearData(
+      kAllQuotaRemoveMask, StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+      blink::StorageKey(url::Origin::Create(remove_origin)), delete_begin,
+      base::Time::Max(), loop_to_quit->QuitClosure());
 }
 
 void ClearQuotaDataForNonPersistent(content::StoragePartition* partition,
@@ -822,7 +823,7 @@
                                     base::RunLoop* loop_to_quit) {
   partition->ClearData(kAllQuotaRemoveMask,
                        ~StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT,
-                       GURL(), delete_begin, base::Time::Max(),
+                       blink::StorageKey(), delete_begin, base::Time::Max(),
                        loop_to_quit->QuitClosure());
 }
 
@@ -831,8 +832,9 @@
                   const base::Time delete_end,
                   base::RunLoop* run_loop) {
   partition->ClearData(StoragePartition::REMOVE_DATA_MASK_COOKIES,
-                       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
-                       delete_begin, delete_end, run_loop->QuitClosure());
+                       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+                       blink::StorageKey(), delete_begin, delete_end,
+                       run_loop->QuitClosure());
 }
 
 void ClearCookiesMatchingInfo(content::StoragePartition* partition,
@@ -866,8 +868,9 @@
 void ClearData(content::StoragePartition* partition, base::RunLoop* run_loop) {
   base::Time time;
   partition->ClearData(StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE,
-                       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
-                       time, time, run_loop->QuitClosure());
+                       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+                       blink::StorageKey(), time, time,
+                       run_loop->QuitClosure());
 }
 
 void ClearCodeCache(content::StoragePartition* partition,
@@ -891,8 +894,9 @@
                             base::RunLoop* run_loop) {
   partition->ClearData(
       StoragePartitionImpl::REMOVE_DATA_MASK_PLUGIN_PRIVATE_DATA,
-      StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, storage_origin,
-      delete_begin, delete_end, run_loop->QuitClosure());
+      StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+      blink::StorageKey(url::Origin::Create(storage_origin)), delete_begin,
+      delete_end, run_loop->QuitClosure());
 }
 #endif  // BUILDFLAG(ENABLE_PLUGINS)
 
@@ -901,8 +905,9 @@
                          const base::Time delete_end,
                          base::RunLoop* run_loop) {
   partition->ClearData(StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS,
-                       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
-                       delete_begin, delete_end, run_loop->QuitClosure());
+                       StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+                       blink::StorageKey(), delete_begin, delete_end,
+                       run_loop->QuitClosure());
 }
 
 void ClearInterestGroupPermissionsCache(content::StoragePartition* partition,
@@ -911,8 +916,8 @@
                                         base::RunLoop* run_loop) {
   partition->ClearData(
       StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUP_PERMISSIONS_CACHE,
-      StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(), delete_begin,
-      delete_end, run_loop->QuitClosure());
+      StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, blink::StorageKey(),
+      delete_begin, delete_end, run_loop->QuitClosure());
 }
 
 bool FilterMatchesCookie(const CookieDeletionFilterPtr& filter,
@@ -2030,7 +2035,7 @@
   base::RunLoop run_loop;
   partition->ClearData(
       StoragePartition::REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_SITE_CREATED, 0,
-      source.common_info().impression_origin().GetURL(), now, now,
+      blink::StorageKey(source.common_info().impression_origin()), now, now,
       run_loop.QuitClosure());
   run_loop.Run();
 
@@ -2052,9 +2057,10 @@
 
   // Arbitrary non-conversions mask.
   base::RunLoop run_loop;
-  partition->ClearData(StoragePartition::REMOVE_DATA_MASK_COOKIES, 0,
-                       source.common_info().impression_origin().GetURL(), now,
-                       now, run_loop.QuitClosure());
+  partition->ClearData(
+      StoragePartition::REMOVE_DATA_MASK_COOKIES, 0,
+      blink::StorageKey(source.common_info().impression_origin()), now, now,
+      run_loop.QuitClosure());
   run_loop.Run();
   EXPECT_FALSE(GetAttributionReportsForTesting(attribution_manager).empty());
 }
@@ -2080,7 +2086,7 @@
   base::RunLoop run_loop;
   partition->ClearData(
       StoragePartition::REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_SITE_CREATED, 0,
-      GURL(), now, now, run_loop.QuitClosure());
+      blink::StorageKey(), now, now, run_loop.QuitClosure());
   run_loop.Run();
 
   EXPECT_TRUE(GetAttributionReportsForTesting(attribution_manager).empty());
@@ -2163,7 +2169,8 @@
       observer,
       OnOriginDataCleared(kTestClearMask, testing::Truly(origin_callback_valid),
                           kBeginTime, kEndTime));
-  partition->ClearData(kTestClearMask, kTestQuotaClearMask, kTestOrigin,
+  partition->ClearData(kTestClearMask, kTestQuotaClearMask,
+                       blink::StorageKey(url::Origin::Create(kTestOrigin)),
                        kBeginTime, kEndTime, base::DoNothing());
   testing::Mock::VerifyAndClearExpectations(&observer);
 
@@ -2404,7 +2411,8 @@
   EXPECT_CALL(*aggregation_service_ptr,
               ClearData(kBeginTime, kEndTime, testing::_))
       .WillOnce(testing::Invoke(invoke_callback));
-  partition->ClearData(kTestClearMask, kTestQuotaClearMask, kTestOrigin,
+  partition->ClearData(kTestClearMask, kTestQuotaClearMask,
+                       blink::StorageKey(url::Origin::Create(kTestOrigin)),
                        kBeginTime, kEndTime, base::DoNothing());
   testing::Mock::VerifyAndClearExpectations(aggregation_service_ptr);
 
@@ -2424,8 +2432,8 @@
   EXPECT_CALL(*aggregation_service_ptr,
               ClearData(kBeginTime, kEndTime, testing::_))
       .WillOnce(testing::Invoke(invoke_callback));
-  partition->ClearData(kTestClearMask, kTestQuotaClearMask, GURL(), kBeginTime,
-                       kEndTime, base::DoNothing());
+  partition->ClearData(kTestClearMask, kTestQuotaClearMask, blink::StorageKey(),
+                       kBeginTime, kEndTime, base::DoNothing());
 }
 
 // https://crbug.com/1221382
diff --git a/content/browser/url_loader_factory_params_helper.cc b/content/browser/url_loader_factory_params_helper.cc
index b0cda918..ff719ad5 100644
--- a/content/browser/url_loader_factory_params_helper.cc
+++ b/content/browser/url_loader_factory_params_helper.cc
@@ -222,11 +222,12 @@
       static_cast<StoragePartitionImpl*>(process->GetStoragePartition())
           ->CreateCookieAccessObserverForServiceWorker(),
       std::move(url_loader_network_observer), std::move(devtools_observer),
-      // Since ExecutionContext::IsFeatureEnabled returns
-      // false in non-Document contexts, no worker should ever
-      // execute a trust token redemption or signing operation,
-      // as these operations require the Permissions Policy feature.
-      network::mojom::TrustTokenRedemptionPolicy::kForbid, debug_tag);
+      // Trust Token redemption and signing operations require the Permissions
+      // Policy. It seems Permissions Policy in worker contexts
+      // is currently an open issue (as of 06/21/2022):
+      // https://github.com/w3c/webappsec-permissions-policy/issues/207.
+      network::mojom::TrustTokenRedemptionPolicy::kPotentiallyPermit,
+      debug_tag);
 }
 
 // static
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
index df1a5cc7..4cadc12 100644
--- a/content/browser/utility_process_host.cc
+++ b/content/browser/utility_process_host.cc
@@ -300,6 +300,7 @@
       switches::kForceWaveAudio,
       switches::kRaiseTimerFrequency,
       switches::kTrySupportedChannelLayouts,
+      switches::kUseFakeAudioCaptureTimestamps,
       switches::kWaveOutBuffers,
       switches::kWebXrForceRuntime,
       sandbox::policy::switches::kAddXrAppContainerCaps,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index ee5067b9..93b02c48 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1799,8 +1799,10 @@
   ForEachFrameTree(base::BindRepeating([](FrameTree* frame_tree) {
     // For prerendering, we don't want to activate a prerendered page loaded
     // with a stale UA and will handle it even if it finishes loading.
-    if (!frame_tree->IsLoading() && !frame_tree->is_prerendering())
+    if (!frame_tree->IsLoadingIncludingInnerFrameTrees() &&
+        !frame_tree->is_prerendering()) {
       return;
+    }
 
     NavigationEntry* entry = frame_tree->controller().GetVisibleEntry();
     if (!entry || !entry->GetIsOverridingUserAgent())
@@ -1928,7 +1930,7 @@
 }
 
 bool WebContentsImpl::IsLoading() {
-  return primary_frame_tree_.IsLoading();
+  return primary_frame_tree_.IsLoadingIncludingInnerFrameTrees();
 }
 
 double WebContentsImpl::GetLoadProgress() {
diff --git a/content/browser/web_contents/web_contents_view_aura_unittest.cc b/content/browser/web_contents/web_contents_view_aura_unittest.cc
index 34913c12..35b8b4b 100644
--- a/content/browser/web_contents/web_contents_view_aura_unittest.cc
+++ b/content/browser/web_contents/web_contents_view_aura_unittest.cc
@@ -244,8 +244,21 @@
   EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE);
 }
 
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
-TEST_F(WebContentsViewAuraTest, DragDropFiles) {
+// TODO(crbug.com/1231509): Enable these tests on Fuchsia when
+// OSExchangeDataProviderFactory::CreateProvider is implemented.
+#if BUILDFLAG(IS_FUCHSIA)
+#define MAYBE_DragDropFiles DISABLED_DragDropFiles
+#define MAYBE_DragDropFilesOriginateFromRenderer \
+  DISABLED_DragDropFilesOriginateFromRenderer
+#define MAYBE_DragDropImageFromRenderer DISABLED_DragDropImageFromRenderer
+#else
+#define MAYBE_DragDropFiles DragDropFiles
+#define MAYBE_DragDropFilesOriginateFromRenderer \
+  DragDropFilesOriginateFromRenderer
+#define MAYBE_DragDropImageFromRenderer DragDropImageFromRenderer
+#endif
+
+TEST_F(WebContentsViewAuraTest, MAYBE_DragDropFiles) {
   WebContentsViewAura* view = GetView();
   auto data = std::make_unique<ui::OSExchangeData>();
 
@@ -339,7 +352,7 @@
   }
 }
 
-TEST_F(WebContentsViewAuraTest, DragDropFilesOriginateFromRenderer) {
+TEST_F(WebContentsViewAuraTest, MAYBE_DragDropFilesOriginateFromRenderer) {
   WebContentsViewAura* view = GetView();
   auto data = std::make_unique<ui::OSExchangeData>();
 
@@ -428,7 +441,7 @@
 #endif
 }
 
-TEST_F(WebContentsViewAuraTest, DragDropImageFromRenderer) {
+TEST_F(WebContentsViewAuraTest, MAYBE_DragDropImageFromRenderer) {
   WebContentsViewAura* view = GetView();
 
   const base::FilePath filename(FILE_PATH_LITERAL("image.jpg"));
@@ -515,8 +528,6 @@
             drop_complete_data_->drop_data.file_contents_content_disposition);
 }
 
-#endif
-
 #if BUILDFLAG(IS_WIN)
 
 TEST_F(WebContentsViewAuraTest, DragDropVirtualFiles) {
@@ -720,7 +731,7 @@
       drop_complete_data_->drop_data.file_contents_source_url.is_empty());
   EXPECT_TRUE(drop_complete_data_->drop_data.file_contents.empty());
 }
-#endif
+#endif  // BUILDFLAG(IS_WIN)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 
diff --git a/content/browser/webui/content_web_ui_controller_factory.cc b/content/browser/webui/content_web_ui_controller_factory.cc
deleted file mode 100644
index 4e23696..0000000
--- a/content/browser/webui/content_web_ui_controller_factory.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2013 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 "content/browser/webui/content_web_ui_controller_factory.h"
-
-#include "content/public/browser/web_ui.h"
-
-namespace content {
-
-WebUI::TypeID ContentWebUIControllerFactory::GetWebUIType(
-    BrowserContext* browser_context,
-    const GURL& url) {
-  return WebUI::kNoWebUI;
-}
-
-bool ContentWebUIControllerFactory::UseWebUIForURL(
-    BrowserContext* browser_context,
-    const GURL& url) {
-  return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
-}
-
-std::unique_ptr<WebUIController>
-ContentWebUIControllerFactory::CreateWebUIControllerForURL(WebUI* web_ui,
-                                                           const GURL& url) {
-  return nullptr;
-}
-
-// static
-ContentWebUIControllerFactory* ContentWebUIControllerFactory::GetInstance() {
-  return base::Singleton<ContentWebUIControllerFactory>::get();
-}
-
-ContentWebUIControllerFactory::ContentWebUIControllerFactory() {
-}
-
-ContentWebUIControllerFactory::~ContentWebUIControllerFactory() {
-}
-
-}  // namespace content
diff --git a/content/browser/webui/content_web_ui_controller_factory.h b/content/browser/webui/content_web_ui_controller_factory.h
deleted file mode 100644
index d86d3385..0000000
--- a/content/browser/webui/content_web_ui_controller_factory.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2013 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 CONTENT_BROWSER_WEBUI_CONTENT_WEB_UI_CONTROLLER_FACTORY_H_
-#define CONTENT_BROWSER_WEBUI_CONTENT_WEB_UI_CONTROLLER_FACTORY_H_
-
-#include "base/memory/singleton.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/browser/web_ui_controller_factory.h"
-
-namespace content {
-
-class CONTENT_EXPORT ContentWebUIControllerFactory
-    : public WebUIControllerFactory {
- public:
-  static ContentWebUIControllerFactory* GetInstance();
-
-  ContentWebUIControllerFactory(const ContentWebUIControllerFactory&) = delete;
-  ContentWebUIControllerFactory& operator=(
-      const ContentWebUIControllerFactory&) = delete;
-
-  // WebUIControllerFactory:
-  WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
-                             const GURL& url) override;
-  bool UseWebUIForURL(BrowserContext* browser_context,
-                      const GURL& url) override;
-  std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
-      WebUI* web_ui,
-      const GURL& url) override;
-
- protected:
-  ContentWebUIControllerFactory();
-  ~ContentWebUIControllerFactory() override;
-
- private:
-  friend struct base::DefaultSingletonTraits<ContentWebUIControllerFactory>;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_WEBUI_CONTENT_WEB_UI_CONTROLLER_FACTORY_H_
diff --git a/content/browser/webui/web_ui_browsertest.cc b/content/browser/webui/web_ui_browsertest.cc
index 2133143..6b87699 100644
--- a/content/browser/webui/web_ui_browsertest.cc
+++ b/content/browser/webui/web_ui_browsertest.cc
@@ -23,7 +23,6 @@
 #include "content/browser/fenced_frame/fenced_frame.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/webui/content_web_ui_controller_factory.h"
 #include "content/browser/webui/web_ui_controller_factory_registry.h"
 #include "content/browser/webui/web_ui_impl.h"
 #include "content/public/browser/child_process_security_policy.h"
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 9fa2fad..a700c36e 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -371,6 +371,8 @@
           {"PrefersColorSchemeClientHintHeader",
            blink::features::kPrefersColorSchemeClientHintHeader},
           {"FirstPartySets", features::kFirstPartySets},
+          {"QuickIntensiveWakeUpThrottlingAfterLoading",
+           blink::features::kQuickIntensiveWakeUpThrottlingAfterLoading},
           {"SanitizerAPI", blink::features::kSanitizerAPI},
           {"SanitizerAPIv0", blink::features::kSanitizerAPIv0},
           {"SecureContextFixForWorkers",
diff --git a/content/common/background_fetch/background_fetch_types.cc b/content/common/background_fetch/background_fetch_types.cc
index f0536acb..e5bfce12 100644
--- a/content/common/background_fetch/background_fetch_types.cc
+++ b/content/common/background_fetch/background_fetch_types.cc
@@ -58,7 +58,8 @@
       request->referrer.Clone(), request->credentials_mode, request->cache_mode,
       request->redirect_mode, request->integrity, request->priority,
       request->fetch_window_id, request->keepalive, request->is_reload,
-      request->is_history_navigation, request->devtools_stack_id);
+      request->is_history_navigation, request->devtools_stack_id,
+      request->trust_token_params.Clone());
 }
 
 }  // namespace content
diff --git a/content/common/fetch/fetch_request_type_converters.cc b/content/common/fetch/fetch_request_type_converters.cc
index e6faf7f..69358cc 100644
--- a/content/common/fetch/fetch_request_type_converters.cc
+++ b/content/common/fetch/fetch_request_type_converters.cc
@@ -95,6 +95,9 @@
   output->is_history_navigation =
       input.transition_type & ui::PAGE_TRANSITION_FORWARD_BACK;
   output->devtools_stack_id = input.devtools_stack_id;
+  if (input.trust_token_params) {
+    output->trust_token_params = input.trust_token_params->Clone();
+  }
   return output;
 }
 
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h
index 8afc8fb4..1ce40cb 100644
--- a/content/public/browser/browser_context.h
+++ b/content/public/browser/browser_context.h
@@ -157,6 +157,12 @@
   using StoragePartitionCallback =
       base::RepeatingCallback<void(StoragePartition*)>;
   void ForEachStoragePartition(StoragePartitionCallback callback);
+
+  // Disposes the given StoragePartition. Only in-memory storage partition
+  // disposal is supported. Caller needs to be careful that no outstanding
+  // references are left to access the disposed storage partition.
+  void DisposeStoragePartition(StoragePartition* storage_partition);
+
   // Returns the number of StoragePartitions that exist for `this`
   // BrowserContext.
   size_t GetStoragePartitionCount();
diff --git a/content/public/browser/download_manager_delegate.h b/content/public/browser/download_manager_delegate.h
index df0bf67a..1fae76fe 100644
--- a/content/public/browser/download_manager_delegate.h
+++ b/content/public/browser/download_manager_delegate.h
@@ -12,7 +12,6 @@
 #include "components/download/public/common/download_danger_type.h"
 #include "components/download/public/common/download_item.h"
 #include "components/download/public/common/download_item_rename_handler.h"
-#include "components/download/public/common/download_schedule.h"
 #include "components/download/public/common/download_url_parameters.h"
 #include "components/download/public/common/quarantine_connection.h"
 #include "content/common/content_export.h"
@@ -72,7 +71,6 @@
     const base::FilePath& intermediate_path,
     const base::FilePath& display_name,
     const std::string& mime_type,
-    absl::optional<download::DownloadSchedule> download_schedule,
     download::DownloadInterruptReason interrupt_reason)>;
 
 // Called when a download delayed by the delegate has completed.
diff --git a/content/public/browser/media_stream_request.h b/content/public/browser/media_stream_request.h
index a2aa228..255a3777 100644
--- a/content/public/browser/media_stream_request.h
+++ b/content/public/browser/media_stream_request.h
@@ -82,6 +82,10 @@
   // audio being played out locally.
   bool disable_local_echo;
 
+  // If audio is requested, |exclude_system_audio| can indicate that
+  // system-audio should nevertheless not be offered to the user.
+  bool exclude_system_audio = false;
+
   // Flag to indicate whether the request is for PTZ use.
   bool request_pan_tilt_zoom_permission;
 };
diff --git a/content/public/browser/preloading_data.h b/content/public/browser/preloading_data.h
index 8c3942da..9f10143 100644
--- a/content/public/browser/preloading_data.h
+++ b/content/public/browser/preloading_data.h
@@ -71,7 +71,8 @@
 class CONTENT_EXPORT PreloadingData {
  public:
   // This static function is implemented in PreloadingDataImpl.
-  // Please see content/browser/preloading_data_impl.cc for more details.
+  // Please see content/browser/preloading/preloading_data_impl.cc for more
+  // details.
   static PreloadingData* GetOrCreateForWebContents(WebContents* web_contents);
 
   // Creates a new PreloadingAttempt and returns a pointer associated with the
diff --git a/content/public/browser/render_frame_host_receiver_set.h b/content/public/browser/render_frame_host_receiver_set.h
index e88dd8fd..3bb1e5d 100644
--- a/content/public/browser/render_frame_host_receiver_set.h
+++ b/content/public/browser/render_frame_host_receiver_set.h
@@ -42,6 +42,8 @@
 template <typename Interface>
 class CONTENT_EXPORT RenderFrameHostReceiverSet : public WebContentsObserver {
  public:
+  using ImplPointerType = Interface*;
+
   RenderFrameHostReceiverSet(WebContents* web_contents, Interface* impl)
       : WebContentsObserver(web_contents), impl_(impl) {}
   ~RenderFrameHostReceiverSet() override = default;
@@ -81,6 +83,31 @@
     current_target_frame_for_testing_ = render_frame_host;
   }
 
+  // Allows test code to swap the interface implementation.
+  //
+  // Returns the existing interface implementation to the caller.
+  //
+  // The caller needs to guarantee that `new_impl` will live longer than
+  // `this` Receiver.  One way to achieve this is to store the returned
+  // `old_impl` and swap it back in when `new_impl` is getting destroyed.
+  // Test code should prefer using `mojo::test::ScopedSwapImplForTesting` if
+  // possible.
+  [[nodiscard]] ImplPointerType SwapImplForTesting(ImplPointerType new_impl) {
+    ImplPointerType old_impl = impl_;
+    impl_ = new_impl;
+
+    for (const auto& it : frame_to_receivers_map_) {
+      const std::vector<mojo::ReceiverId>& receiver_ids = it.second;
+      for (const mojo::ReceiverId& id : receiver_ids) {
+        // RenderFrameHostReceiverSet only allows all-or=nothing swaps, so
+        // all the old impls are expected to be equal to `this`'s old impl_.
+        CHECK_EQ(old_impl, receivers_.SwapImplForTesting(id, new_impl));
+      }
+    }
+
+    return old_impl;
+  }
+
  private:
   // content::WebContentsObserver:
   void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
@@ -105,7 +132,7 @@
   raw_ptr<RenderFrameHost> current_target_frame_for_testing_ = nullptr;
 
   // Must outlive this class.
-  const raw_ptr<Interface> impl_;
+  raw_ptr<Interface> impl_;
 };
 
 }  // namespace content
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h
index c828d24..725bca7 100644
--- a/content/public/browser/storage_partition.h
+++ b/content/public/browser/storage_partition.h
@@ -27,22 +27,26 @@
 namespace base {
 class FilePath;
 class Time;
-}
+}  // namespace base
+
+namespace blink {
+class StorageKey;
+}  // namespace blink
 
 namespace storage {
 class FileSystemContext;
-}
+}  // namespace storage
 
 namespace leveldb_proto {
 class ProtoDatabaseProvider;
-}
+}  // namespace leveldb_proto
 
 namespace network {
 namespace mojom {
 class CookieManager;
 class NetworkContext;
 class URLLoaderNetworkServiceObserver;
-}
+}  // namespace mojom
 }  // namespace network
 
 namespace storage {
@@ -50,11 +54,11 @@
 class SpecialStoragePolicy;
 struct QuotaSettings;
 class DatabaseTracker;
-}
+}  // namespace storage
 
 namespace url {
 class Origin;
-}
+}  // namespace url
 
 namespace content {
 
@@ -242,12 +246,12 @@
   };
 
   // Similar to ClearDataForOrigin().
-  // Deletes all data out for the StoragePartition if |storage_origin| is empty.
-  // |callback| is called when data deletion is done or at least the deletion is
-  // scheduled.
+  // Deletes all data out for the StoragePartition if |storage_key|'s origin is
+  // opaque. |callback| is called when data deletion is done or at least the
+  // deletion is scheduled.
   virtual void ClearData(uint32_t remove_mask,
                          uint32_t quota_storage_remove_mask,
-                         const GURL& storage_origin,
+                         const blink::StorageKey& storage_key,
                          const base::Time begin,
                          const base::Time end,
                          base::OnceClosure callback) = 0;
diff --git a/content/public/test/test_storage_partition.cc b/content/public/test/test_storage_partition.cc
index 31f567f4..29dc891 100644
--- a/content/public/test/test_storage_partition.cc
+++ b/content/public/test/test_storage_partition.cc
@@ -187,13 +187,12 @@
     const GURL& storage_origin,
     base::OnceClosure callback) {}
 
-void TestStoragePartition::ClearData(
-    uint32_t remove_mask,
-    uint32_t quota_storage_remove_mask,
-    const GURL& storage_origin,
-    const base::Time begin,
-    const base::Time end,
-    base::OnceClosure callback) {}
+void TestStoragePartition::ClearData(uint32_t remove_mask,
+                                     uint32_t quota_storage_remove_mask,
+                                     const blink::StorageKey& storage_key,
+                                     const base::Time begin,
+                                     const base::Time end,
+                                     base::OnceClosure callback) {}
 
 void TestStoragePartition::ClearData(
     uint32_t remove_mask,
diff --git a/content/public/test/test_storage_partition.h b/content/public/test/test_storage_partition.h
index 86e128a..47ef623 100644
--- a/content/public/test/test_storage_partition.h
+++ b/content/public/test/test_storage_partition.h
@@ -17,9 +17,13 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 
+namespace blink {
+class StorageKey;
+}  // namespace blink
+
 namespace leveldb_proto {
 class ProtoDatabaseProvider;
-}
+}  // namespace leveldb_proto
 
 namespace content {
 
@@ -35,7 +39,7 @@
 
 namespace mojom {
 class NetworkContext;
-}
+}  // namespace mojom
 
 // Fake implementation of StoragePartition.
 class TestStoragePartition : public StoragePartition {
@@ -186,7 +190,7 @@
 
   void ClearData(uint32_t remove_mask,
                  uint32_t quota_storage_remove_mask,
-                 const GURL& storage_origin,
+                 const blink::StorageKey& storage_key,
                  const base::Time begin,
                  const base::Time end,
                  base::OnceClosure callback) override;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index cb87db0..cd78e5e 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -573,7 +573,7 @@
 group("for_content_tests") {
   visibility = [
     "//content/test/*",
-    "//content/web_test:web_test_renderer",
+    "//content/web_test:web_test_renderer_public_deps",
   ]
 
   if (!is_component_build) {
diff --git a/content/renderer/pepper/pepper_media_stream_video_track_host.cc b/content/renderer/pepper/pepper_media_stream_video_track_host.cc
index 6c45b6af..1c02f5f 100644
--- a/content/renderer/pepper/pepper_media_stream_video_track_host.cc
+++ b/content/renderer/pepper/pepper_media_stream_video_track_host.cc
@@ -431,7 +431,8 @@
 
   void StartSourceImpl(
       blink::VideoCaptureDeliverFrameCB frame_callback,
-      blink::EncodedVideoFrameCB encoded_frame_callback) final {
+      blink::EncodedVideoFrameCB encoded_frame_callback,
+      blink::VideoCaptureCropVersionCB crop_version_callback) final {
     if (host_) {
       host_->frame_deliverer_ =
           new FrameDeliverer(io_task_runner(), std::move(frame_callback));
diff --git a/content/renderer/pepper/pepper_platform_video_capture.cc b/content/renderer/pepper/pepper_platform_video_capture.cc
index 648f462f..838aa4c 100644
--- a/content/renderer/pepper/pepper_platform_video_capture.cc
+++ b/content/renderer/pepper/pepper_platform_video_capture.cc
@@ -53,7 +53,8 @@
                                 weak_factory_.GetWeakPtr())),
                             media::BindToCurrentLoop(base::BindRepeating(
                                 &PepperPlatformVideoCapture::OnFrameReady,
-                                weak_factory_.GetWeakPtr())));
+                                weak_factory_.GetWeakPtr())),
+                            /*crop_version_cb=*/base::DoNothing());
 }
 
 void PepperPlatformVideoCapture::StopCapture() {
diff --git a/content/shell/browser/shell_download_manager_delegate.cc b/content/shell/browser/shell_download_manager_delegate.cc
index 3c2c063..3c68e99 100644
--- a/content/shell/browser/shell_download_manager_delegate.cc
+++ b/content/shell/browser/shell_download_manager_delegate.cc
@@ -80,8 +80,7 @@
         download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
         download::DownloadItem::MixedContentStatus::UNKNOWN,
         download->GetForcedFilePath(), base::FilePath(),
-        std::string() /*mime_type*/, absl::nullopt /*download_schedule*/,
-        download::DOWNLOAD_INTERRUPT_REASON_NONE);
+        std::string() /*mime_type*/, download::DOWNLOAD_INTERRUPT_REASON_NONE);
     return true;
   }
 
@@ -148,7 +147,6 @@
         download::DownloadItem::MixedContentStatus::UNKNOWN,
         suggested_path.AddExtension(FILE_PATH_LITERAL(".crdownload")),
         base::FilePath(), std::string() /*mime_type*/,
-        absl::nullopt /*download_schedule*/,
         download::DOWNLOAD_INTERRUPT_REASON_NONE);
     return;
   }
@@ -201,7 +199,6 @@
                           download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
                           download::DownloadItem::MixedContentStatus::UNKNOWN,
                           result, base::FilePath(), std::string() /*mime_type*/,
-                          absl::nullopt /*download_schedule*/,
                           download::DOWNLOAD_INTERRUPT_REASON_NONE);
 }
 
diff --git a/content/shell/fuchsia/content_shell.cmx b/content/shell/fuchsia/content_shell.cmx
index 6fdf012..8edcff5 100644
--- a/content/shell/fuchsia/content_shell.cmx
+++ b/content/shell/fuchsia/content_shell.cmx
@@ -32,6 +32,7 @@
       "fuchsia.process.Launcher",
       "fuchsia.sys.Launcher",
       "fuchsia.sysmem.Allocator",
+      "fuchsia.tracing.perfetto.ProducerConnector",
       "fuchsia.ui.composition.Allocator",
       "fuchsia.ui.composition.Flatland",
       "fuchsia.ui.input3.Keyboard",
diff --git a/content/test/attribution_simulator_input_parser.cc b/content/test/attribution_simulator_input_parser.cc
index 7f18577..ecbfaf34 100644
--- a/content/test/attribution_simulator_input_parser.cc
+++ b/content/test/attribution_simulator_input_parser.cc
@@ -295,6 +295,7 @@
 
     absl::optional<uint64_t> debug_key;
     AttributionFilterData filters;
+    AttributionFilterData not_filters;
     std::vector<AttributionTrigger::EventTriggerData> event_triggers;
     std::vector<AttributionAggregatableTriggerData> aggregatable_trigger_data;
     AttributionAggregatableValues aggregatable_values;
@@ -308,6 +309,9 @@
                   filters = ParseFilterData(
                       dict, "filters",
                       &AttributionFilterData::FromTriggerFilterValues);
+                  not_filters = ParseFilterData(
+                      dict, "not_filters",
+                      &AttributionFilterData::FromTriggerFilterValues);
                   event_triggers = ParseEventTriggers(dict);
 
                   aggregatable_trigger_data =
@@ -325,8 +329,8 @@
         AttributionTriggerAndTime{
             .trigger = AttributionTrigger(
                 std::move(destination_origin), std::move(reporting_origin),
-                std::move(filters), debug_key, std::move(event_triggers),
-                std::move(aggregatable_trigger_data),
+                std::move(filters), std::move(not_filters), debug_key,
+                std::move(event_triggers), std::move(aggregatable_trigger_data),
                 std::move(aggregatable_values)),
             .time = trigger_time,
         },
@@ -404,13 +408,15 @@
     const std::string* v = dict.FindString(key);
     int64_t milliseconds;
 
-    if (!v || !base::StringToInt64(*v, &milliseconds)) {
-      *Error() << "must be an integer number of milliseconds since the Unix "
-                  "epoch formatted as a base-10 string";
-      return base::Time();
+    if (v && base::StringToInt64(*v, &milliseconds)) {
+      base::Time time = offset_time_ + base::Milliseconds(milliseconds);
+      if (!time.is_null() && !time.is_inf())
+        return time;
     }
 
-    return offset_time_ + base::Milliseconds(milliseconds);
+    *Error() << "must be an integer number of milliseconds since the Unix "
+                "epoch formatted as a base-10 string";
+    return base::Time();
   }
 
   uint64_t ParseUint64(const std::string* s, base::StringPiece key) {
diff --git a/content/test/attribution_simulator_input_parser_unittest.cc b/content/test/attribution_simulator_input_parser_unittest.cc
index 6938d95..42d0d93 100644
--- a/content/test/attribution_simulator_input_parser_unittest.cc
+++ b/content/test/attribution_simulator_input_parser_unittest.cc
@@ -309,6 +309,9 @@
         "filters": {
           "a": ["b", "c"],
           "d": []
+        },
+        "not_filters": {
+          "e": ["f"]
         }
       }
     },
@@ -346,10 +349,15 @@
                       url::Origin::Create(GURL("https://a.d1.test")),
                       /*reporting_origin=*/
                       url::Origin::Create(GURL("https://a.r.test")),
+                      /*filters=*/
                       *AttributionFilterData::FromTriggerFilterValues({
                           {"a", {"b", "c"}},
                           {"d", {}},
                       }),
+                      /*not_filters=*/
+                      *AttributionFilterData::FromTriggerFilterValues({
+                          {"e", {"f"}},
+                      }),
                       /*debug_key=*/14,
                       {
                           AttributionTrigger::EventTriggerData(
@@ -383,7 +391,8 @@
                       url::Origin::Create(GURL("https://a.d2.test")),
                       /*reporting_origin=*/
                       url::Origin::Create(GURL("https://b.r.test")),
-                      AttributionFilterData(),
+                      /*filters=*/AttributionFilterData(),
+                      /*not_filters=*/AttributionFilterData(),
                       /*debug_key=*/absl::nullopt,
                       /*event_triggers=*/{},
                       /*aggregatable_trigger_data=*/{},
@@ -398,7 +407,8 @@
                       url::Origin::Create(GURL("https://a.d2.test")),
                       /*reporting_origin=*/
                       url::Origin::Create(GURL("https://b.r.test")),
-                      AttributionFilterData(),
+                      /*filters=*/AttributionFilterData(),
+                      /*not_filters=*/AttributionFilterData(),
                       /*debug_key=*/absl::nullopt,
                       /*event_triggers=*/{},
                       {AttributionAggregatableTriggerData::CreateForTesting(
@@ -1018,6 +1028,12 @@
         R"json({"cookies": [{}]})json",
     },
     {
+        R"(["cookies"][0]["timestamp"]: must be an integer number of milliseconds)",
+        R"json({"cookies": [{
+          "timestamp": "9223372036854775"
+        }]})json",
+    },
+    {
         R"(["cookies"][0]["url"]: must be a valid URL)",
         R"json({"cookies": [{
         "timestamp": "1643235576000"
diff --git a/content/test/data/accessibility/event/add-alert-with-role-change-expected-uia-win.txt b/content/test/data/accessibility/event/add-alert-with-role-change-expected-uia-win.txt
index 18257334..cb12386a 100644
--- a/content/test/data/accessibility/event/add-alert-with-role-change-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/add-alert-with-role-change-expected-uia-win.txt
@@ -1 +1 @@
-SystemAlert on role=alert
\ No newline at end of file
+LiveRegionChanged on role=alert
diff --git a/content/test/data/accessibility/event/add-alert-with-role-change.html b/content/test/data/accessibility/event/add-alert-with-role-change.html
index 67eb622e..25f1ae0 100644
--- a/content/test/data/accessibility/event/add-alert-with-role-change.html
+++ b/content/test/data/accessibility/event/add-alert-with-role-change.html
@@ -3,6 +3,7 @@
 @WIN-ALLOW:EVENT_SYSTEM_ALERT*
 @UIA-WIN-DENY:*
 @UIA-WIN-ALLOW:SystemAlert*
+@UIA-WIN-ALLOW:LiveRegion*
 -->
 <!DOCTYPE html>
 <html>
diff --git a/content/test/data/fuzzer_corpus/attribution_simulator/all_fields.textproto b/content/test/data/fuzzer_corpus/attribution_simulator/all_fields.textproto
index 701b8fb..cca0db5 100644
--- a/content/test/data/fuzzer_corpus/attribution_simulator/all_fields.textproto
+++ b/content/test/data/fuzzer_corpus/attribution_simulator/all_fields.textproto
@@ -259,6 +259,25 @@
                     }
                   }
                   field {
+                    name: "not_filters"
+                    value {
+                      object_value {
+                        field {
+                          name: "i"
+                          value {
+                            array_value {
+                              value {
+                                string_value {
+                                  value: "j"
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                  field {
                     name: "event_trigger_data"
                     value {
                       array_value {
diff --git a/content/test/data/media/video-player.html b/content/test/data/media/video-player.html
index d81d093..ec9a48f 100644
--- a/content/test/data/media/video-player.html
+++ b/content/test/data/media/video-player.html
@@ -5,7 +5,7 @@
   <meta name=viewport content='width=device-width initial-scale=1.0'>
 </head>
 <body>
-  <video controls id=video src=bear.webm controlsList='noplaybackrate noremoteplayback'></video>
+  <video controls id=video src=bear.webm controlsList='noplaybackrate noremoteplayback' disablePictureInPicture></video>
   <button id='fullscreen'>fullscreen</button>
 </body>
 <script>
diff --git a/content/web_test/BUILD.gn b/content/web_test/BUILD.gn
index 5c35546..9deef6c 100644
--- a/content/web_test/BUILD.gn
+++ b/content/web_test/BUILD.gn
@@ -220,6 +220,42 @@
   }
 }
 
+# TODO(crbug.com/1154721): The `allow_circular_includes_from` declared in
+# `:web_test_renderer` does not propagate the public_deps
+# from `:web_test_renderer`'s own dependencies. This means that those targets
+# are not built when `//third_party/blink/renderer/core/web_test` is built,
+# and some generated mojom headers will be missing. As a workaround, split
+# these deps into this separate group so that
+# `//third_party/blink/renderer/core/web_test` can add include them in its
+# own deps directly.
+group("web_test_renderer_public_deps") {
+  testonly = true
+
+  public_deps = [
+    ":web_test_common",
+    "//base",
+    "//cc",
+    "//cc/paint",
+    "//content/public/renderer",  # For component builds.
+    "//content/renderer:for_content_tests",  # For non-component builds.
+    "//content/shell:content_shell_lib",
+    "//device/gamepad/public/cpp:shared_with_blink",
+    "//device/gamepad/public/mojom",
+    "//gin",
+    "//gpu",
+    "//mojo/public/cpp/bindings",
+    "//services/device/public/mojom",
+    "//third_party/blink/public:blink_headers",
+    "//third_party/blink/public:test_headers",
+    "//ui/accessibility:ax_base",
+    "//ui/base/dragdrop/mojom",
+    "//ui/display",
+    "//ui/gfx/geometry",
+    "//url",
+    "//v8",
+  ]
+}
+
 static_library("web_test_renderer") {
   testonly = true
 
@@ -307,28 +343,8 @@
   ]
 
   public_deps = [
-    ":web_test_common",
-    "//base",
-    "//cc",
-    "//cc/paint",
-    "//content/public/renderer",  # For component builds.
-    "//content/renderer:for_content_tests",  # For non-component builds.
-    "//content/shell:content_shell_lib",
-    "//device/gamepad/public/cpp:shared_with_blink",
-    "//device/gamepad/public/mojom",
-    "//gin",
-    "//gpu",
-    "//mojo/public/cpp/bindings",
-    "//services/device/public/mojom",
-    "//third_party/blink/public:blink_headers",
-    "//third_party/blink/public:test_headers",
+    ":web_test_renderer_public_deps",
     "//third_party/blink/renderer/core/web_test",
-    "//ui/accessibility:ax_base",
-    "//ui/base/dragdrop/mojom",
-    "//ui/display",
-    "//ui/gfx/geometry",
-    "//url",
-    "//v8",
   ]
 
   if (enable_basic_printing) {
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index 0018199..0f9b3fab 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -989,12 +989,12 @@
       "//chromeos/ash/components/dbus/media_analytics",
       "//chromeos/ash/components/dbus/media_analytics:media_perception_proto",
       "//chromeos/ash/components/dbus/upstart",
+      "//chromeos/ash/components/network:test_support",
       "//chromeos/dbus:test_support",
       "//chromeos/dbus/audio",
       "//chromeos/dbus/permission_broker",
       "//chromeos/dbus/power",
       "//chromeos/login/login_state",
-      "//chromeos/network:test_support",
       "//components/feedback",
       "//components/prefs:prefs",
       "//extensions/shell:app_shell_lib",
diff --git a/extensions/browser/api/alarms/alarm_manager.cc b/extensions/browser/api/alarms/alarm_manager.cc
index 6ae08a3..7d5ba3f 100644
--- a/extensions/browser/api/alarms/alarm_manager.cc
+++ b/extensions/browser/api/alarms/alarm_manager.cc
@@ -51,11 +51,11 @@
   ~DefaultAlarmDelegate() override {}
 
   void OnAlarm(const std::string& extension_id, const Alarm& alarm) override {
-    std::vector<base::Value> args;
-    args.push_back(base::Value::FromUniquePtrValue(alarm.js_alarm->ToValue()));
-    std::unique_ptr<Event> event(new Event(events::ALARMS_ON_ALARM,
-                                           alarms::OnAlarm::kEventName,
-                                           std::move(args), browser_context_));
+    base::Value::List args;
+    args.Append(base::Value::FromUniquePtrValue(alarm.js_alarm->ToValue()));
+    auto event = std::make_unique<Event>(events::ALARMS_ON_ALARM,
+                                         alarms::OnAlarm::kEventName,
+                                         std::move(args), browser_context_);
     EventRouter::Get(browser_context_)
         ->DispatchEventToExtension(extension_id, std::move(event));
   }
diff --git a/extensions/browser/api/app_runtime/app_runtime_api.cc b/extensions/browser/api/app_runtime/app_runtime_api.cc
index 4b6dd46b..218aba5 100644
--- a/extensions/browser/api/app_runtime/app_runtime_api.cc
+++ b/extensions/browser/api/app_runtime/app_runtime_api.cc
@@ -36,8 +36,8 @@
     const std::string& extension_id,
     std::unique_ptr<base::DictionaryValue> app_embedding_request_data,
     content::BrowserContext* context) {
-  std::vector<base::Value> args;
-  args.emplace_back(
+  base::Value::List args;
+  args.Append(
       base::Value::FromUniquePtrValue(std::move(app_embedding_request_data)));
   auto event = std::make_unique<Event>(
       events::APP_RUNTIME_ON_EMBED_REQUESTED,
@@ -69,8 +69,8 @@
       "isPublicSession",
       ExtensionsBrowserClient::Get()->IsLoggedInAsPublicAccount());
 
-  std::vector<base::Value> args;
-  args.emplace_back(base::Value::FromUniquePtrValue(std::move(launch_data)));
+  base::Value::List args;
+  args.Append(base::Value::FromUniquePtrValue(std::move(launch_data)));
   auto event = std::make_unique<Event>(events::APP_RUNTIME_ON_LAUNCHED,
                                        app_runtime::OnLaunched::kEventName,
                                        std::move(args), context);
@@ -166,7 +166,7 @@
     const Extension* extension) {
   auto event = std::make_unique<Event>(events::APP_RUNTIME_ON_RESTARTED,
                                        app_runtime::OnRestarted::kEventName,
-                                       std::vector<base::Value>(), context);
+                                       base::Value::List(), context);
   EventRouter::Get(context)
       ->DispatchEventToExtension(extension->id(), std::move(event));
 }
diff --git a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
index 48481c2..b1b736a 100644
--- a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
+++ b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
@@ -1060,9 +1060,8 @@
   // lists of enums correctly.
   apibtle::Characteristic api_characteristic;
   PopulateCharacteristic(characteristic, &api_characteristic);
-  std::vector<base::Value> args;
-  args.push_back(
-      base::Value(apibtle::CharacteristicToValue(&api_characteristic)));
+  base::Value::List args;
+  args.Append(apibtle::CharacteristicToValue(&api_characteristic));
 
   DispatchEventToExtensionsWithPermission(
       events::BLUETOOTH_LOW_ENERGY_ON_CHARACTERISTIC_VALUE_CHANGED,
@@ -1092,8 +1091,8 @@
   // lists of enums correctly.
   apibtle::Descriptor api_descriptor;
   PopulateDescriptor(descriptor, &api_descriptor);
-  std::vector<base::Value> args;
-  args.push_back(base::Value::FromUniquePtrValue(
+  base::Value::List args;
+  args.Append(base::Value::FromUniquePtrValue(
       apibtle::DescriptorToValue(&api_descriptor)));
 
   DispatchEventToExtensionsWithPermission(
@@ -1477,7 +1476,7 @@
     const std::string& event_name,
     const device::BluetoothUUID& uuid,
     const std::string& characteristic_id,
-    std::vector<base::Value> args) {
+    base::Value::List args) {
   // Obtain the listeners of |event_name|. The list can contain multiple
   // entries for the same extension, so we keep track of the extensions that we
   // already sent the event to, since we want the send an event to an extension
@@ -1515,14 +1514,9 @@
         !FindNotifySession(extension_id, characteristic_id))
       continue;
 
-    std::vector<base::Value> args_copy;
-    args_copy.reserve(args.size());
-    for (const auto& arg : args) {
-      args_copy.emplace_back(arg.Clone());
-    }
     // Send the event.
-    auto event = std::make_unique<Event>(histogram_value, event_name,
-                                         std::move(args_copy));
+    auto event =
+        std::make_unique<Event>(histogram_value, event_name, args.Clone());
     EventRouter::Get(browser_context_)
         ->DispatchEventToExtension(extension_id, std::move(event));
   }
@@ -1532,7 +1526,7 @@
     const std::string& extension_id,
     events::HistogramValue histogram_value,
     const std::string& event_name,
-    std::vector<base::Value> args) {
+    base::Value::List args) {
   // For all API methods, the "low_energy" permission check is handled by
   // BluetoothLowEnergyExtensionFunction but for events we have to do the
   // check here.
diff --git a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h
index eff1fd0..0d7d9b3 100644
--- a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h
+++ b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h
@@ -408,12 +408,12 @@
       const std::string& event_name,
       const device::BluetoothUUID& uuid,
       const std::string& characteristic_id,
-      std::vector<base::Value> args);
+      base::Value::List args);
 
   void DispatchEventToExtension(const std::string& extension_id,
                                 events::HistogramValue histogram_value,
                                 const std::string& event_name,
-                                std::vector<base::Value> args);
+                                base::Value::List args);
 
   // Returns a BluetoothRemoteGattService by its instance ID |instance_id|.
   // Returns
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
index 99f56e0b..554ef61 100644
--- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
+++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
@@ -353,8 +353,7 @@
                                std::move(error_callback));
 }
 
-std::vector<base::Value>
-BluetoothSocketListenUsingRfcommFunction::CreateResults() {
+base::Value::List BluetoothSocketListenUsingRfcommFunction::CreateResults() {
   return bluetooth_socket::ListenUsingRfcomm::Results::Create();
 }
 
@@ -401,8 +400,7 @@
                               std::move(error_callback));
 }
 
-std::vector<base::Value>
-BluetoothSocketListenUsingL2capFunction::CreateResults() {
+base::Value::List BluetoothSocketListenUsingL2capFunction::CreateResults() {
   return bluetooth_socket::ListenUsingL2cap::Results::Create();
 }
 
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h
index a31d3a88..eef14cc 100644
--- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h
+++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.h
@@ -128,7 +128,7 @@
       const absl::optional<std::string>& name,
       device::BluetoothAdapter::CreateServiceCallback callback,
       device::BluetoothAdapter::CreateServiceErrorCallback error_callback) = 0;
-  virtual std::vector<base::Value> CreateResults() = 0;
+  virtual base::Value::List CreateResults() = 0;
 
   virtual int socket_id() const = 0;
   virtual const std::string& uuid() const = 0;
@@ -166,7 +166,7 @@
                      device::BluetoothAdapter::CreateServiceCallback callback,
                      device::BluetoothAdapter::CreateServiceErrorCallback
                          error_callback) override;
-  std::vector<base::Value> CreateResults() override;
+  base::Value::List CreateResults() override;
 
  protected:
   ~BluetoothSocketListenUsingRfcommFunction() override;
@@ -194,7 +194,7 @@
                      device::BluetoothAdapter::CreateServiceCallback callback,
                      device::BluetoothAdapter::CreateServiceErrorCallback
                          error_callback) override;
-  std::vector<base::Value> CreateResults() override;
+  base::Value::List CreateResults() override;
 
  protected:
   ~BluetoothSocketListenUsingL2capFunction() override;
diff --git a/extensions/browser/api/declarative_net_request/action_tracker.cc b/extensions/browser/api/declarative_net_request/action_tracker.cc
index 8b9f1a2..5edcd3c 100644
--- a/extensions/browser/api/declarative_net_request/action_tracker.cc
+++ b/extensions/browser/api/declarative_net_request/action_tracker.cc
@@ -431,8 +431,8 @@
   matched_rule_info_debug.rule = std::move(matched_rule);
   matched_rule_info_debug.request = std::move(request_details);
 
-  std::vector<base::Value> args;
-  args.push_back(
+  base::Value::List args;
+  args.Append(
       base::Value::FromUniquePtrValue(matched_rule_info_debug.ToValue()));
 
   auto event = std::make_unique<Event>(
diff --git a/extensions/browser/api/hid/hid_device_manager.cc b/extensions/browser/api/hid/hid_device_manager.cc
index 246ae16..7a5ca9b 100644
--- a/extensions/browser/api/hid/hid_device_manager.cc
+++ b/extensions/browser/api/hid/hid_device_manager.cc
@@ -385,7 +385,7 @@
 void HidDeviceManager::DispatchEvent(
     events::HistogramValue histogram_value,
     const std::string& event_name,
-    std::vector<base::Value> event_args,
+    base::Value::List event_args,
     const device::mojom::HidDeviceInfo& device_info) {
   std::unique_ptr<Event> event(
       new Event(histogram_value, event_name, std::move(event_args)));
diff --git a/extensions/browser/api/hid/hid_device_manager.h b/extensions/browser/api/hid/hid_device_manager.h
index 63cc998..46e1c26 100644
--- a/extensions/browser/api/hid/hid_device_manager.h
+++ b/extensions/browser/api/hid/hid_device_manager.h
@@ -125,7 +125,7 @@
 
   void DispatchEvent(events::HistogramValue histogram_value,
                      const std::string& event_name,
-                     std::vector<base::Value> event_args,
+                     base::Value::List event_args,
                      const device::mojom::HidDeviceInfo& device_info);
 
   base::ThreadChecker thread_checker_;
diff --git a/extensions/browser/api/idle/idle_manager.cc b/extensions/browser/api/idle/idle_manager.cc
index f0dca08..9c6c5c6 100644
--- a/extensions/browser/api/idle/idle_manager.cc
+++ b/extensions/browser/api/idle/idle_manager.cc
@@ -54,8 +54,8 @@
 
 void DefaultEventDelegate::OnStateChanged(const std::string& extension_id,
                                           ui::IdleState new_state) {
-  std::vector<base::Value> args;
-  args.emplace_back(IdleManager::CreateIdleValue(new_state));
+  base::Value::List args;
+  args.Append(IdleManager::CreateIdleValue(new_state));
   auto event = std::make_unique<Event>(events::IDLE_ON_STATE_CHANGED,
                                        idle::OnStateChanged::kEventName,
                                        std::move(args), context_);
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc b/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc
index c608ba8..45f8a0e 100644
--- a/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc
+++ b/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc
@@ -105,9 +105,8 @@
         extensions::api::lock_screen_data::OnDataItemsAvailable::kEventName) {
       return;
     }
-    ASSERT_TRUE(event->event_args);
-    ASSERT_TRUE(!event->event_args->GetList().empty());
-    const base::Value& arg_value = event->event_args->GetList()[0];
+    ASSERT_TRUE(!event->event_args.empty());
+    const base::Value& arg_value = event->event_args[0];
 
     std::unique_ptr<extensions::api::lock_screen_data::DataItemsAvailableEvent>
         event_args = extensions::api::lock_screen_data::
diff --git a/extensions/browser/api/management/management_api.cc b/extensions/browser/api/management/management_api.cc
index d5dcc53..7f501cd6 100644
--- a/extensions/browser/api/management/management_api.cc
+++ b/extensions/browser/api/management/management_api.cc
@@ -1098,11 +1098,11 @@
     const char* event_name) {
   if (!extension->ShouldExposeViaManagementAPI())
     return;
-  std::vector<base::Value> args;
+  base::Value::List args;
   if (event_name == management::OnUninstalled::kEventName) {
-    args.push_back(base::Value(extension->id()));
+    args.Append(extension->id());
   } else {
-    args.push_back(base::Value::FromUniquePtrValue(
+    args.Append(base::Value::FromUniquePtrValue(
         CreateExtensionInfo(nullptr, *extension, browser_context_).ToValue()));
   }
 
diff --git a/extensions/browser/api/messaging/messaging_api_message_filter.cc b/extensions/browser/api/messaging/messaging_api_message_filter.cc
index 5469f5e..c89c991 100644
--- a/extensions/browser/api/messaging/messaging_api_message_filter.cc
+++ b/extensions/browser/api/messaging/messaging_api_message_filter.cc
@@ -16,6 +16,7 @@
 #include "extensions/browser/bad_message.h"
 #include "extensions/browser/content_script_tracker.h"
 #include "extensions/browser/event_router_factory.h"
+#include "extensions/browser/extension_util.h"
 #include "extensions/common/extension_features.h"
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/trace_util.h"
@@ -49,17 +50,6 @@
   ~ShutdownNotifierFactory() override = default;
 };
 
-// Returns true if the process corresponding to `render_process_id` can host an
-// extension with `extension_id`.  (It doesn't necessarily mean that the process
-// *does* host this specific extension at this point in time.)
-bool CanRendererHostExtensionOrigin(int render_process_id,
-                                    const std::string& extension_id) {
-  url::Origin extension_origin =
-      Extension::CreateOriginFromExtensionId(extension_id);
-  auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
-  return policy->CanAccessDataForOrigin(render_process_id, extension_origin);
-}
-
 // Returns true if `source_endpoint` can be legitimately claimed/used by
 // `process`.  Otherwise reports a bad IPC message and returns false (expecting
 // the caller to not take any action based on the rejected, untrustworthy
@@ -87,7 +77,7 @@
             &process, bad_message::EMF_NO_EXTENSION_ID_FOR_EXTENSION_SOURCE);
         return false;
       }
-      if (!CanRendererHostExtensionOrigin(
+      if (!util::CanRendererHostExtensionOrigin(
               process.GetID(), source_endpoint.extension_id.value())) {
         bad_message::ReceivedBadMessage(
             &process,
@@ -148,8 +138,8 @@
     // exists using ProcessManager::HasServiceWorker) might incorrectly return
     // false=invalid-IPC for IPCs from workers that were recently torn down /
     // made inactive.
-    if (!CanRendererHostExtensionOrigin(process.GetID(),
-                                        worker_context.extension_id)) {
+    if (!util::CanRendererHostExtensionOrigin(process.GetID(),
+                                              worker_context.extension_id)) {
       bad_message::ReceivedBadMessage(
           &process, bad_message::EMF_INVALID_EXTENSION_ID_FOR_WORKER_CONTEXT);
       return false;
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc b/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
index e94589e1..5f68325 100644
--- a/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
+++ b/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_device_client.h"
 #include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/dbus/shill/shill_service_client.h"
@@ -18,7 +19,6 @@
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/onc/onc_constants.h"
diff --git a/extensions/browser/api/printer_provider/printer_provider_api.cc b/extensions/browser/api/printer_provider/printer_provider_api.cc
index dc8b113..26462d9b 100644
--- a/extensions/browser/api/printer_provider/printer_provider_api.cc
+++ b/extensions/browser/api/printer_provider/printer_provider_api.cc
@@ -548,15 +548,15 @@
   // be needed later on.
   int request_id = pending_get_printers_requests_.Add(callback);
 
-  std::vector<base::Value> internal_args;
+  base::Value::List internal_args;
   // Request id is not part of the public API, but it will be massaged out in
   // custom bindings.
-  internal_args.push_back(base::Value(request_id));
+  internal_args.Append(request_id);
 
-  std::unique_ptr<Event> event(
-      new Event(events::PRINTER_PROVIDER_ON_GET_PRINTERS_REQUESTED,
-                api::printer_provider::OnGetPrintersRequested::kEventName,
-                std::move(internal_args)));
+  auto event = std::make_unique<Event>(
+      events::PRINTER_PROVIDER_ON_GET_PRINTERS_REQUESTED,
+      api::printer_provider::OnGetPrintersRequested::kEventName,
+      std::move(internal_args));
   // This callback is called synchronously during |BroadcastEvent|, so
   // Unretained is safe.
   event->will_dispatch_callback =
@@ -587,11 +587,11 @@
   int request_id =
       pending_capability_requests_[extension_id].Add(std::move(callback));
 
-  std::vector<base::Value> internal_args;
+  base::Value::List internal_args;
   // Request id is not part of the public API, but it will be massaged out in
   // custom bindings.
-  internal_args.push_back(base::Value(request_id));
-  internal_args.push_back(base::Value(internal_printer_id));
+  internal_args.Append(request_id);
+  internal_args.Append(internal_printer_id);
 
   std::unique_ptr<Event> event(
       new Event(events::PRINTER_PROVIDER_ON_GET_CAPABILITY_REQUESTED,
@@ -632,15 +632,15 @@
   int request_id = pending_print_requests_[extension_id].Add(
       std::move(job), std::move(callback));
 
-  std::vector<base::Value> internal_args;
+  base::Value::List internal_args;
   // Request id is not part of the public API and it will be massaged out in
   // custom bindings.
-  internal_args.push_back(base::Value(request_id));
-  internal_args.push_back(base::Value::FromUniquePtrValue(print_job.ToValue()));
-  std::unique_ptr<Event> event(
-      new Event(events::PRINTER_PROVIDER_ON_PRINT_REQUESTED,
-                api::printer_provider::OnPrintRequested::kEventName,
-                std::move(internal_args)));
+  internal_args.Append(request_id);
+  internal_args.Append(base::Value::FromUniquePtrValue(print_job.ToValue()));
+  auto event = std::make_unique<Event>(
+      events::PRINTER_PROVIDER_ON_PRINT_REQUESTED,
+      api::printer_provider::OnPrintRequested::kEventName,
+      std::move(internal_args));
   event_router->DispatchEventToExtension(extension_id, std::move(event));
 }
 
@@ -670,16 +670,15 @@
   api::usb::Device api_device;
   UsbDeviceManager::Get(browser_context_)->GetApiDevice(device, &api_device);
 
-  std::vector<base::Value> internal_args;
+  base::Value::List internal_args;
   // Request id is not part of the public API and it will be massaged out in
   // custom bindings.
-  internal_args.push_back(base::Value(request_id));
-  internal_args.push_back(
-      base::Value::FromUniquePtrValue(api_device.ToValue()));
-  std::unique_ptr<Event> event(
-      new Event(events::PRINTER_PROVIDER_ON_GET_USB_PRINTER_INFO_REQUESTED,
-                api::printer_provider::OnGetUsbPrinterInfoRequested::kEventName,
-                std::move(internal_args)));
+  internal_args.Append(request_id);
+  internal_args.Append(base::Value::FromUniquePtrValue(api_device.ToValue()));
+  auto event = std::make_unique<Event>(
+      events::PRINTER_PROVIDER_ON_GET_USB_PRINTER_INFO_REQUESTED,
+      api::printer_provider::OnGetUsbPrinterInfoRequested::kEventName,
+      std::move(internal_args));
   event_router->DispatchEventToExtension(extension_id, std::move(event));
 }
 
diff --git a/extensions/browser/api/runtime/runtime_api.cc b/extensions/browser/api/runtime/runtime_api.cc
index 52658f8..e8ae028 100644
--- a/extensions/browser/api/runtime/runtime_api.cc
+++ b/extensions/browser/api/runtime/runtime_api.cc
@@ -138,9 +138,9 @@
     }
   }
 
-  std::unique_ptr<Event> event(new Event(events::RUNTIME_ON_STARTUP,
-                                         runtime::OnStartup::kEventName,
-                                         std::vector<base::Value>()));
+  auto event = std::make_unique<Event>(events::RUNTIME_ON_STARTUP,
+                                       runtime::OnStartup::kEventName,
+                                       base::Value::List());
   EventRouter::Get(browser_context)
       ->DispatchEventToExtension(extension_id, std::move(event));
 }
@@ -449,7 +449,7 @@
     return;
   }
 
-  std::vector<base::Value> event_args;
+  base::Value::List event_args;
   base::Value info(base::Value::Type::DICTIONARY);
   if (old_version.IsValid()) {
     info.SetStringKey(kInstallReason, kInstallReasonUpdate);
@@ -459,12 +459,12 @@
   } else {
     info.SetStringKey(kInstallReason, kInstallReasonInstall);
   }
-  event_args.push_back(std::move(info));
+  event_args.Append(std::move(info));
   EventRouter* event_router = EventRouter::Get(context);
   DCHECK(event_router);
-  std::unique_ptr<Event> event(new Event(events::RUNTIME_ON_INSTALLED,
-                                         runtime::OnInstalled::kEventName,
-                                         std::move(event_args)));
+  auto event = std::make_unique<Event>(events::RUNTIME_ON_INSTALLED,
+                                       runtime::OnInstalled::kEventName,
+                                       std::move(event_args));
   event_router->DispatchEventWithLazyListener(extension_id, std::move(event));
 
   if (old_version.IsValid()) {
@@ -477,15 +477,15 @@
       for (ExtensionSet::const_iterator i = dependents->begin();
            i != dependents->end();
            i++) {
-        std::vector<base::Value> sm_event_args;
+        base::Value::List sm_event_args;
         base::Value sm_info(base::Value::Type::DICTIONARY);
         sm_info.SetStringKey(kInstallReason, kInstallReasonSharedModuleUpdate);
         sm_info.SetStringKey(kInstallPreviousVersion, old_version.GetString());
         sm_info.SetStringKey(kInstallId, extension_id);
-        sm_event_args.push_back(std::move(sm_info));
-        std::unique_ptr<Event> sm_event(new Event(
+        sm_event_args.Append(std::move(sm_info));
+        auto sm_event = std::make_unique<Event>(
             events::RUNTIME_ON_INSTALLED, runtime::OnInstalled::kEventName,
-            std::move(sm_event_args)));
+            std::move(sm_event_args));
         event_router->DispatchEventWithLazyListener((*i)->id(),
                                                     std::move(sm_event));
       }
@@ -502,13 +502,13 @@
   if (!system)
     return;
 
-  std::vector<base::Value> args;
-  args.push_back(manifest->Clone());
+  base::Value::List args;
+  args.Append(manifest->Clone());
   EventRouter* event_router = EventRouter::Get(context);
   DCHECK(event_router);
-  std::unique_ptr<Event> event(new Event(events::RUNTIME_ON_UPDATE_AVAILABLE,
-                                         runtime::OnUpdateAvailable::kEventName,
-                                         std::move(args)));
+  auto event = std::make_unique<Event>(events::RUNTIME_ON_UPDATE_AVAILABLE,
+                                       runtime::OnUpdateAvailable::kEventName,
+                                       std::move(args));
   event_router->DispatchEventToExtension(extension_id, std::move(event));
 }
 
@@ -521,10 +521,9 @@
 
   EventRouter* event_router = EventRouter::Get(context);
   DCHECK(event_router);
-  std::unique_ptr<Event> event(
-      new Event(events::RUNTIME_ON_BROWSER_UPDATE_AVAILABLE,
-                runtime::OnBrowserUpdateAvailable::kEventName,
-                std::vector<base::Value>()));
+  auto event = std::make_unique<Event>(
+      events::RUNTIME_ON_BROWSER_UPDATE_AVAILABLE,
+      runtime::OnBrowserUpdateAvailable::kEventName, base::Value::List());
   event_router->BroadcastEvent(std::move(event));
 }
 
diff --git a/extensions/browser/api/storage/storage_frontend.cc b/extensions/browser/api/storage/storage_frontend.cc
index a250b18..8a5f9408 100644
--- a/extensions/browser/api/storage/storage_frontend.cc
+++ b/extensions/browser/api/storage/storage_frontend.cc
@@ -199,17 +199,17 @@
       event_router->ExtensionHasEventListener(extension_id, area_event_name);
 
   auto make_changed_event = [&namespace_string](base::Value changes) {
-    std::vector<base::Value> args;
-    args.emplace_back(std::move(changes));
-    args.emplace_back(base::Value(namespace_string));
+    base::Value::List args;
+    args.Append(std::move(changes));
+    args.Append(namespace_string);
     return std::make_unique<Event>(events::STORAGE_ON_CHANGED,
                                    api::storage::OnChanged::kEventName,
                                    std::move(args));
   };
   auto make_area_changed_event = [&storage_area,
                                   &area_event_name](base::Value changes) {
-    std::vector<base::Value> args;
-    args.push_back(std::move(changes));
+    base::Value::List args;
+    args.Append(std::move(changes));
     return std::make_unique<Event>(StorageAreaToEventHistogram(storage_area),
                                    area_event_name, std::move(args));
   };
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index c2c9a707..2caefc6 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -314,8 +314,8 @@
   if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
     return;
 
-  std::vector<base::Value> event_args;
-  event_args.emplace_back(
+  base::Value::List event_args;
+  event_args.Append(
       base::Value::FromUniquePtrValue(event_details->GetAndClearDict()));
 
   EventRouter* event_router = EventRouter::Get(browser_context);
diff --git a/extensions/browser/bad_message.h b/extensions/browser/bad_message.h
index 93ffd3e..c1589cb 100644
--- a/extensions/browser/bad_message.h
+++ b/extensions/browser/bad_message.h
@@ -43,6 +43,7 @@
   EMF_INVALID_EXTENSION_ID_FOR_WORKER_CONTEXT = 17,
   EMF_INVALID_PORT_CONTEXT = 18,
   AWCI_INVALID_CALL_FROM_NOT_PRIMARY_MAIN_FRAME = 19,
+  EFD_INVALID_EXTENSION_ID_FOR_PROCESS = 20,
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. ExtensionHost becomes EH) plus a unique description of the
   // reason. After making changes, you MUST update histograms.xml by running:
diff --git a/extensions/browser/event_listener_map_unittest.cc b/extensions/browser/event_listener_map_unittest.cc
index 27b29f0b..e2433d40 100644
--- a/extensions/browser/event_listener_map_unittest.cc
+++ b/extensions/browser/event_listener_map_unittest.cc
@@ -98,8 +98,8 @@
     mojom::EventFilteringInfoPtr info = mojom::EventFilteringInfo::New();
     info->url = url;
     return std::make_unique<Event>(
-        events::FOR_TEST, event_name, std::vector<base::Value>(), nullptr,
-        GURL(), EventRouter::USER_GESTURE_UNKNOWN, std::move(info));
+        events::FOR_TEST, event_name, base::Value::List(), nullptr, GURL(),
+        EventRouter::USER_GESTURE_UNKNOWN, std::move(info));
   }
 
   std::unique_ptr<EventListener> CreateLazyListener(
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index f5f44d6..cb4cd70 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -978,9 +978,9 @@
     return;
   }
 
-  base::Value::List event_args_to_use =
-      modified_event_args ? std::move(*modified_event_args)
-                          : event.event_args->GetList().Clone();
+  base::Value::List event_args_to_use = modified_event_args
+                                            ? std::move(*modified_event_args)
+                                            : event.event_args.Clone();
 
   mojom::EventFilteringInfoPtr filter_info =
       modified_event_filter_info ? std::move(modified_event_filter_info)
@@ -1254,12 +1254,12 @@
 
 Event::Event(events::HistogramValue histogram_value,
              const std::string& event_name,
-             std::vector<base::Value> event_args)
+             base::Value::List event_args)
     : Event(histogram_value, event_name, std::move(event_args), nullptr) {}
 
 Event::Event(events::HistogramValue histogram_value,
              const std::string& event_name,
-             std::vector<base::Value> event_args,
+             base::Value::List event_args,
              content::BrowserContext* restrict_to_browser_context)
     : Event(histogram_value,
             event_name,
@@ -1271,19 +1271,18 @@
 
 Event::Event(events::HistogramValue histogram_value,
              const std::string& event_name,
-             std::vector<base::Value> event_args_tmp,
+             base::Value::List event_args_tmp,
              content::BrowserContext* restrict_to_browser_context,
              const GURL& event_url,
              EventRouter::UserGestureState user_gesture,
              mojom::EventFilteringInfoPtr info)
     : histogram_value(histogram_value),
       event_name(event_name),
-      event_args(std::make_unique<base::ListValue>(std::move(event_args_tmp))),
+      event_args(std::move(event_args_tmp)),
       restrict_to_browser_context(restrict_to_browser_context),
       event_url(event_url),
       user_gesture(user_gesture),
       filter_info(std::move(info)) {
-  DCHECK(event_args);
   DCHECK_NE(events::UNKNOWN, histogram_value)
       << "events::UNKNOWN cannot be used as a histogram value.\n"
       << "If this is a test, use events::FOR_TEST.\n"
@@ -1292,13 +1291,30 @@
       << "See extension_event_histogram_value.h for inspiration.";
 }
 
+Event::Event(events::HistogramValue histogram_value,
+             const std::string& event_name,
+             std::vector<base::Value> event_args)
+    : Event(histogram_value, event_name, std::move(event_args), nullptr) {}
+
+Event::Event(events::HistogramValue histogram_value,
+             const std::string& event_name,
+             std::vector<base::Value> event_args,
+             content::BrowserContext* restrict_to_browser_context)
+    : Event(histogram_value,
+            event_name,
+            std::move(base::Value(std::move(event_args)).GetList()),
+            restrict_to_browser_context,
+            GURL(),
+            EventRouter::USER_GESTURE_UNKNOWN,
+            mojom::EventFilteringInfo::New()) {}
+
 Event::~Event() = default;
 
 std::unique_ptr<Event> Event::DeepCopy() const {
-  auto copy = std::make_unique<Event>(histogram_value, event_name,
-                                      event_args->Clone().TakeListDeprecated(),
-                                      restrict_to_browser_context, event_url,
-                                      user_gesture, filter_info.Clone());
+  auto copy =
+      std::make_unique<Event>(histogram_value, event_name, event_args.Clone(),
+                              restrict_to_browser_context, event_url,
+                              user_gesture, filter_info.Clone());
   copy->will_dispatch_callback = will_dispatch_callback;
   return copy;
 }
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h
index 842cae8..0312b17 100644
--- a/extensions/browser/event_router.h
+++ b/extensions/browser/event_router.h
@@ -533,7 +533,7 @@
   const std::string event_name;
 
   // Arguments to send to the event listener.
-  std::unique_ptr<base::ListValue> event_args;
+  base::Value::List event_args;
 
   // If non-null, then the event will not be sent to other BrowserContexts
   // unless the extension has permission (e.g. incognito tab update -> normal
@@ -568,21 +568,33 @@
   // related browser_contexts. See https://crbug.com/726022.
   Event(events::HistogramValue histogram_value,
         const std::string& event_name,
-        std::vector<base::Value> event_args);
+        base::Value::List event_args);
 
   Event(events::HistogramValue histogram_value,
         const std::string& event_name,
-        std::vector<base::Value> event_args,
+        base::Value::List event_args,
         content::BrowserContext* restrict_to_browser_context);
 
   Event(events::HistogramValue histogram_value,
         const std::string& event_name,
-        std::vector<base::Value> event_args,
+        base::Value::List event_args,
         content::BrowserContext* restrict_to_browser_context,
         const GURL& event_url,
         EventRouter::UserGestureState user_gesture,
         mojom::EventFilteringInfoPtr info);
 
+  // Deprecated versions of the above methods.
+  //
+  // TODO(https://crbug.com/1338341): Remove these when no more callers use
+  // them, or once base::Value::ListStorage has been removed.
+  Event(events::HistogramValue histogram_value,
+        const std::string& event_name,
+        std::vector<base::Value> event_args);
+  Event(events::HistogramValue histogram_value,
+        const std::string& event_name,
+        std::vector<base::Value> event_args,
+        content::BrowserContext* restrict_to_browser_context);
+
   ~Event();
 
   // Makes a deep copy of this instance.
diff --git a/extensions/browser/events/lazy_event_dispatcher.cc b/extensions/browser/events/lazy_event_dispatcher.cc
index 884be8a2..74ea0c0 100644
--- a/extensions/browser/events/lazy_event_dispatcher.cc
+++ b/extensions/browser/events/lazy_event_dispatcher.cc
@@ -99,8 +99,7 @@
       return true;
     }
     if (modified_event_args) {
-      dispatched_event->event_args = base::ListValue::From(
-          std::make_unique<base::Value>(std::move(*modified_event_args)));
+      dispatched_event->event_args = std::move(*modified_event_args);
     }
     if (modified_event_filter_info)
       dispatched_event->filter_info = std::move(modified_event_filter_info);
diff --git a/extensions/browser/extension_frame_host.h b/extensions/browser/extension_frame_host.h
index 9cf2a94..abd83ac 100644
--- a/extensions/browser/extension_frame_host.h
+++ b/extensions/browser/extension_frame_host.h
@@ -31,6 +31,11 @@
       mojo::PendingAssociatedReceiver<mojom::LocalFrameHost> receiver,
       content::RenderFrameHost* rfh);
 
+  content::RenderFrameHostReceiverSet<mojom::LocalFrameHost>&
+  receivers_for_testing() {
+    return receivers_;
+  }
+
   // mojom::LocalFrameHost:
   void RequestScriptInjectionPermission(
       const std::string& extension_id,
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc
index 49eefc9e..077c179 100644
--- a/extensions/browser/extension_function.cc
+++ b/extensions/browser/extension_function.cc
@@ -680,6 +680,11 @@
 }
 
 ExtensionFunction::ResponseValue ExtensionFunction::ArgumentList(
+    base::Value::List results) {
+  return ResponseValue(new ArgumentListResponseValue(this, std::move(results)));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::ArgumentList(
     std::vector<base::Value> results) {
   base::Value::List list;
   for (auto&& value : results) {
@@ -717,14 +722,20 @@
 }
 
 ExtensionFunction::ResponseValue ExtensionFunction::ErrorWithArguments(
+    base::Value::List args,
+    const std::string& error) {
+  return ResponseValue(
+      new ErrorWithArgumentsResponseValue(this, std::move(args), error));
+}
+
+ExtensionFunction::ResponseValue ExtensionFunction::ErrorWithArguments(
     std::vector<base::Value> args,
     const std::string& error) {
   base::Value::List list;
   for (auto&& value : args) {
     list.Append(std::move(value));
   }
-  return ResponseValue(
-      new ErrorWithArgumentsResponseValue(this, std::move(list), error));
+  return ErrorWithArguments(std::move(list), error);
 }
 
 ExtensionFunction::ResponseValue ExtensionFunction::BadMessage() {
diff --git a/extensions/browser/extension_function.h b/extensions/browser/extension_function.h
index 0e92b82..82ea988 100644
--- a/extensions/browser/extension_function.h
+++ b/extensions/browser/extension_function.h
@@ -378,6 +378,11 @@
   // should be using the generated Result struct and ArgumentList.
   ResponseValue TwoArguments(base::Value arg1, base::Value arg2);
   // Success, a list of arguments |results| to pass to caller.
+  ResponseValue ArgumentList(base::Value::List results);
+  // Deprecated version of above method.
+  //
+  // TODO(https://crbug.com/1338341): Remove this when no longer needed, or when
+  // removing Value::List.
   ResponseValue ArgumentList(std::vector<base::Value> results);
   // Error. chrome.runtime.lastError.message will be set to |error|.
   ResponseValue Error(std::string error);
@@ -397,6 +402,12 @@
   // Using this ResponseValue indicates something is wrong with the API.
   // It shouldn't be possible to have both an error *and* some arguments.
   // Some legacy APIs do rely on it though, like webstorePrivate.
+  ResponseValue ErrorWithArguments(base::Value::List args,
+                                   const std::string& error);
+  // Deprecated version of above method.
+  //
+  // TODO(https://crbug.com/1338341): Remove this when no longer needed, or when
+  // removing Value::List.
   ResponseValue ErrorWithArguments(std::vector<base::Value> args,
                                    const std::string& error);
   // Bad message. A ResponseValue equivalent to EXTENSION_FUNCTION_VALIDATE(),
diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc
index 480560d2..c17f326 100644
--- a/extensions/browser/extension_function_dispatcher.cc
+++ b/extensions/browser/extension_function_dispatcher.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/debug/crash_logging.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
@@ -30,6 +31,7 @@
 #include "content/public/common/result_codes.h"
 #include "extensions/browser/api_activity_monitor.h"
 #include "extensions/browser/bad_message.h"
+#include "extensions/browser/content_script_tracker.h"
 #include "extensions/browser/extension_function_registry.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
@@ -42,9 +44,11 @@
 #include "extensions/common/extension_api.h"
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/extension_set.h"
+#include "extensions/common/extension_urls.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_macros.h"
 #include "mojo/public/cpp/bindings/message.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 using content::BrowserThread;
 
@@ -73,6 +77,143 @@
   std::move(callback).Run(type, base::Value::List(), error);
 }
 
+// Returns `true` if `render_process_host` can legitimately claim to send IPC
+// messages on behalf of `extension_id`.  `render_frame_host` parameter is
+// needed to account for scenarios involving a Chrome Web Store frame.
+bool CanRendererActOnBehalfOfExtension(
+    const ExtensionId& extension_id,
+    content::RenderFrameHost* render_frame_host,
+    content::RenderProcessHost& render_process_host) {
+  // TODO(lukasza): Some of the checks below can be restricted to specific
+  // context types (e.g. an empty `extension_id` should not happen in an
+  // extension context;  and the SiteInstance-based check should only be needed
+  // for hosted apps).  Consider leveraging ProcessMap::GetMostLikelyContextType
+  // to implement this kind of restrictions.  Note that
+  // ExtensionFunctionDispatcher::CreateExtensionFunction already calls
+  // GetMostLikelyContextType - some refactoring might be needed to avoid
+  // duplicating the work.
+
+  // Allow empty extension id (it seems okay to assume that no
+  // extension-specific special powers will be granted without an extension id).
+  // For instance, WebUI pages may call private APIs like developerPrivate,
+  // settingsPrivate, metricsPrivate, and others. In these cases, there is no
+  // associated extension ID.
+  //
+  // TODO(lukasza): Investigate if the exception below can be avoided if
+  // `render_process_host` hosts HTTP origins (i.e. if the exception can be
+  // restricted to NTP, and/or chrome://... cases.
+  if (extension_id.empty())
+    return true;
+
+  // Did `render_process_id` run a content script from `extension_id`?
+  if (ContentScriptTracker::DidProcessRunContentScriptFromExtension(
+          render_process_host, extension_id)) {
+    return true;
+  }
+
+  // Can `render_process_id` host a chrome-extension:// origin (frame, worker,
+  // etc.)?
+  if (util::CanRendererHostExtensionOrigin(render_process_host.GetID(),
+                                           extension_id)) {
+    return true;
+  }
+
+  if (render_frame_host) {
+    DCHECK_EQ(render_process_host.GetID(),
+              render_frame_host->GetProcess()->GetID());
+    content::SiteInstance& site_instance =
+        *render_frame_host->GetSiteInstance();
+
+    // Chrome Extension APIs can be accessed from some hosted apps.
+    //
+    // Today this is mostly needed by the Chrome Web Store's hosted app, but the
+    // code below doesn't make this assumption and allows *all* hosted apps
+    // based on the trustworthy, Browser-side information from the SiteInstance
+    // / SiteURL.  This way the code is resilient to future changes + there are
+    // concerns that `chrome.test.sendMessage` might already be exposed to
+    // hosted apps (but maybe not covered by tests).
+    //
+    // Note that the condition below allows all extensions (i.e. not just hosted
+    // apps), but hosted apps aren't covered by the
+    // `CanRendererHostExtensionOrigin` call above (because the process lock of
+    // hosted apps is based on a https://, rather than chrome-extension:// url).
+    //
+    // GuestView is explicitly excluded, because we don't want to allow
+    // GuestViews to spoof the extension id of their host.
+    if (!site_instance.IsGuest() &&
+        extension_id == util::GetExtensionIdForSiteInstance(site_instance)) {
+      return true;
+    }
+  }
+
+  // Disallow any other cases.
+  return false;
+}
+
+absl::optional<bad_message::BadMessageReason> ValidateRequest(
+    const mojom::RequestParams& params,
+    content::RenderFrameHost* render_frame_host,
+    content::RenderProcessHost& render_process_host) {
+  if ((render_frame_host && IsRequestFromServiceWorker(params)) ||
+      (!render_frame_host && !IsRequestFromServiceWorker(params))) {
+    return bad_message::EFD_BAD_MESSAGE;
+  }
+
+  if (!CanRendererActOnBehalfOfExtension(params.extension_id, render_frame_host,
+                                         render_process_host)) {
+    return bad_message::EFD_INVALID_EXTENSION_ID_FOR_PROCESS;
+  }
+
+  // TODO(https://crbug.com/1186447): Validate `params.user_gesture`.
+
+  return absl::nullopt;
+}
+
+const char* ToString(bad_message::BadMessageReason bad_message_code) {
+  switch (bad_message_code) {
+    case bad_message::BadMessageReason::EFD_BAD_MESSAGE:
+      return "LocalFrameHost::Request got a bad message.";
+    case bad_message::BadMessageReason::EFD_INVALID_EXTENSION_ID_FOR_PROCESS:
+      return "LocalFrameHost::Request: renderer never hosted such extension";
+    default:
+      NOTREACHED();
+      return "LocalFrameHost::Request encountered unrecognized validation "
+             "error.";
+  }
+}
+
+// Helper for logging crash keys related to a the IPC payload from
+// mojom::RequestParams.
+class ScopedRequestParamsCrashKeys {
+ public:
+  explicit ScopedRequestParamsCrashKeys(const mojom::RequestParams& params)
+      : name_(GetNameCrashKey(), params.name),
+        extension_id_(GetExtensionIdCrashKey(), params.extension_id) {}
+
+  ~ScopedRequestParamsCrashKeys() = default;
+
+  // No copy constructor and no copy assignment operator.
+  ScopedRequestParamsCrashKeys(const ScopedRequestParamsCrashKeys&) = delete;
+  ScopedRequestParamsCrashKeys& operator=(const ScopedRequestParamsCrashKeys&) =
+      delete;
+
+ private:
+  static base::debug::CrashKeyString* GetNameCrashKey() {
+    static auto* crash_key = base::debug::AllocateCrashKeyString(
+        "RequestParams::name", base::debug::CrashKeySize::Size256);
+    return crash_key;
+  }
+
+  static base::debug::CrashKeyString* GetExtensionIdCrashKey() {
+    static auto* crash_key = base::debug::AllocateCrashKeyString(
+        "RequestParams::extension_id", base::debug::CrashKeySize::Size64);
+    return crash_key;
+  }
+
+  base::debug::ScopedCrashKeyString name_;
+  base::debug::ScopedCrashKeyString extension_id_;
+};
+
 }  // namespace
 
 class ExtensionFunctionDispatcher::ResponseCallbackWrapper
@@ -237,12 +378,18 @@
     mojom::RequestParamsPtr params,
     content::RenderFrameHost& frame,
     mojom::LocalFrameHost::RequestCallback callback) {
-  if (IsRequestFromServiceWorker(*params)) {
-    constexpr char kBadMessage[] = "LocalFrameHost::Request got a bad message.";
-    std::move(callback).Run(ExtensionFunction::FAILED, base::Value::List(),
-                            kBadMessage);
+  ScopedRequestParamsCrashKeys request_params_crash_keys(*params);
+  SCOPED_CRASH_KEY_STRING256(
+      "extensions", "frame.GetSiteInstance()",
+      frame.GetSiteInstance()->GetSiteURL().possibly_invalid_spec());
+
+  if (auto bad_message_code =
+          ValidateRequest(*params, &frame, *frame.GetProcess())) {
     // Kill the renderer if it's an invalid request.
-    mojo::ReportBadMessage(kBadMessage);
+    const char* msg = ToString(*bad_message_code);
+    std::move(callback).Run(ExtensionFunction::FAILED, base::Value::List(),
+                            msg);
+    mojo::ReportBadMessage(msg);
     return;
   }
 
@@ -265,19 +412,24 @@
 void ExtensionFunctionDispatcher::DispatchForServiceWorker(
     const mojom::RequestParams& params,
     int render_process_id) {
-  if (!IsRequestFromServiceWorker(params)) {
-    // Kill the renderer if it's an invalid request.
-    bad_message::ReceivedBadMessage(render_process_id,
-                                    bad_message::EFD_BAD_MESSAGE);
-    return;
-  }
+  ScopedRequestParamsCrashKeys request_params_crash_keys(params);
 
+  // The IPC might race with RenderProcessHost destruction.  This may only
+  // happen in scenarios that are already inherently racey, so dropping the IPC
+  // is okay and won't lead to any additional risk of data loss.  Continuing is
+  // impossible, because WorkerResponseCallbackWrapper requires render process
+  // host to be around.
   content::RenderProcessHost* rph =
       content::RenderProcessHost::FromID(render_process_id);
-  // WorkerResponseCallbackWrapper requires render process host to be around.
   if (!rph)
     return;
 
+  if (auto bad_message_code = ValidateRequest(params, nullptr, *rph)) {
+    // Kill the renderer if it's an invalid request.
+    bad_message::ReceivedBadMessage(render_process_id, *bad_message_code);
+    return;
+  }
+
   WorkerId worker_id{params.extension_id, render_process_id,
                      params.service_worker_version_id, params.worker_thread_id};
   // Ignore if the worker has already stopped.
diff --git a/extensions/browser/extension_util.cc b/extensions/browser/extension_util.cc
index 7d8a3fe7..d651368 100644
--- a/extensions/browser/extension_util.cc
+++ b/extensions/browser/extension_util.cc
@@ -9,12 +9,15 @@
 #include "base/no_destructor.h"
 #include "build/chromeos_buildflags.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/cors_origin_pattern_setter.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/storage_partition_config.h"
+#include "content/public/common/url_constants.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_browser_client.h"
+#include "extensions/browser/process_manager.h"
 #include "extensions/browser/ui_util.h"
 #include "extensions/common/cors_util.h"
 #include "extensions/common/extension.h"
@@ -26,6 +29,7 @@
 #include "extensions/common/manifest_handlers/shared_module_info.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "mojo/public/cpp/bindings/clone_traits.h"
+#include "url/gurl.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "base/system/sys_info.h"
@@ -75,7 +79,7 @@
           extension->location() == mojom::ManifestLocation::kComponent);
 }
 
-bool IsIncognitoEnabled(const std::string& extension_id,
+bool IsIncognitoEnabled(const ExtensionId& extension_id,
                         content::BrowserContext* context) {
   const Extension* extension =
       ExtensionRegistry::Get(context)->GetExtensionById(
@@ -113,7 +117,7 @@
 }
 
 content::StoragePartitionConfig GetStoragePartitionConfigForExtensionId(
-    const std::string& extension_id,
+    const ExtensionId& extension_id,
     content::BrowserContext* browser_context) {
   if (ExtensionsBrowserClient::Get()->HasIsolatedStorage(extension_id,
                                                          browser_context)) {
@@ -129,7 +133,7 @@
 }
 
 content::StoragePartition* GetStoragePartitionForExtensionId(
-    const std::string& extension_id,
+    const ExtensionId& extension_id,
     content::BrowserContext* browser_context,
     bool can_create) {
   auto storage_partition_config =
@@ -170,7 +174,7 @@
 
   if (SharedModuleInfo::IsImportedPath(path)) {
     // Check if this is a valid path that is imported for this extension.
-    std::string new_extension_id;
+    ExtensionId new_extension_id;
     std::string new_relative_path;
     SharedModuleInfo::ParseImportedPath(path, &new_extension_id,
                                         &new_relative_path);
@@ -285,5 +289,29 @@
   }
 }
 
+// TODO(solomonkinard): Take into account GUID-based dynamic URLs.
+ExtensionId GetExtensionIdForSiteInstance(
+    content::SiteInstance& site_instance) {
+  // <webview> guests always store the ExtensionId in the partition domain.
+  if (site_instance.IsGuest())
+    return site_instance.GetStoragePartitionConfig().partition_domain();
+
+  // This works for both apps and extensions because the site has been
+  // normalized to the extension URL for hosted apps.
+  const GURL& site_url = site_instance.GetSiteURL();
+  if (site_url.SchemeIs(kExtensionScheme))
+    return site_url.host();
+
+  return ExtensionId();
+}
+
+bool CanRendererHostExtensionOrigin(int render_process_id,
+                                    const ExtensionId& extension_id) {
+  url::Origin extension_origin =
+      Extension::CreateOriginFromExtensionId(extension_id);
+  auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
+  return policy->CanAccessDataForOrigin(render_process_id, extension_origin);
+}
+
 }  // namespace util
 }  // namespace extensions
diff --git a/extensions/browser/extension_util.h b/extensions/browser/extension_util.h
index 85bd1d8f..22fe192 100644
--- a/extensions/browser/extension_util.h
+++ b/extensions/browser/extension_util.h
@@ -18,6 +18,7 @@
 
 namespace content {
 class BrowserContext;
+class SiteInstance;
 class StoragePartition;
 class StoragePartitionConfig;
 }
@@ -36,7 +37,7 @@
 bool CanBeIncognitoEnabled(const Extension* extension);
 
 // Returns true if |extension_id| can run in an incognito window.
-bool IsIncognitoEnabled(const std::string& extension_id,
+bool IsIncognitoEnabled(const ExtensionId& extension_id,
                         content::BrowserContext* context);
 
 // Returns true if |extension| can see events and data from another sub-profile
@@ -52,11 +53,11 @@
 // associated with |extension_id| has isolated storage.
 // Otherwise, return the default StoragePartitionConfig.
 content::StoragePartitionConfig GetStoragePartitionConfigForExtensionId(
-    const std::string& extension_id,
+    const ExtensionId& extension_id,
     content::BrowserContext* browser_context);
 
 content::StoragePartition* GetStoragePartitionForExtensionId(
-    const std::string& extension_id,
+    const ExtensionId& extension_id,
     content::BrowserContext* browser_context,
     bool can_create = true);
 
@@ -75,7 +76,7 @@
 // extension.
 bool CanWithholdPermissionsFromExtension(const Extension& extension);
 bool CanWithholdPermissionsFromExtension(
-    const std::string& extension_id,
+    const ExtensionId& extension_id,
     const Manifest::Type type,
     const mojom::ManifestLocation location);
 
@@ -106,6 +107,16 @@
     const std::string& extension_id,
     content::BrowserContext* browser_context);
 
+// Gets the ExtensionId associated with the given `site_instance`.  An empty
+// string is returned when `site_instance` is not associated with an extension.
+ExtensionId GetExtensionIdForSiteInstance(content::SiteInstance& site_instance);
+
+// Returns true if the process corresponding to `render_process_id` can host an
+// extension with `extension_id`.  (It doesn't necessarily mean that the process
+// *does* host this specific extension at this point in time.)
+bool CanRendererHostExtensionOrigin(int render_process_id,
+                                    const ExtensionId& extension_id);
+
 }  // namespace util
 }  // namespace extensions
 
diff --git a/extensions/browser/extension_util_unittest.cc b/extensions/browser/extension_util_unittest.cc
index 6efa6e7..69c8859 100644
--- a/extensions/browser/extension_util_unittest.cc
+++ b/extensions/browser/extension_util_unittest.cc
@@ -4,11 +4,19 @@
 
 #include "extensions/browser/extension_util.h"
 
+#include "base/memory/ref_counted.h"
 #include "base/path_service.h"
+#include "base/strings/strcat.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_content_client_initializer.h"
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/extension_paths.h"
 #include "extensions/common/extension_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/url_constants.h"
 
 namespace extensions {
 namespace {
@@ -56,4 +64,35 @@
                                           &does_not_exist_path));
   EXPECT_FALSE(does_not_exist_path.empty());
 }
+
+TEST(ExtensionUtilTest, ExtensionIdForSiteInstance) {
+  content::BrowserTaskEnvironment test_environment;
+  content::TestBrowserContext test_context;
+
+  // Extension.
+  const ExtensionId kExtensionId1(32, 'a');
+  scoped_refptr<content::SiteInstance> extension_site_instance =
+      content::SiteInstance::CreateForURL(
+          &test_context, Extension::GetBaseURLFromExtensionId(kExtensionId1));
+  EXPECT_EQ(kExtensionId1,
+            util::GetExtensionIdForSiteInstance(*extension_site_instance));
+
+  // GuestView.
+  const ExtensionId kExtensionId2(32, 'b');
+  scoped_refptr<content::SiteInstance> guest_site_instance =
+      content::SiteInstance::CreateForGuest(
+          &test_context,
+          content::StoragePartitionConfig::Create(&test_context, kExtensionId2,
+                                                  "fake_storage_partition_id",
+                                                  true /* in_memory */));
+  EXPECT_EQ(kExtensionId2,
+            util::GetExtensionIdForSiteInstance(*guest_site_instance));
+
+  // Http.
+  scoped_refptr<content::SiteInstance> https_site_instance =
+      content::SiteInstance::CreateForURL(&test_context,
+                                          GURL("https://example.com"));
+  EXPECT_EQ("", util::GetExtensionIdForSiteInstance(*https_site_instance));
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
index aef9d1a..d7dcd90 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
@@ -338,8 +338,8 @@
   if (!attached() || !plugin_can_save_)
     return false;
 
-  base::ListValue::ListStorage args;
-  args.emplace_back(stream_->stream_url().spec());
+  base::ListValue::List args;
+  args.Append(stream_->stream_url().spec());
 
   auto event =
       std::make_unique<Event>(events::MIME_HANDLER_PRIVATE_SAVE,
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index 4d09fbd..1952407 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -95,25 +95,10 @@
   return base::Milliseconds(kEventPageSuspendDelayMs.Get());
 }
 
-// TODO(solomonkinard): Take into account GUID-based dynamic URLs.
-std::string GetExtensionIdForSiteInstance(
-    content::SiteInstance* site_instance) {
-  // <webview> guests always store the ExtensionId in the partition domain.
-  if (site_instance->IsGuest())
-    return site_instance->GetStoragePartitionConfig().partition_domain();
-
-  // This works for both apps and extensions because the site has been
-  // normalized to the extension URL for hosted apps.
-  const GURL& site_url = site_instance->GetSiteURL();
-  if (site_url.SchemeIs(kExtensionScheme))
-    return site_url.host();
-
-  return std::string();
-}
-
 std::string GetExtensionID(content::RenderFrameHost* render_frame_host) {
   CHECK(render_frame_host);
-  return GetExtensionIdForSiteInstance(render_frame_host->GetSiteInstance());
+  return util::GetExtensionIdForSiteInstance(
+      *render_frame_host->GetSiteInstance());
 }
 
 bool IsFrameInExtensionHost(ExtensionHost* extension_host,
@@ -480,7 +465,8 @@
     return nullptr;
   const Extension* extension =
       extension_registry_->enabled_extensions().GetByID(
-          GetExtensionIdForSiteInstance(web_contents->GetSiteInstance()));
+          util::GetExtensionIdForSiteInstance(
+              *web_contents->GetSiteInstance()));
   if (extension && extension->is_hosted_app()) {
     // For hosted apps, be sure to exclude URLs outside of the app that might
     // be loaded in the same SiteInstance (extensions guarantee that only
diff --git a/extensions/shell/browser/shell_extensions_browser_client.cc b/extensions/shell/browser/shell_extensions_browser_client.cc
index 8a18c64..4e37d62 100644
--- a/extensions/shell/browser/shell_extensions_browser_client.cc
+++ b/extensions/shell/browser/shell_extensions_browser_client.cc
@@ -251,12 +251,8 @@
     return;
   }
 
-  std::vector<base::Value> event_args(args.size());
-  std::transform(args.begin(), args.end(), event_args.begin(),
-                 [](const base::Value& arg) { return arg.Clone(); });
-
-  auto event = std::make_unique<Event>(histogram_value, event_name,
-                                       std::move(event_args));
+  auto event =
+      std::make_unique<Event>(histogram_value, event_name, std::move(args));
   EventRouter::Get(browser_context_)->BroadcastEvent(std::move(event));
 }
 
diff --git a/fuchsia/DEPS b/fuchsia/DEPS
deleted file mode 100644
index bb1cb57..0000000
--- a/fuchsia/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-include_rules = [
-  # The //fuchsia directory is effectively a top-level directory under which
-  # components that exist only on Fuchsia are defined. As such we do not allow
-  # sub-directories to reference one another without explicit opt-in.
-  "-fuchsia",
-]
\ No newline at end of file
diff --git a/fuchsia/DIR_METADATA b/fuchsia/DIR_METADATA
deleted file mode 100644
index 7bba048..0000000
--- a/fuchsia/DIR_METADATA
+++ /dev/null
@@ -1,9 +0,0 @@
-# Metadata information for this directory.
-#
-# For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
-#
-# For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
-
-mixins: "//build/fuchsia/COMMON_METADATA"
diff --git a/fuchsia/OWNERS b/fuchsia/OWNERS
deleted file mode 100644
index ff7d7e1..0000000
--- a/fuchsia/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-set noparent
-file://build/fuchsia/OWNERS
diff --git a/fuchsia/base/DEPS b/fuchsia/base/DEPS
deleted file mode 100644
index 02fe90e..0000000
--- a/fuchsia/base/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-include_rules = [
-  "+fuchsia_web/common",
-  "+mojo/public",
-  "+third_party/blink/public/common/messaging",
-  "+third_party/blink/public/mojom/messaging",
-]
diff --git a/fuchsia_web/common/BUILD.gn b/fuchsia_web/common/BUILD.gn
index 26dd70b..edc8f37 100644
--- a/fuchsia_web/common/BUILD.gn
+++ b/fuchsia_web/common/BUILD.gn
@@ -8,8 +8,6 @@
 visibility = [ "//fuchsia_web/*" ]
 
 source_set("common") {
-  # TODO(crbug.com/1081525): Remove once directory is deleted.
-  visibility += [ "//fuchsia/base/test/*" ]
   sources = [
     "fuchsia_dir_scheme.cc",
     "init_logging.cc",
diff --git a/fuchsia_web/common/test/BUILD.gn b/fuchsia_web/common/test/BUILD.gn
index 468d7b8..b8fb2504 100644
--- a/fuchsia_web/common/test/BUILD.gn
+++ b/fuchsia_web/common/test/BUILD.gn
@@ -9,9 +9,6 @@
 
 source_set("test_support") {
   testonly = true
-
-  # TODO(crbug.com/1081525): Remove once directory is deleted.
-  visibility += [ "//fuchsia/base/*" ]
   sources = [
     "fit_adapter.h",
     "frame_test_util.cc",
@@ -25,7 +22,6 @@
   ]
   public_deps = [
     "//base",
-    "//fuchsia/base:modular",
     "//fuchsia_web/common",
     "//net",
     "//net:test_support",
diff --git a/fuchsia_web/runners/BUILD.gn b/fuchsia_web/runners/BUILD.gn
index 1e9207b..418293e 100644
--- a/fuchsia_web/runners/BUILD.gn
+++ b/fuchsia_web/runners/BUILD.gn
@@ -34,7 +34,7 @@
   deps = [
     ":buildflags",
     "//base",
-    "//fuchsia/base:modular",
+    "//fuchsia_web/runners/common/modular",
     "//fuchsia_web/webinstance_host",
     "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
     "//ui/gfx/geometry",
@@ -83,12 +83,13 @@
     "//components/cast/message_port",
     "//components/cast/named_message_port_connector:named_message_port_connector",
     "//components/fuchsia_component_support",
-    "//fuchsia/base:modular",
+    "//fuchsia_web/runners/common/modular",
 
     # TODO(crbug.com/852834): Remove this dependency when
     # kAudioCapturerWithEchoCancellation is removed.
     "//media",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.diagnostics",
+    "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.legacymetrics",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.modular",
     "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
@@ -99,7 +100,6 @@
   public_deps = [
     ":common",
     "./cast/fidl",
-    "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.legacymetrics",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.web",
   ]
 
@@ -209,6 +209,7 @@
   deps = [
     ":cast_runner_core",
     ":cast_runner_test_core",
+    "common/modular:unit_tests",
     "//base",
     "//base/test:run_all_unittests",
     "//base/test:test_support",
@@ -224,8 +225,8 @@
 test("cast_runner_integration_tests_cfv1") {
   sources = [
     "cast/cast_runner_integration_test.cc",
-    "cast/fake_component_context.cc",
-    "cast/fake_component_context.h",
+    "common/modular/fake_component_context.cc",
+    "common/modular/fake_component_context.h",
   ]
   data = [ "cast/testdata" ]
   deps = [
@@ -235,10 +236,12 @@
     "//components/cast/message_port",
     "//fuchsia_web/common/test:run_all_integration_tests",
     "//fuchsia_web/common/test:test_support",
+    "//fuchsia_web/runners/common/modular",
     "//media/fuchsia/audio:test_support",
     "//net:test_support",
     "//testing/gtest",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.camera3",
+    "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.legacymetrics",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.media",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.modular",
     "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp",
@@ -331,8 +334,8 @@
     "//base",
     "//base/test:test_support",
     "//components/cast/message_port",
-    "//fuchsia/base:modular",
     "//fuchsia_web/common/test:run_all_integration_tests",
+    "//fuchsia_web/runners/common/modular",
     "//net:test_support",
     "//testing/gtest",
     "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sys",
diff --git a/fuchsia_web/runners/DEPS b/fuchsia_web/runners/DEPS
index a12232e4..3ccec9cd 100644
--- a/fuchsia_web/runners/DEPS
+++ b/fuchsia_web/runners/DEPS
@@ -1,5 +1,4 @@
 include_rules  =  [
   "+components/fuchsia_component_support",
-  "+fuchsia/base",
   "+fuchsia_web/webinstance_host",
 ]
diff --git a/fuchsia_web/runners/cast/cast_component.cc b/fuchsia_web/runners/cast/cast_component.cc
index 985cb75e..f9e9129 100644
--- a/fuchsia_web/runners/cast/cast_component.cc
+++ b/fuchsia_web/runners/cast/cast_component.cc
@@ -4,6 +4,7 @@
 
 #include "fuchsia_web/runners/cast/cast_component.h"
 
+#include <fuchsia/legacymetrics/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
 #include <lib/ui/scenic/cpp/view_ref_pair.h>
 #include <algorithm>
@@ -18,11 +19,11 @@
 #include "base/task/current_thread.h"
 #include "components/cast/message_port/fuchsia/message_port_fuchsia.h"
 #include "components/cast/message_port/platform_message_port.h"
-#include "fuchsia/base/agent_manager.h"
 #include "fuchsia_web/runners/cast/cast_runner.h"
 #include "fuchsia_web/runners/cast/cast_streaming.h"
 #include "fuchsia_web/runners/cast/create_web_message.h"
 #include "fuchsia_web/runners/cast/fidl/fidl/chromium/cast/cpp/fidl.h"
+#include "fuchsia_web/runners/common/modular/agent_manager.h"
 #include "fuchsia_web/runners/common/web_component.h"
 
 namespace {
diff --git a/fuchsia_web/runners/cast/cast_component.h b/fuchsia_web/runners/cast/cast_component.h
index cffb3a89..50a973e9 100644
--- a/fuchsia_web/runners/cast/cast_component.h
+++ b/fuchsia_web/runners/cast/cast_component.h
@@ -6,7 +6,6 @@
 #define FUCHSIA_WEB_RUNNERS_CAST_CAST_COMPONENT_H_
 
 #include <fuchsia/camera3/cpp/fidl.h>
-#include <fuchsia/legacymetrics/cpp/fidl.h>
 #include <fuchsia/media/cpp/fidl.h>
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
@@ -27,6 +26,10 @@
 #include "fuchsia_web/runners/common/web_component.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
+namespace fuchsia::legacymetrics {
+class MetricsRecorder;
+}
+
 namespace cr_fuchsia {
 class AgentManager;
 }
diff --git a/fuchsia_web/runners/cast/cast_runner.cc b/fuchsia_web/runners/cast/cast_runner.cc
index a132087c..9e7e6a2 100644
--- a/fuchsia_web/runners/cast/cast_runner.cc
+++ b/fuchsia_web/runners/cast/cast_runner.cc
@@ -4,6 +4,7 @@
 
 #include "fuchsia_web/runners/cast/cast_runner.h"
 
+#include <fuchsia/legacymetrics/cpp/fidl.h>
 #include <fuchsia/sys/cpp/fidl.h>
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/fit/function.h>
@@ -27,7 +28,6 @@
 #include "base/values.h"
 #include "components/cast/common/constants.h"
 #include "components/fuchsia_component_support/config_reader.h"
-#include "fuchsia/base/agent_manager.h"
 #include "fuchsia_web/runners/cast/cast_streaming.h"
 #include "fuchsia_web/runners/cast/pending_cast_component.h"
 #include "fuchsia_web/runners/common/web_content_runner.h"
@@ -73,6 +73,7 @@
     "fuchsia.ui.composition.Flatland",
     "fuchsia.ui.input3.Keyboard",
     "fuchsia.ui.scenic.Scenic",
+    "fuchsia.tracing.perfetto.ProducerConnector",
     "fuchsia.vulkan.loader.Loader",
 };
 
diff --git a/fuchsia_web/runners/cast/cast_runner.cml b/fuchsia_web/runners/cast/cast_runner.cml
index f14c2f54..b2c765b4 100644
--- a/fuchsia_web/runners/cast/cast_runner.cml
+++ b/fuchsia_web/runners/cast/cast_runner.cml
@@ -65,6 +65,7 @@
         "fuchsia.settings.Display",
         "fuchsia.sys.Environment",
         "fuchsia.sys.Loader",
+        "fuchsia.tracing.perfetto.ProducerConnector",
         "fuchsia.ui.composition.Allocator",
         "fuchsia.ui.composition.Flatland",
         "fuchsia.ui.input3.Keyboard",
diff --git a/fuchsia_web/runners/cast/cast_runner.cmx b/fuchsia_web/runners/cast/cast_runner.cmx
index eaf7f8b..258e264 100644
--- a/fuchsia_web/runners/cast/cast_runner.cmx
+++ b/fuchsia_web/runners/cast/cast_runner.cmx
@@ -36,6 +36,7 @@
       "fuchsia.sys.Loader",
       "fuchsia.sys.Runner-cast",
       "fuchsia.sysmem.Allocator",
+      "fuchsia.tracing.perfetto.ProducerConnector",
       "fuchsia.ui.composition.Allocator",
       "fuchsia.ui.composition.Flatland",
       "fuchsia.ui.input3.Keyboard",
diff --git a/fuchsia_web/runners/cast/cast_runner.h b/fuchsia_web/runners/cast/cast_runner.h
index 44b88dc9..a79231f 100644
--- a/fuchsia_web/runners/cast/cast_runner.h
+++ b/fuchsia_web/runners/cast/cast_runner.h
@@ -6,7 +6,6 @@
 #define FUCHSIA_WEB_RUNNERS_CAST_CAST_RUNNER_H_
 
 #include <fuchsia/camera3/cpp/fidl.h>
-#include <fuchsia/legacymetrics/cpp/fidl.h>
 #include <fuchsia/media/cpp/fidl.h>
 #include <fuchsia/sys/cpp/fidl.h>
 #include <fuchsia/web/cpp/fidl.h>
@@ -28,6 +27,10 @@
 class FilteredServiceDirectory;
 }  // namespace base
 
+namespace fuchsia::legacymetrics {
+class MetricsRecorder;
+}
+
 namespace cr_fuchsia {
 class WebInstanceHost;
 }  // namespace cr_fuchsia
diff --git a/fuchsia_web/runners/cast/cast_runner_integration_test.cc b/fuchsia_web/runners/cast/cast_runner_integration_test.cc
index 9aa8072..b3afe09 100644
--- a/fuchsia_web/runners/cast/cast_runner_integration_test.cc
+++ b/fuchsia_web/runners/cast/cast_runner_integration_test.cc
@@ -41,7 +41,6 @@
 #include "base/test/test_timeouts.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "build/build_config.h"
-#include "fuchsia/base/agent_impl.h"
 #include "fuchsia_web/common/string_util.h"
 #include "fuchsia_web/common/test/fit_adapter.h"
 #include "fuchsia_web/common/test/frame_test_util.h"
@@ -51,8 +50,9 @@
 #include "fuchsia_web/runners/cast/cast_runner_switches.h"
 #include "fuchsia_web/runners/cast/fake_api_bindings.h"
 #include "fuchsia_web/runners/cast/fake_application_config_manager.h"
-#include "fuchsia_web/runners/cast/fake_component_context.h"
 #include "fuchsia_web/runners/cast/fidl/fidl/chromium/cast/cpp/fidl.h"
+#include "fuchsia_web/runners/common/modular/agent_impl.h"
+#include "fuchsia_web/runners/common/modular/fake_component_context.h"
 #include "media/fuchsia/audio/fake_audio_device_enumerator.h"
 #include "net/test/embedded_test_server/default_handlers.h"
 #include "net/test/embedded_test_server/http_request.h"
diff --git a/fuchsia_web/runners/cast/pending_cast_component.cc b/fuchsia_web/runners/cast/pending_cast_component.cc
index ae97e50..6ace6b9e 100644
--- a/fuchsia_web/runners/cast/pending_cast_component.cc
+++ b/fuchsia_web/runners/cast/pending_cast_component.cc
@@ -8,7 +8,7 @@
 #include "base/check.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/strings/string_piece.h"
-#include "fuchsia/base/agent_manager.h"
+#include "fuchsia_web/runners/common/modular/agent_manager.h"
 
 PendingCastComponent::PendingCastComponent(
     Delegate* delegate,
diff --git a/fuchsia/base/BUILD.gn b/fuchsia_web/runners/common/modular/BUILD.gn
similarity index 77%
rename from fuchsia/base/BUILD.gn
rename to fuchsia_web/runners/common/modular/BUILD.gn
index c43860b1..57b2fd60 100644
--- a/fuchsia/base/BUILD.gn
+++ b/fuchsia_web/runners/common/modular/BUILD.gn
@@ -6,14 +6,16 @@
 
 import("//testing/test.gni")
 
+# Only allow use by targets in this directory unless explicitly specified.
+visibility = [ ":*" ]
+
 # Integration helpers for fuchsia.modular.
+# TODO(crbug.com/1280705): Delete this directory once fully migrated to CFv2.
 source_set("modular") {
   # Only for use by Fuchsia Components.
-  visibility = [
-    ":cr_fuchsia_base_unittests__exec",
-    "./test/*",
+  visibility += [
+    ":unit_tests",
     "//chromecast/internal/*",
-    "//fuchsia_web/common/test/*",
     "//fuchsia_web/runners/*",
     "//fuchsia_web/webengine/*",
   ]
@@ -32,8 +34,9 @@
   ]
 }
 
-# Unit-tests for all //fuchsia/base utilities.
-test("cr_fuchsia_base_unittests") {
+source_set("unit_tests") {
+  testonly = true
+  visibility += [ "//fuchsia_web/runners/*" ]
   sources = [ "agent_impl_unittest.cc" ]
   deps = [
     ":modular",
diff --git a/fuchsia/base/agent_impl.cc b/fuchsia_web/runners/common/modular/agent_impl.cc
similarity index 70%
rename from fuchsia/base/agent_impl.cc
rename to fuchsia_web/runners/common/modular/agent_impl.cc
index f4d6496..2fbcebf 100644
--- a/fuchsia/base/agent_impl.cc
+++ b/fuchsia_web/runners/common/modular/agent_impl.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "fuchsia/base/agent_impl.h"
+#include "fuchsia_web/runners/common/modular/agent_impl.h"
 
 #include <lib/sys/cpp/component_context.h>
 
 #include "base/bind.h"
+#include "base/fuchsia/process_context.h"
 
 namespace cr_fuchsia {
 
@@ -48,8 +49,17 @@
 AgentImpl::AgentImpl(
     sys::OutgoingDirectory* outgoing_directory,
     CreateComponentStateCallback create_component_state_callback)
+    : AgentImpl(outgoing_directory,
+                std::move(create_component_state_callback),
+                {}) {}
+
+AgentImpl::AgentImpl(
+    sys::OutgoingDirectory* outgoing_directory,
+    CreateComponentStateCallback create_component_state_callback,
+    std::vector<std::string> public_service_names)
     : create_component_state_callback_(
           std::move(create_component_state_callback)),
+      public_service_names_(std::move(public_service_names)),
       agent_binding_(outgoing_directory, this) {}
 
 AgentImpl::~AgentImpl() {
@@ -66,6 +76,21 @@
     if (!component_state)
       return;
 
+    // Add public services to the |component_state|.
+    const auto* outgoing = component_state->outgoing_directory();
+    for (const auto& service_name : public_service_names_) {
+      zx_status_t status = outgoing->AddPublicService(
+          std::make_unique<vfs::Service>(
+              [service_name](zx::channel request,
+                             async_dispatcher_t* dispatcher) {
+                base::ComponentContextForProcess()->svc()->Connect(
+                    service_name, std::move(request));
+              }),
+          service_name);
+      CHECK_EQ(status, ZX_OK);
+    }
+
+    // Register the new component's state.
     auto result =
         active_components_.emplace(requester_url, std::move(component_state));
     it = result.first;
diff --git a/fuchsia/base/agent_impl.h b/fuchsia_web/runners/common/modular/agent_impl.h
similarity index 85%
rename from fuchsia/base/agent_impl.h
rename to fuchsia_web/runners/common/modular/agent_impl.h
index b1fdaaf..e5cee3e 100644
--- a/fuchsia/base/agent_impl.h
+++ b/fuchsia_web/runners/common/modular/agent_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef FUCHSIA_BASE_AGENT_IMPL_H_
-#define FUCHSIA_BASE_AGENT_IMPL_H_
+#ifndef FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_AGENT_IMPL_H_
+#define FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_AGENT_IMPL_H_
 
 #include <fuchsia/modular/cpp/fidl.h>
 #include <lib/fidl/cpp/binding_set.h>
@@ -12,6 +12,7 @@
 #include <memory>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/containers/flat_map.h"
@@ -26,7 +27,7 @@
 // Specializations of the ComponentStateBase returned by the factory function
 // can extend it to publish specific services, and to manage per-component
 // service state as desired.
-class AgentImpl : public ::fuchsia::modular::Agent {
+class AgentImpl final : public ::fuchsia::modular::Agent {
  public:
   // Common base for per-component services and state. The base provides an
   // outgoing directory into which specializations publish their services, to
@@ -110,6 +111,15 @@
   AgentImpl(sys::OutgoingDirectory* outgoing_directory,
             CreateComponentStateCallback create_component_state_callback);
 
+  // As above, with the addition that |public_services| will be offered to all
+  // components, in addition to any services offered by the ComponentState
+  // implementations themselves. The agent process should publish the services
+  // to its outgoing-directory, and additionally list them here, to have them
+  // also available via calls by Mods to ConnectToAgentService().
+  AgentImpl(sys::OutgoingDirectory* outgoing_directory,
+            CreateComponentStateCallback create_component_state_callback,
+            std::vector<std::string> public_service_names);
+
   AgentImpl(const AgentImpl&) = delete;
   AgentImpl& operator=(const AgentImpl&) = delete;
 
@@ -129,6 +139,9 @@
   // Returns a ComponentStateBase instance for a given component-Id.
   const CreateComponentStateCallback create_component_state_callback_;
 
+  // Set of service names to publish to all components.
+  const std::vector<std::string> public_service_names_;
+
   // Binds this Agent implementation into the |outgoing_directory|.
   base::ScopedServiceBinding<::fuchsia::modular::Agent> agent_binding_;
 
@@ -139,4 +152,4 @@
 
 }  // namespace cr_fuchsia
 
-#endif  // FUCHSIA_BASE_AGENT_IMPL_H_
+#endif  // FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_AGENT_IMPL_H_
diff --git a/fuchsia/base/agent_impl_unittest.cc b/fuchsia_web/runners/common/modular/agent_impl_unittest.cc
similarity index 83%
rename from fuchsia/base/agent_impl_unittest.cc
rename to fuchsia_web/runners/common/modular/agent_impl_unittest.cc
index a2419cf..47d98fa 100644
--- a/fuchsia/base/agent_impl_unittest.cc
+++ b/fuchsia_web/runners/common/modular/agent_impl_unittest.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "fuchsia/base/agent_impl.h"
+#include "fuchsia_web/runners/common/modular/agent_impl.h"
 
 #include <lib/sys/cpp/component_context.h>
 
 #include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/test_component_context_for_process.h"
 #include "base/logging.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
@@ -88,9 +89,17 @@
 
   fuchsia::modular::AgentPtr CreateAgentAndConnect() {
     EXPECT_FALSE(agent_impl_);
-    agent_impl_ = std::make_unique<AgentImpl>(
-        &services_, base::BindRepeating(&AgentImplTest::OnComponentConnect,
-                                        base::Unretained(this)));
+    if (public_services_.empty()) {
+      agent_impl_ = std::make_unique<AgentImpl>(
+          &services_, base::BindRepeating(&AgentImplTest::OnComponentConnect,
+                                          base::Unretained(this)));
+    } else {
+      agent_impl_ = std::make_unique<AgentImpl>(
+          &services_,
+          base::BindRepeating(&AgentImplTest::OnComponentConnect,
+                              base::Unretained(this)),
+          public_services_);
+    }
     fuchsia::modular::AgentPtr agent;
     services_client_->Connect(agent.NewRequest());
     return agent;
@@ -100,6 +109,10 @@
     std::move(disconnect_clients_and_teardown_).Run();
   }
 
+  void set_public_services(std::vector<std::string> services) {
+    public_services_ = std::move(services);
+  }
+
  protected:
   std::unique_ptr<AgentImpl::ComponentStateBase> OnComponentConnect(
       base::StringPiece component_id) {
@@ -129,6 +142,10 @@
   // Set only if a keep-alive component was connected, to allow the test to
   // forcibly teardown the ComponentState for it.
   base::OnceClosure disconnect_clients_and_teardown_;
+
+  // Service names passed to the AgentImpl constructor to publish from
+  // the process' outgoing directory.
+  std::vector<std::string> public_services_;
 };
 
 }  // namespace
@@ -376,4 +393,45 @@
   }
 }
 
+// Verify that the DefaultComponentState publishes the process' outgoing
+// service directory.
+TEST_F(AgentImplTest, PublicService) {
+  base::TestComponentContextForProcess test_context;
+
+  constexpr char kServiceName[] = "base.testfidl.TestInterface-public";
+
+  // Publish a dummy service for the DefaultComponentState to "see".
+  test_context.additional_services()
+      ->AddPublicService<base::testfidl::TestInterface>(
+          [](fidl::InterfaceRequest<base::testfidl::TestInterface> request) {
+            request.Close(ZX_OK);
+          },
+          kServiceName);
+
+  // Configure the AgentImpl to provide the "public" service.
+  set_public_services({kServiceName});
+  fuchsia::modular::AgentPtr agent = CreateAgentAndConnect();
+
+  // Connect to the ServiceProvider for the a dummy component.
+  fuchsia::sys::ServiceProviderPtr component_services;
+  agent->Connect(kAccumulatorComponentId1, component_services.NewRequest());
+  base::testfidl::TestInterfacePtr test_interface;
+  component_services->ConnectToService(
+      kServiceName, test_interface.NewRequest().TakeChannel());
+
+  // Wait for the service connection to be closed, and verify that the epitaph
+  // is the expected value, rather than ZX_ERR_PEER_CLOSED.
+  base::test::TestFuture<zx_status_t> service_disconnect_status;
+  test_interface.set_error_handler(cr_fuchsia::CallbackToFitFunction(
+      service_disconnect_status.GetCallback()));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(service_disconnect_status.IsReady());
+  EXPECT_EQ(service_disconnect_status.Get(), ZX_OK);
+
+  // Close the ServiceProvider channel and spin the MessageLoop to let the
+  // AgentImpl clean up the component state.
+  component_services = nullptr;
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace cr_fuchsia
diff --git a/fuchsia/base/agent_manager.cc b/fuchsia_web/runners/common/modular/agent_manager.cc
similarity index 96%
rename from fuchsia/base/agent_manager.cc
rename to fuchsia_web/runners/common/modular/agent_manager.cc
index 0a4fbb9..d6b7a69 100644
--- a/fuchsia/base/agent_manager.cc
+++ b/fuchsia_web/runners/common/modular/agent_manager.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 "fuchsia/base/agent_manager.h"
+#include "fuchsia_web/runners/common/modular/agent_manager.h"
 
 #include <utility>
 
diff --git a/fuchsia/base/agent_manager.h b/fuchsia_web/runners/common/modular/agent_manager.h
similarity index 92%
rename from fuchsia/base/agent_manager.h
rename to fuchsia_web/runners/common/modular/agent_manager.h
index 8603820f..9247109 100644
--- a/fuchsia/base/agent_manager.h
+++ b/fuchsia_web/runners/common/modular/agent_manager.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef FUCHSIA_BASE_AGENT_MANAGER_H_
-#define FUCHSIA_BASE_AGENT_MANAGER_H_
+#ifndef FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_AGENT_MANAGER_H_
+#define FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_AGENT_MANAGER_H_
 
 #include <fuchsia/modular/cpp/fidl.h>
 #include <fuchsia/sys/cpp/fidl.h>
@@ -66,4 +66,4 @@
 
 }  // namespace cr_fuchsia
 
-#endif  // FUCHSIA_BASE_AGENT_MANAGER_H_
+#endif  // FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_AGENT_MANAGER_H_
diff --git a/fuchsia_web/runners/cast/fake_component_context.cc b/fuchsia_web/runners/common/modular/fake_component_context.cc
similarity index 92%
rename from fuchsia_web/runners/cast/fake_component_context.cc
rename to fuchsia_web/runners/common/modular/fake_component_context.cc
index bc7197a..44a890e4 100644
--- a/fuchsia_web/runners/cast/fake_component_context.cc
+++ b/fuchsia_web/runners/common/modular/fake_component_context.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 "fuchsia_web/runners/cast/fake_component_context.h"
+#include "fuchsia_web/runners/common/modular/fake_component_context.h"
 
 #include <memory>
 #include <string>
@@ -12,7 +12,7 @@
 #include "base/notreached.h"
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
-#include "fuchsia/base/agent_impl.h"
+#include "fuchsia_web/runners/common/modular/agent_impl.h"
 
 namespace cr_fuchsia {
 
diff --git a/fuchsia_web/runners/cast/fake_component_context.h b/fuchsia_web/runners/common/modular/fake_component_context.h
similarity index 88%
rename from fuchsia_web/runners/cast/fake_component_context.h
rename to fuchsia_web/runners/common/modular/fake_component_context.h
index 7ec95f0..b179c36 100644
--- a/fuchsia_web/runners/cast/fake_component_context.h
+++ b/fuchsia_web/runners/common/modular/fake_component_context.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef FUCHSIA_WEB_RUNNERS_CAST_FAKE_COMPONENT_CONTEXT_H_
-#define FUCHSIA_WEB_RUNNERS_CAST_FAKE_COMPONENT_CONTEXT_H_
+#ifndef FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_FAKE_COMPONENT_CONTEXT_H_
+#define FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_FAKE_COMPONENT_CONTEXT_H_
 
 #include <fuchsia/modular/cpp/fidl_test_base.h>
 
@@ -13,7 +13,7 @@
 #include <utility>
 
 #include "base/strings/string_piece.h"
-#include "fuchsia/base/agent_impl.h"
+#include "fuchsia_web/runners/common/modular/agent_impl.h"
 
 namespace cr_fuchsia {
 
@@ -57,4 +57,4 @@
 };
 
 }  // namespace cr_fuchsia
-#endif  // FUCHSIA_WEB_RUNNERS_CAST_FAKE_COMPONENT_CONTEXT_H_
+#endif  // FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_FAKE_COMPONENT_CONTEXT_H_
diff --git a/fuchsia/base/lifecycle_impl.cc b/fuchsia_web/runners/common/modular/lifecycle_impl.cc
similarity index 89%
rename from fuchsia/base/lifecycle_impl.cc
rename to fuchsia_web/runners/common/modular/lifecycle_impl.cc
index f8f635b..65e0da18 100644
--- a/fuchsia/base/lifecycle_impl.cc
+++ b/fuchsia_web/runners/common/modular/lifecycle_impl.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 "fuchsia/base/lifecycle_impl.h"
+#include "fuchsia_web/runners/common/modular/lifecycle_impl.h"
 
 namespace cr_fuchsia {
 
diff --git a/fuchsia/base/lifecycle_impl.h b/fuchsia_web/runners/common/modular/lifecycle_impl.h
similarity index 85%
rename from fuchsia/base/lifecycle_impl.h
rename to fuchsia_web/runners/common/modular/lifecycle_impl.h
index eef406c..6e01dbc 100644
--- a/fuchsia/base/lifecycle_impl.h
+++ b/fuchsia_web/runners/common/modular/lifecycle_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef FUCHSIA_BASE_LIFECYCLE_IMPL_H_
-#define FUCHSIA_BASE_LIFECYCLE_IMPL_H_
+#ifndef FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_LIFECYCLE_IMPL_H_
+#define FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_LIFECYCLE_IMPL_H_
 
 #include <fuchsia/modular/cpp/fidl.h>
 
@@ -38,4 +38,4 @@
 
 }  // namespace cr_fuchsia
 
-#endif  // FUCHSIA_BASE_LIFECYCLE_IMPL_H_
+#endif  // FUCHSIA_WEB_RUNNERS_COMMON_MODULAR_LIFECYCLE_IMPL_H_
diff --git a/fuchsia_web/runners/common/web_component.h b/fuchsia_web/runners/common/web_component.h
index f1968dd..13aca62 100644
--- a/fuchsia_web/runners/common/web_component.h
+++ b/fuchsia_web/runners/common/web_component.h
@@ -17,7 +17,7 @@
 
 #include "base/fuchsia/scoped_service_binding.h"
 #include "base/fuchsia/startup_context.h"
-#include "fuchsia/base/lifecycle_impl.h"
+#include "fuchsia_web/runners/common/modular/lifecycle_impl.h"
 #include "url/gurl.h"
 
 class WebContentRunner;
diff --git a/fuchsia_web/runners/web/web_runner.cmx b/fuchsia_web/runners/web/web_runner.cmx
index c98e487..fac8885 100644
--- a/fuchsia_web/runners/web/web_runner.cmx
+++ b/fuchsia_web/runners/web/web_runner.cmx
@@ -32,6 +32,7 @@
       "fuchsia.sys.Environment",
       "fuchsia.sys.Loader",
       "fuchsia.sysmem.Allocator",
+      "fuchsia.tracing.perfetto.ProducerConnector",
       "fuchsia.ui.composition.Allocator",
       "fuchsia.ui.composition.Flatland",
       "fuchsia.ui.input3.Keyboard",
diff --git a/fuchsia_web/webengine/BUILD.gn b/fuchsia_web/webengine/BUILD.gn
index 6833a16..fb54c587 100644
--- a/fuchsia_web/webengine/BUILD.gn
+++ b/fuchsia_web/webengine/BUILD.gn
@@ -119,7 +119,6 @@
     "//content/public/child",
     "//content/public/common",
     "//content/public/renderer",
-    "//fuchsia/base:modular",
     "//fuchsia_web/common",
     "//fuchsia_web/webengine/mojom",
 
diff --git a/fuchsia_web/webengine/DEPS b/fuchsia_web/webengine/DEPS
index 7577fce..ceb20f5 100644
--- a/fuchsia_web/webengine/DEPS
+++ b/fuchsia_web/webengine/DEPS
@@ -9,7 +9,6 @@
   "+components/version_info",
   "+content/public/app",
   "+content/public/common",
-  "+fuchsia/base",
   "+fuchsia_web/webinstance_host",
   "+google_apis",
   "+gpu/command_buffer/service/gpu_switches.h",
diff --git a/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc b/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
index 318faf8d..fccef31 100644
--- a/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
+++ b/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
@@ -129,9 +129,8 @@
 
   // Start the Sender
   cast_streaming::CastStreamingTestSender sender;
-  EXPECT_TRUE(sender.Start(std::move(sender_message_port),
-                           net::IPAddress::IPv6Localhost(),
-                           GetDefaultAudioConfig(), GetDefaultVideoConfig()));
+  sender.Start(std::move(sender_message_port), net::IPAddress::IPv6Localhost(),
+               GetDefaultAudioConfig(), GetDefaultVideoConfig());
 
   // Create a Frame and set the Receiver MessagePort on it.
   auto frame = cr_fuchsia::FrameForTest::Create(
@@ -146,7 +145,7 @@
       frame.GetNavigationController(), fuchsia::web::LoadUrlParams(),
       page_url.spec()));
 
-  sender.RunUntilStarted();
+  ASSERT_TRUE(sender.RunUntilActive());
   frame.navigation_listener().RunUntilTitleEquals("canplay");
 
   EXPECT_TRUE(post_result.Wait());
@@ -174,9 +173,8 @@
 
   // Start the Sender
   cast_streaming::CastStreamingTestSender sender;
-  EXPECT_TRUE(sender.Start(std::move(sender_message_port),
-                           net::IPAddress::IPv6Localhost(),
-                           GetDefaultAudioConfig(), GetDefaultVideoConfig()));
+  sender.Start(std::move(sender_message_port), net::IPAddress::IPv6Localhost(),
+               GetDefaultAudioConfig(), GetDefaultVideoConfig());
 
   // Create a Frame and set the Receiver MessagePort on it.
   auto frame = cr_fuchsia::FrameForTest::Create(
@@ -192,7 +190,7 @@
       frame.GetNavigationController(), fuchsia::web::LoadUrlParams(),
       kPageUrl.spec()));
 
-  sender.RunUntilStarted();
+  ASSERT_TRUE(sender.RunUntilActive());
   frame.navigation_listener().RunUntilTitleEquals("canplay");
 
   EXPECT_TRUE(post_result.Wait());
diff --git a/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc b/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
index afbfe35..98b998e 100644
--- a/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
+++ b/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
@@ -84,6 +84,33 @@
       ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
 }
 
+static constexpr char const* kRendererSwitchesToCopy[] = {
+    blink::switches::kSharedArrayBufferAllowedOrigins,
+    switches::kCorsExemptHeaders,
+    switches::kEnableCastStreamingReceiver,
+    switches::kEnableProtectedVideoBuffers,
+    switches::kUseOverlaysForVideo,
+
+    // TODO(crbug/1013412): Delete these two switches when fixed.
+    switches::kEnableWidevine,
+    switches::kPlayreadyKeySystem,
+
+    // Pass to the renderer process for consistency with Chrome.
+    network::switches::kUnsafelyTreatInsecureOriginAsSecure,
+};
+
+static constexpr char const*
+    kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy[] = {
+        network::switches::kUnsafelyTreatInsecureOriginAsSecure,
+};
+
+// These are passed to every child process and should only be used when it is
+// not possible to narrow the scope down to a subset of processes.
+static constexpr char const* kAllProcessSwitchesToCopy[] = {
+    // This is used by every child process in WebEngineContentClient.
+    switches::kEnableContentDirectories,
+};
+
 }  // namespace
 
 WebEngineContentBrowserClient::WebEngineContentBrowserClient()
@@ -187,22 +214,30 @@
 void WebEngineContentBrowserClient::AppendExtraCommandLineSwitches(
     base::CommandLine* command_line,
     int child_process_id) {
-  // TODO(https://crbug.com/1083520): Pass based on process type.
-  constexpr char const* kSwitchesToCopy[] = {
-      blink::switches::kSharedArrayBufferAllowedOrigins,
-      switches::kCorsExemptHeaders,
-      switches::kEnableCastStreamingReceiver,
-      switches::kEnableContentDirectories,
-      switches::kEnableProtectedVideoBuffers,
-      switches::kEnableWidevine,
-      switches::kMaxDecodedImageSizeMb,
-      switches::kPlayreadyKeySystem,
-      network::switches::kUnsafelyTreatInsecureOriginAsSecure,
-      switches::kUseOverlaysForVideo,
-  };
+  const base::CommandLine& browser_command_line =
+      *base::CommandLine::ForCurrentProcess();
 
-  command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
-                                 kSwitchesToCopy, std::size(kSwitchesToCopy));
+  command_line->CopySwitchesFrom(browser_command_line,
+                                 kAllProcessSwitchesToCopy,
+                                 std::size(kAllProcessSwitchesToCopy));
+
+  std::string process_type =
+      command_line->GetSwitchValueASCII(switches::kProcessType);
+
+  if (process_type == switches::kRendererProcess) {
+    command_line->CopySwitchesFrom(browser_command_line,
+                                   kRendererSwitchesToCopy,
+                                   std::size(kRendererSwitchesToCopy));
+  } else if (process_type == switches::kUtilityProcess) {
+    // Although only the Network process needs
+    // kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy, differentiating utility
+    // process sub-types is non-trivial. ChromeContentBrowserClient appends this
+    // switch to all Utility processes so do the same here.
+    // Do not add other switches here.
+    command_line->CopySwitchesFrom(
+        browser_command_line, kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy,
+        std::size(kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy));
+  }
 }
 
 std::string WebEngineContentBrowserClient::GetApplicationLocale() {
diff --git a/fuchsia_web/webengine/test/web_engine_shell.cmx b/fuchsia_web/webengine/test/web_engine_shell.cmx
index a14d635..5817f99d 100644
--- a/fuchsia_web/webengine/test/web_engine_shell.cmx
+++ b/fuchsia_web/webengine/test/web_engine_shell.cmx
@@ -35,6 +35,7 @@
       "fuchsia.sys.Launcher",
       "fuchsia.sys.Loader",
       "fuchsia.sysmem.Allocator",
+      "fuchsia.tracing.perfetto.ProducerConnector",
       "fuchsia.ui.composition.Allocator",
       "fuchsia.ui.composition.Flatland",
       "fuchsia.ui.input3.Keyboard",
diff --git a/fuchsia_web/webengine/web_instance.cmx b/fuchsia_web/webengine/web_instance.cmx
index 4163a99..0f4d39f 100644
--- a/fuchsia_web/webengine/web_instance.cmx
+++ b/fuchsia_web/webengine/web_instance.cmx
@@ -34,6 +34,7 @@
       "fuchsia.process.Launcher",
       "fuchsia.settings.Display",
       "fuchsia.sysmem.Allocator",
+      "fuchsia.tracing.perfetto.ProducerConnector",
       "fuchsia.ui.composition.Allocator",
       "fuchsia.ui.composition.Flatland",
       "fuchsia.ui.input3.Keyboard",
diff --git a/fuchsia_web/webinstance_host/DEPS b/fuchsia_web/webinstance_host/DEPS
index 9c7461f..cfb5c0d4 100644
--- a/fuchsia_web/webinstance_host/DEPS
+++ b/fuchsia_web/webinstance_host/DEPS
@@ -2,7 +2,6 @@
   "+components/embedder_support",
   "+components/fuchsia_component_support",
   "+content/public/common",
-  "+fuchsia/base",
   "+fuchsia_web/webengine/features.h",
   "+fuchsia_web/webengine/switches.h",
   "+gpu/config/gpu_finch_features.h",
diff --git a/fuchsia_web/webinstance_host/web_instance_host.cc b/fuchsia_web/webinstance_host/web_instance_host.cc
index d0bc11f..255506bb 100644
--- a/fuchsia_web/webinstance_host/web_instance_host.cc
+++ b/fuchsia_web/webinstance_host/web_instance_host.cc
@@ -355,12 +355,18 @@
   // at:
   //   https://fuchsia.dev/reference/fidl/fuchsia.web#CreateContextParams.service_directory
   std::vector<std::string> services{
-      "fuchsia.buildinfo.Provider",      "fuchsia.device.NameProvider",
-      "fuchsia.fonts.Provider",          "fuchsia.hwinfo.Product",
-      "fuchsia.intl.PropertyProvider",   "fuchsia.logger.LogSink",
-      "fuchsia.memorypressure.Provider", "fuchsia.process.Launcher",
+      "fuchsia.buildinfo.Provider",
+      "fuchsia.device.NameProvider",
+      "fuchsia.fonts.Provider",
+      "fuchsia.hwinfo.Product",
+      "fuchsia.intl.PropertyProvider",
+      "fuchsia.logger.LogSink",
+      "fuchsia.memorypressure.Provider",
+      "fuchsia.process.Launcher",
       "fuchsia.settings.Display",  // Used if preferred theme is DEFAULT.
-      "fuchsia.sysmem.Allocator",        "fuchsia.ui.scenic.Scenic"};
+      "fuchsia.sysmem.Allocator",
+      "fuchsia.tracing.perfetto.ProducerConnector",
+      "fuchsia.ui.scenic.Scenic"};
 
   // TODO(crbug.com/1209031): Provide these conditionally, once corresponding
   // ContextFeatureFlags have been defined.
diff --git a/gpu/command_buffer/service/shared_image_representation_gl_ozone.cc b/gpu/command_buffer/service/shared_image_representation_gl_ozone.cc
index b6add09f..7f5f8bb4 100644
--- a/gpu/command_buffer/service/shared_image_representation_gl_ozone.cc
+++ b/gpu/command_buffer/service/shared_image_representation_gl_ozone.cc
@@ -95,8 +95,8 @@
 
   std::unique_ptr<ui::NativePixmapGLBinding> np_gl_binding =
       gl_ozone->ImportNativePixmap(std::move(pixmap), buffer_format, plane,
-                                   backing->size(), target,
-                                   gl_texture_service_id);
+                                   backing->size(), backing->color_space(),
+                                   target, gl_texture_service_id);
   if (!np_gl_binding) {
     DLOG(ERROR) << "Failed to create NativePixmapGLBinding.";
     api->glDeleteTexturesFn(1, &gl_texture_service_id);
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index 32156819..c51c171 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -4045,6 +4045,27 @@
       "features": [
         "add_fence_for_same_gl_context"
       ]
+    },
+    {
+      "id": 397,
+      "description": "VPx decoding crashes due to a buggy driver / chipset combo.",
+      "cr_bugs": [1333299],
+      "os": {
+        "type": "win",
+        "version": {
+          "op": ">=",
+          "value": "10"
+        }
+      },
+      "vendor_id": "0x8086",
+      "device_id": [ "0x591B" ],
+      "driver_version": {
+        "op": "=",
+        "value": "26.20.100.6998"
+      },
+      "features": [
+        "disable_accelerated_vp9_decode"
+      ]
     }
   ]
 }
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json
index 73b6e99..382c5ea 100644
--- a/gpu/config/software_rendering_list.json
+++ b/gpu/config/software_rendering_list.json
@@ -40,41 +40,6 @@
       ]
     },
     {
-      "id": 5,
-      "description": "ATI/AMD cards with older drivers in Linux are crash-prone",
-      "cr_bugs": [71381, 76428, 73910, 101225, 136240, 357314, 719213],
-      "os": {
-        "type": "linux"
-      },
-      "vendor_id": "0x1002",
-      "exceptions": [
-        {
-          "driver_vendor": ".*AMD.*",
-          "driver_version": {
-            "op": ">=",
-            "style": "lexical",
-            "value": "8.98"
-          }
-        },
-        {
-          "driver_vendor": "Mesa",
-          "driver_version": {
-            "op": ">=",
-            "value": "10.0.4"
-          }
-        },
-        {
-          "driver_vendor": ".*ANGLE.*"
-        },
-        {
-          "driver_vendor": ".*Brahma.*"
-        }
-      ],
-      "features": [
-        "all"
-      ]
-    },
-    {
       "id": 8,
       "description": "NVIDIA GeForce FX Go5200 is assumed to be buggy",
       "cr_bugs": [72938],
diff --git a/gpu/ipc/service/gpu_channel_manager_unittest.cc b/gpu/ipc/service/gpu_channel_manager_unittest.cc
index 28df5d5a..9b02192 100644
--- a/gpu/ipc/service/gpu_channel_manager_unittest.cc
+++ b/gpu/ipc/service/gpu_channel_manager_unittest.cc
@@ -66,8 +66,7 @@
 
       g_trace_event = std::make_unique<base::trace_event::TraceEvent>(
           trace_event.thread_id(), trace_event.timestamp(),
-          trace_event.thread_timestamp(),
-          trace_event.thread_instruction_count(), trace_event.phase(),
+          trace_event.thread_timestamp(), trace_event.phase(),
           trace_event.category_group_enabled(), trace_event.name(),
           trace_event.scope(), trace_event.id(), trace_event.bind_id(),
           args.get(), trace_event.flags());
diff --git a/gpu/ipc/service/image_transport_surface_mac.mm b/gpu/ipc/service/image_transport_surface_mac.mm
index 959677e..1071b3b 100644
--- a/gpu/ipc/service/image_transport_surface_mac.mm
+++ b/gpu/ipc/service/image_transport_surface_mac.mm
@@ -23,7 +23,6 @@
   switch (gl::GetGLImplementation()) {
     case gl::kGLImplementationDesktopGL:
     case gl::kGLImplementationDesktopGLCoreProfile:
-    case gl::kGLImplementationAppleGL:
       return base::WrapRefCounted<gl::GLSurface>(
           new ImageTransportSurfaceOverlayMac(delegate));
 #if defined(USE_EGL)
diff --git a/gpu/webgpu/.gitignore b/gpu/webgpu/.gitignore
new file mode 100644
index 0000000..c80fb99
--- /dev/null
+++ b/gpu/webgpu/.gitignore
@@ -0,0 +1,2 @@
+### Dawn version file (generated as part of DEPS hook)
+DAWN_VERSION
\ No newline at end of file
diff --git a/headless/lib/browser/headless_content_browser_client.cc b/headless/lib/browser/headless_content_browser_client.cc
index 024dc8e..e2b2cd34 100644
--- a/headless/lib/browser/headless_content_browser_client.cc
+++ b/headless/lib/browser/headless_content_browser_client.cc
@@ -265,14 +265,6 @@
                                             headless_browser_context_impl,
                                             process_type, child_process_id);
   }
-
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-  // Processes may only query perf_event_open with the BPF sandbox disabled.
-  if (old_command_line.HasSwitch(::switches::kEnableThreadInstructionCount) &&
-      old_command_line.HasSwitch(sandbox::policy::switches::kNoSandbox)) {
-    command_line->AppendSwitch(::switches::kEnableThreadInstructionCount);
-  }
-#endif
 }
 
 std::string HeadlessContentBrowserClient::GetApplicationLocale() {
diff --git a/headless/lib/browser/policy/headless_browser_policy_connector.cc b/headless/lib/browser/policy/headless_browser_policy_connector.cc
index ed3e652..a8dc184a 100644
--- a/headless/lib/browser/policy/headless_browser_policy_connector.cc
+++ b/headless/lib/browser/policy/headless_browser_policy_connector.cc
@@ -123,7 +123,7 @@
       base::ThreadPool::CreateSequencedTaskRunner(
           {base::MayBlock(), base::TaskPriority::BEST_EFFORT}),
       policy::PlatformManagementService::GetInstance(),
-      kRegistryChromePolicyKey, IsCommandLineSwitchSupported()));
+      kRegistryChromePolicyKey));
   return std::make_unique<AsyncPolicyProvider>(GetSchemaRegistry(),
                                                std::move(loader));
 #elif BUILDFLAG(IS_MAC)
diff --git a/infra/archive_config/README.md b/infra/archive_config/README.md
new file mode 100644
index 0000000..0b0048c
--- /dev/null
+++ b/infra/archive_config/README.md
@@ -0,0 +1,9 @@
+This directory contains the configurations of which binaries get archived on
+Chromium builders, and controls how and where they're stored. This applies
+mostly to the `*-archive-*` builders on this
+[console](https://ci.chromium.org/p/chromium/g/chromium/console).
+
+Each JSON file here corresponds to the archive configuration for a single
+builder. See the
+[properties.proto](https://source.chromium.org/chromium/chromium/tools/build/+/main:recipes/recipe_modules/archive/properties.proto;drc=cca630e6c409dcdcc18567b94fcdc782b337e0ab;l=270)
+definition of the archive recipe module for the schema of these files.
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient staging/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient staging/properties.json
new file mode 100644
index 0000000..306ee40
--- /dev/null
+++ b/infra/config/generated/builders/reclient/Mac Builder reclient staging/properties.json
@@ -0,0 +1,60 @@
+{
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "reclient",
+              "builder": "Mac Builder reclient staging",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "build_gs_bucket": "chromium-fyi-archive",
+              "builder_group": "chromium.reclient.fyi",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb",
+                  "goma_use_local"
+                ],
+                "build_config": "Release",
+                "config": "chromium",
+                "target_bits": 64,
+                "target_platform": "mac"
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "use_clang_coverage",
+                  "enable_reclient",
+                  "reclient_staging"
+                ],
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "reclient",
+          "builder": "Mac Builder reclient staging",
+          "project": "chromium"
+        }
+      ]
+    }
+  },
+  "$build/reclient": {
+    "instance": "rbe-chromium-trusted",
+    "metrics_project": "chromium-reclient-metrics"
+  },
+  "$recipe_engine/resultdb/test_presentation": {
+    "column_keys": [],
+    "grouping_keys": [
+      "status",
+      "v.test_suite"
+    ]
+  },
+  "builder_group": "chromium.reclient.fyi",
+  "recipe": "chromium"
+}
\ No newline at end of file
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json
new file mode 100644
index 0000000..5f60cef
--- /dev/null
+++ b/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json
@@ -0,0 +1,60 @@
+{
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "reclient",
+              "builder": "Mac Builder reclient test",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "build_gs_bucket": "chromium-fyi-archive",
+              "builder_group": "chromium.reclient.fyi",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb",
+                  "goma_use_local"
+                ],
+                "build_config": "Release",
+                "config": "chromium",
+                "target_bits": 64,
+                "target_platform": "mac"
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "use_clang_coverage",
+                  "enable_reclient",
+                  "reclient_test"
+                ],
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "reclient",
+          "builder": "Mac Builder reclient test",
+          "project": "chromium"
+        }
+      ]
+    }
+  },
+  "$build/reclient": {
+    "instance": "rbe-chromium-trusted-test",
+    "metrics_project": "chromium-reclient-metrics"
+  },
+  "$recipe_engine/resultdb/test_presentation": {
+    "column_keys": [],
+    "grouping_keys": [
+      "status",
+      "v.test_suite"
+    ]
+  },
+  "builder_group": "chromium.reclient.fyi",
+  "recipe": "chromium"
+}
\ No newline at end of file
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 247eeec..9a94b9a 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -46129,6 +46129,162 @@
       }
     }
     builders {
+      name: "Mac Builder reclient staging"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builderless:1"
+      dimensions: "cpu:x86-64"
+      dimensions: "free_space:standard"
+      dimensions: "os:Mac-11|Mac-12"
+      dimensions: "pool:luci.chromium.ci"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/reclient/Mac Builder reclient staging/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "chromium.reclient.fyi",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium"'
+        '}'
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://[^/]*blink_web_tests/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
+      name: "Mac Builder reclient test"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builderless:1"
+      dimensions: "cpu:x86-64"
+      dimensions: "free_space:standard"
+      dimensions: "os:Mac-11|Mac-12"
+      dimensions: "pool:luci.chromium.ci"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "chromium.reclient.fyi",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium"'
+        '}'
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://[^/]*blink_web_tests/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "Simple Chrome Builder reclient staging"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index 6e2aa1a..56f9859 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -11985,6 +11985,16 @@
     short_name: "rcs"
   }
   builders {
+    name: "buildbucket/luci.chromium.reclient/Mac Builder reclient staging"
+    category: "rbe|mac"
+    short_name: "rcs"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.reclient/Mac Builder reclient test"
+    category: "rbe|mac"
+    short_name: "rcs"
+  }
+  builders {
     name: "buildbucket/luci.chromium.reclient/Win x64 Builder reclient staging"
     category: "rbe|win"
     short_name: "rcs"
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg
index 9c6f959..19ca09b 100644
--- a/infra/config/generated/luci/luci-scheduler.cfg
+++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -2215,6 +2215,26 @@
   }
 }
 job {
+  id: "Mac Builder reclient staging"
+  realm: "reclient"
+  acl_sets: "reclient"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "reclient"
+    builder: "Mac Builder reclient staging"
+  }
+}
+job {
+  id: "Mac Builder reclient test"
+  realm: "reclient"
+  acl_sets: "reclient"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "reclient"
+    builder: "Mac Builder reclient test"
+  }
+}
+job {
   id: "Mac Debug (Intel)"
   realm: "ci"
   acls {
@@ -7278,6 +7298,8 @@
   triggers: "mac-archive-rel-goma-rbe-latest"
   triggers: "Linux Builder reclient staging"
   triggers: "Linux Builder reclient test"
+  triggers: "Mac Builder reclient staging"
+  triggers: "Mac Builder reclient test"
   triggers: "Simple Chrome Builder reclient staging"
   triggers: "Simple Chrome Builder reclient test"
   triggers: "Win x64 Builder reclient staging"
diff --git a/infra/config/subprojects/reclient/reclient.star b/infra/config/subprojects/reclient/reclient.star
index 53dfacf..23a1379 100644
--- a/infra/config/subprojects/reclient/reclient.star
+++ b/infra/config/subprojects/reclient/reclient.star
@@ -118,6 +118,50 @@
 )
 
 fyi_reclient_staging_builder(
+    name = "Mac Builder reclient staging",
+    builder_spec = builder_config.copy_from(
+        "ci/Mac Builder",
+        lambda spec: structs.evolve(
+            spec,
+            gclient_config = structs.extend(
+                spec.gclient_config,
+                apply_configs = [
+                    "enable_reclient",
+                    "reclient_staging",
+                ],
+            ),
+            build_gs_bucket = "chromium-fyi-archive",
+        ),
+    ),
+    console_view_category = "mac",
+    os = os.MAC_DEFAULT,
+    builderless = True,
+    cores = None,
+)
+
+fyi_reclient_test_builder(
+    name = "Mac Builder reclient test",
+    builder_spec = builder_config.copy_from(
+        "ci/Mac Builder",
+        lambda spec: structs.evolve(
+            spec,
+            gclient_config = structs.extend(
+                spec.gclient_config,
+                apply_configs = [
+                    "enable_reclient",
+                    "reclient_test",
+                ],
+            ),
+            build_gs_bucket = "chromium-fyi-archive",
+        ),
+    ),
+    console_view_category = "mac",
+    os = os.MAC_DEFAULT,
+    builderless = True,
+    cores = None,
+)
+
+fyi_reclient_staging_builder(
     name = "Win x64 Builder reclient staging",
     builder_spec = builder_config.copy_from(
         "ci/Win x64 Builder",
diff --git a/infra/orchestrator/BUILD.gn b/infra/orchestrator/BUILD.gn
index cafc960..b0db66f 100644
--- a/infra/orchestrator/BUILD.gn
+++ b/infra/orchestrator/BUILD.gn
@@ -18,8 +18,15 @@
     ":standard_isolated_script_merge_py",
   ]
 
-  # Test specs the Orchestrator needs to trigger swarming tests
-  data = [ "//testing/buildbot/*.json" ]
+  data = [
+    # Various merge/collect scripts will likely need a venv specified in
+    # the root vpython spec files.
+    "//.vpython",
+    "//.vpython3",
+
+    # Test specs the Orchestrator needs to trigger swarming tests
+    "//testing/buildbot/*.json",
+  ]
 
   # Orchestrator will run this script to curl for the coverage tool, which
   # merges and outputs coverage data
@@ -28,12 +35,10 @@
   }
 
   if (use_jacoco_coverage) {
-    data += [
-      "//third_party/jacoco/lib/jacococli.jar",
-    ]
+    data += [ "//third_party/jacoco/lib/jacococli.jar" ]
     data_deps += [
-      "//third_party/jdk:java_data",
       "//build/android:test_result_presentations_py",
+      "//third_party/jdk:java_data",
     ]
   }
   write_runtime_deps = "$root_out_dir/orchestrator_all.runtime_deps"
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 6355ebdd..4df19e6 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -1141,15 +1141,20 @@
 }
 
 - (void)scheduleFaviconsCleanup {
+#if BUILDFLAG(IOS_CREDENTIAL_PROVIDER_ENABLED)
+  __weak MainController* weakSelf = self;
   [[DeferredInitializationRunner sharedInstance]
       enqueueBlockNamed:kFaviconsCleanup
                   block:^{
-#if BUILDFLAG(IOS_CREDENTIAL_PROVIDER_ENABLED)
+                    MainController* strongSelf = weakSelf;
+                    if (!strongSelf || !strongSelf.currentBrowserState) {
+                      return;
+                    }
                     UpdateFaviconsStorage(
                         IOSChromeFaviconLoaderFactory::GetForBrowserState(
-                            self.currentBrowserState));
-#endif
+                            strongSelf.currentBrowserState));
                   }];
+#endif
 }
 
 - (void)expireFirstUserActionRecorder {
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 691cf2d..cf4ba67 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -720,6 +720,9 @@
       <message name="IDS_IOS_CONTENT_SUGGESTIONS_SHOW" desc="The label in the header to show/uncollapse Content Suggestions [Length: 10em]">
         Show
       </message>
+      <message name="IDS_IOS_CONTENT_SUGGESTIONS_TRENDING_QUERIES_MODULE_TITLE" desc="The Trending Queries module title on the new tab page [Length: 10em]">
+        Trending Searches
+      </message>
       <message name="IDS_IOS_CONTENT_SETTINGS_TITLE" desc="Title for content settings dialog [Length: 29em] [iOS only]">
         Content Settings
       </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_SUGGESTIONS_TRENDING_QUERIES_MODULE_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_SUGGESTIONS_TRENDING_QUERIES_MODULE_TITLE.png.sha1
new file mode 100644
index 0000000..82f53e790
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_SUGGESTIONS_TRENDING_QUERIES_MODULE_TITLE.png.sha1
@@ -0,0 +1 @@
+caf1b0a893a1efaa3e541ad34210ae763cca5f50
\ No newline at end of file
diff --git a/ios/chrome/browser/download/BUILD.gn b/ios/chrome/browser/download/BUILD.gn
index 48de5de3..c773af6 100644
--- a/ios/chrome/browser/download/BUILD.gn
+++ b/ios/chrome/browser/download/BUILD.gn
@@ -66,6 +66,8 @@
 
 source_set("mime_types") {
   sources = [
+    "download_mimetype_util.cc",
+    "download_mimetype_util.h",
     "mime_type_util.cc",
     "mime_type_util.h",
   ]
diff --git a/ios/chrome/browser/download/browser_download_service.h b/ios/chrome/browser/download/browser_download_service.h
index 49f401c..1e1861f 100644
--- a/ios/chrome/browser/download/browser_download_service.h
+++ b/ios/chrome/browser/download/browser_download_service.h
@@ -16,58 +16,6 @@
 class WebState;
 }  // namespace web
 
-// Enum for the Download.IOSDownloadMimeType UMA histogram to report the
-// MIME type of the download task.
-// Note: This enum is used to back an UMA histogram, and should be treated as
-// append-only.
-enum class DownloadMimeTypeResult {
-  // MIME type other than those listed below.
-  Other = 0,
-  // application/vnd.apple.pkpass MIME type.
-  PkPass = 1,
-  // application/x-apple-aspen-config MIME type.
-  iOSMobileConfig = 2,
-  // application/zip MIME type.
-  ZipArchive = 3,
-  // application/x-msdownload MIME type (.exe file).
-  MicrosoftApplication = 4,
-  // application/vnd.android.package-archive MIME type (.apk file).
-  AndroidPackageArchive = 5,
-  // text/vcard MIME type.
-  VirtualContactFile = 6,
-  // text/calendar MIME type.
-  Calendar = 7,
-  // model/usd MIME type.
-  LegacyUniversalSceneDescription = 8,
-  // application/x-apple-diskimage MIME type.
-  AppleDiskImage = 9,
-  // application/vnd.apple.installer+xml MIME type.
-  AppleInstallerPackage = 10,
-  // application/x-7z-compressed MIME type.
-  SevenZipArchive = 11,
-  // application/x-rar-compressed MIME type.
-  RARArchive = 12,
-  // application/x-tar MIME type.
-  TarArchive = 13,
-  // application/x-shockwave-flash MIME type.
-  AdobeFlash = 14,
-  // application/vnd.amazon.ebook MIME type.
-  AmazonKindleBook = 15,
-  // application/octet-stream MIME type.
-  BinaryData = 16,
-  // application/x-bittorrent MIME type.
-  BitTorrent = 17,
-  // application/java-archive MIME type.
-  JavaArchive = 18,
-  // model/vnd.pixar.usd MIME type.
-  LegacyPixarUniversalSceneDescription = 19,
-  // model/vnd.usdz+zip MIME type.
-  UniversalSceneDescription = 20,
-  // text/vcard MIME type.
-  Vcard = 21,
-  kMaxValue = Vcard,
-};
-
 // Keyed Service which acts as web::DownloadController delegate and routes
 // download tasks to the appropriate TabHelper for download.
 class BrowserDownloadService : public KeyedService,
diff --git a/ios/chrome/browser/download/browser_download_service.mm b/ios/chrome/browser/download/browser_download_service.mm
index 44a435f..296440e 100644
--- a/ios/chrome/browser/download/browser_download_service.mm
+++ b/ios/chrome/browser/download/browser_download_service.mm
@@ -10,6 +10,7 @@
 #import "ios/chrome/browser/download/ar_quick_look_tab_helper.h"
 #include "ios/chrome/browser/download/download_manager_metric_names.h"
 #import "ios/chrome/browser/download/download_manager_tab_helper.h"
+#import "ios/chrome/browser/download/download_mimetype_util.h"
 #include "ios/chrome/browser/download/mime_type_util.h"
 #import "ios/chrome/browser/download/pass_kit_tab_helper.h"
 #import "ios/chrome/browser/download/safari_download_tab_helper.h"
@@ -24,76 +25,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-// Returns DownloadMimeTypeResult for the given MIME type.
-DownloadMimeTypeResult GetUmaResult(const std::string& mime_type) {
-  if (mime_type == kPkPassMimeType)
-    return DownloadMimeTypeResult::PkPass;
-
-  if (mime_type == kZipArchiveMimeType)
-    return DownloadMimeTypeResult::ZipArchive;
-
-  if (mime_type == kMobileConfigurationType)
-    return DownloadMimeTypeResult::iOSMobileConfig;
-
-  if (mime_type == kMicrosoftApplicationMimeType)
-    return DownloadMimeTypeResult::MicrosoftApplication;
-
-  if (mime_type == kAndroidPackageArchiveMimeType)
-    return DownloadMimeTypeResult::AndroidPackageArchive;
-
-  if (mime_type == kVcardMimeType)
-    return DownloadMimeTypeResult::VirtualContactFile;
-
-  if (mime_type == kCalendarMimeType)
-    return DownloadMimeTypeResult::Calendar;
-
-  if (mime_type == kLegacyUsdzMimeType)
-    return DownloadMimeTypeResult::LegacyUniversalSceneDescription;
-
-  if (mime_type == kAppleDiskImageMimeType)
-    return DownloadMimeTypeResult::AppleDiskImage;
-
-  if (mime_type == kAppleInstallerPackageMimeType)
-    return DownloadMimeTypeResult::AppleInstallerPackage;
-
-  if (mime_type == kSevenZipArchiveMimeType)
-    return DownloadMimeTypeResult::SevenZipArchive;
-
-  if (mime_type == kRARArchiveMimeType)
-    return DownloadMimeTypeResult::RARArchive;
-
-  if (mime_type == kTarArchiveMimeType)
-    return DownloadMimeTypeResult::TarArchive;
-
-  if (mime_type == kAdobeFlashMimeType)
-    return DownloadMimeTypeResult::AdobeFlash;
-
-  if (mime_type == kAmazonKindleBookMimeType)
-    return DownloadMimeTypeResult::AmazonKindleBook;
-
-  if (mime_type == kBinaryDataMimeType)
-    return DownloadMimeTypeResult::BinaryData;
-
-  if (mime_type == kBitTorrentMimeType)
-    return DownloadMimeTypeResult::BitTorrent;
-
-  if (mime_type == kJavaArchiveMimeType)
-    return DownloadMimeTypeResult::JavaArchive;
-
-  if (mime_type == kVcardMimeType)
-    return DownloadMimeTypeResult::Vcard;
-
-  if (mime_type == kLegacyPixarUsdzMimeType)
-    return DownloadMimeTypeResult::LegacyPixarUniversalSceneDescription;
-
-  if (mime_type == kUsdzMimeType)
-    return DownloadMimeTypeResult::UniversalSceneDescription;
-
-  return DownloadMimeTypeResult::Other;
-}
-}  // namespace
-
 BrowserDownloadService::BrowserDownloadService(
     web::DownloadController* download_controller)
     : download_controller_(download_controller) {
diff --git a/ios/chrome/browser/download/browser_download_service_unittest.mm b/ios/chrome/browser/download/browser_download_service_unittest.mm
index e290cf8f..8969392 100644
--- a/ios/chrome/browser/download/browser_download_service_unittest.mm
+++ b/ios/chrome/browser/download/browser_download_service_unittest.mm
@@ -13,6 +13,7 @@
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/download/ar_quick_look_tab_helper.h"
 #import "ios/chrome/browser/download/download_manager_tab_helper.h"
+#import "ios/chrome/browser/download/download_mimetype_util.h"
 #include "ios/chrome/browser/download/mime_type_util.h"
 #import "ios/chrome/browser/download/pass_kit_tab_helper.h"
 #import "ios/chrome/browser/download/vcard_tab_helper.h"
@@ -219,8 +220,8 @@
 // Type.
 TEST_F(BrowserDownloadServiceTest, PdfMimeType) {
   ASSERT_TRUE(download_controller()->GetDelegate());
-  auto task =
-      std::make_unique<web::FakeDownloadTask>(GURL(kUrl), "application/pdf");
+  auto task = std::make_unique<web::FakeDownloadTask>(
+      GURL(kUrl), kAdobePortableDocumentFormatMimeType);
   web::DownloadTask* task_ptr = task.get();
   download_controller()->GetDelegate()->OnDownloadCreated(
       download_controller(), &web_state_, std::move(task));
@@ -229,7 +230,8 @@
   EXPECT_EQ(task_ptr, download_manager_tab_helper()->tasks()[0].get());
   histogram_tester_.ExpectUniqueSample(
       "Download.IOSDownloadMimeType",
-      static_cast<base::HistogramBase::Sample>(DownloadMimeTypeResult::Other),
+      static_cast<base::HistogramBase::Sample>(
+          DownloadMimeTypeResult::AdobePortableDocumentFormat),
       1);
 }
 
diff --git a/ios/chrome/browser/download/download_mimetype_util.cc b/ios/chrome/browser/download/download_mimetype_util.cc
new file mode 100644
index 0000000..b6b5fcb3
--- /dev/null
+++ b/ios/chrome/browser/download/download_mimetype_util.cc
@@ -0,0 +1,270 @@
+// 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 "ios/chrome/browser/download/download_mimetype_util.h"
+#include "ios/chrome/browser/download/mime_type_util.h"
+
+DownloadMimeTypeResult GetUmaResult(const std::string& mime_type) {
+  if (mime_type == kPkPassMimeType)
+    return DownloadMimeTypeResult::PkPass;
+
+  if (mime_type == kZipArchiveMimeType)
+    return DownloadMimeTypeResult::ZipArchive;
+
+  if (mime_type == kMobileConfigurationType)
+    return DownloadMimeTypeResult::iOSMobileConfig;
+
+  if (mime_type == kMicrosoftApplicationMimeType)
+    return DownloadMimeTypeResult::MicrosoftApplication;
+
+  if (mime_type == kAndroidPackageArchiveMimeType)
+    return DownloadMimeTypeResult::AndroidPackageArchive;
+
+  if (mime_type == kVcardMimeType)
+    return DownloadMimeTypeResult::VirtualContactFile;
+
+  if (mime_type == kCalendarMimeType)
+    return DownloadMimeTypeResult::Calendar;
+
+  if (mime_type == kLegacyUsdzMimeType)
+    return DownloadMimeTypeResult::LegacyUniversalSceneDescription;
+
+  if (mime_type == kAppleDiskImageMimeType)
+    return DownloadMimeTypeResult::AppleDiskImage;
+
+  if (mime_type == kAppleInstallerPackageMimeType)
+    return DownloadMimeTypeResult::AppleInstallerPackage;
+
+  if (mime_type == kSevenZipArchiveMimeType)
+    return DownloadMimeTypeResult::SevenZipArchive;
+
+  if (mime_type == kRARArchiveMimeType)
+    return DownloadMimeTypeResult::RARArchive;
+
+  if (mime_type == kTarArchiveMimeType)
+    return DownloadMimeTypeResult::TarArchive;
+
+  if (mime_type == kAdobeFlashMimeType)
+    return DownloadMimeTypeResult::AdobeFlash;
+
+  if (mime_type == kAmazonKindleBookMimeType)
+    return DownloadMimeTypeResult::AmazonKindleBook;
+
+  if (mime_type == kBinaryDataMimeType)
+    return DownloadMimeTypeResult::BinaryData;
+
+  if (mime_type == kBitTorrentMimeType)
+    return DownloadMimeTypeResult::BitTorrent;
+
+  if (mime_type == kJavaArchiveMimeType)
+    return DownloadMimeTypeResult::JavaArchive;
+
+  if (mime_type == kVcardMimeType)
+    return DownloadMimeTypeResult::Vcard;
+
+  if (mime_type == kLegacyPixarUsdzMimeType)
+    return DownloadMimeTypeResult::LegacyPixarUniversalSceneDescription;
+
+  if (mime_type == kUsdzMimeType)
+    return DownloadMimeTypeResult::UniversalSceneDescription;
+
+  if (mime_type == kAACAudioMimeType)
+    return DownloadMimeTypeResult::AACAudio;
+
+  if (mime_type == kAbiWordDocumentMimeType)
+    return DownloadMimeTypeResult::AbiWordDocument;
+
+  if (mime_type == kArchiveDocumentMimeType)
+    return DownloadMimeTypeResult::ArchiveDocument;
+
+  if (mime_type == kAVIFImageMimeType)
+    return DownloadMimeTypeResult::AVIFImage;
+
+  if (mime_type == kAVIVideoMimeType)
+    return DownloadMimeTypeResult::AVIVideo;
+
+  if (mime_type == kGenericBitmapMimeType)
+    return DownloadMimeTypeResult::GenericBitmap;
+
+  if (mime_type == kMicrosoftBitmapMimeType)
+    return DownloadMimeTypeResult::MicrosoftBitmap;
+
+  if (mime_type == kBZip2ArchiveMimeType)
+    return DownloadMimeTypeResult::BZip2Archive;
+
+  if (mime_type == kCDAudioMimeType)
+    return DownloadMimeTypeResult::CDAudio;
+
+  if (mime_type == kCShellScriptMimeType)
+    return DownloadMimeTypeResult::CShellScript;
+
+  if (mime_type == kCascadingStyleSheetMimeType)
+    return DownloadMimeTypeResult::CascadingStyleSheet;
+
+  if (mime_type == kCommaSeparatedValuesMimeType)
+    return DownloadMimeTypeResult::CommaSeparatedValues;
+
+  if (mime_type == kMicrosoftWordMimeType)
+    return DownloadMimeTypeResult::MicrosoftWord;
+
+  if (mime_type == kMicrosoftWordXMLMimeType)
+    return DownloadMimeTypeResult::MicrosoftWordXML;
+
+  if (mime_type == kMSEmbeddedOpenTypefontMimeType)
+    return DownloadMimeTypeResult::MSEmbeddedOpenTypefont;
+
+  if (mime_type == kElectronicPublicationMimeType)
+    return DownloadMimeTypeResult::ElectronicPublication;
+
+  if (mime_type == kGZipCompressedArchiveMimeType)
+    return DownloadMimeTypeResult::GZipCompressedArchive;
+
+  if (mime_type == kGraphicsInterchangeFormatMimeType)
+    return DownloadMimeTypeResult::GraphicsInterchangeFormat;
+
+  if (mime_type == kHyperTextMarkupLanguageMimeType)
+    return DownloadMimeTypeResult::HyperTextMarkupLanguage;
+
+  if (mime_type == kIconFormatMimeType)
+    return DownloadMimeTypeResult::IconFormat;
+
+  if (mime_type == kJPEGImageMimeType)
+    return DownloadMimeTypeResult::JPEGImage;
+  if (mime_type == kJavaScriptMimeType)
+    return DownloadMimeTypeResult::JavaScript;
+
+  if (mime_type == kJSONFormatMimeType)
+    return DownloadMimeTypeResult::JSONFormat;
+
+  if (mime_type == kJSONLDFormatMimeType)
+    return DownloadMimeTypeResult::JSONLDFormat;
+
+  if (mime_type == kMusicalInstrumentDigitalInterfaceMimeType)
+    return DownloadMimeTypeResult::MusicalInstrumentDigitalInterface;
+
+  if (mime_type == kXMusicalInstrumentDigitalInterfaceMimeType)
+    return DownloadMimeTypeResult::XMusicalInstrumentDigitalInterface;
+
+  if (mime_type == kMP3AudioMimeType)
+    return DownloadMimeTypeResult::MP3Audio;
+
+  if (mime_type == kMP4VideoMimeType)
+    return DownloadMimeTypeResult::MP4Video;
+
+  if (mime_type == kMPEGVideoMimeType)
+    return DownloadMimeTypeResult::MPEGVideo;
+
+  if (mime_type == kOpenDocumentPresentationDocumentMimeType)
+    return DownloadMimeTypeResult::OpenDocumentPresentationDocument;
+
+  if (mime_type == kOpenDocumentSpreadsheetDocumentMimeType)
+    return DownloadMimeTypeResult::OpenDocumentSpreadsheetDocument;
+
+  if (mime_type == kOpenDocumentTextDocumentMimeType)
+    return DownloadMimeTypeResult::OpenDocumentTextDocument;
+
+  if (mime_type == kOGGAudioMimeType)
+    return DownloadMimeTypeResult::OGGAudio;
+
+  if (mime_type == kOGGVideoMimeType)
+    return DownloadMimeTypeResult::OGGVideo;
+
+  if (mime_type == kOGGMimeType)
+    return DownloadMimeTypeResult::OGG;
+
+  if (mime_type == kOpusAudioMimeType)
+    return DownloadMimeTypeResult::OpusAudio;
+
+  if (mime_type == kOpenTypeFontMimeType)
+    return DownloadMimeTypeResult::OpenTypeFont;
+
+  if (mime_type == kPortableNetworkGraphicMimeType)
+    return DownloadMimeTypeResult::PortableNetworkGraphic;
+
+  if (mime_type == kAdobePortableDocumentFormatMimeType)
+    return DownloadMimeTypeResult::AdobePortableDocumentFormat;
+
+  if (mime_type == kHypertextPreprocessorMimeType)
+    return DownloadMimeTypeResult::HypertextPreprocessor;
+
+  if (mime_type == kMicrosoftPowerPointMimeType)
+    return DownloadMimeTypeResult::MicrosoftPowerPoint;
+
+  if (mime_type == kMicrosoftPowerPointOpenXMLMimeType)
+    return DownloadMimeTypeResult::MicrosoftPowerPointOpenXML;
+
+  if (mime_type == kRARArchiveVNDMimeType)
+    return DownloadMimeTypeResult::RARArchiveVND;
+
+  if (mime_type == kRichTextFormatMimeType)
+    return DownloadMimeTypeResult::RichTextFormat;
+
+  if (mime_type == kBourneShellScriptMimeType)
+    return DownloadMimeTypeResult::BourneShellScript;
+
+  if (mime_type == kScalableVectorGraphicMimeType)
+    return DownloadMimeTypeResult::ScalableVectorGraphic;
+
+  if (mime_type == kTaggedImageFileFormatMimeType)
+    return DownloadMimeTypeResult::TaggedImageFileFormat;
+
+  if (mime_type == kMPEGTransportStreamMimeType)
+    return DownloadMimeTypeResult::MPEGTransportStream;
+
+  if (mime_type == kTrueTypeFontMimeType)
+    return DownloadMimeTypeResult::TrueTypeFont;
+
+  if (mime_type == kTextMimeType)
+    return DownloadMimeTypeResult::Text;
+
+  if (mime_type == kMicrosoftVisioMimeType)
+    return DownloadMimeTypeResult::MicrosoftVisio;
+
+  if (mime_type == kWaveformAudioFormatMimeType)
+    return DownloadMimeTypeResult::WaveformAudioFormat;
+
+  if (mime_type == kWEBMAudioMimeType)
+    return DownloadMimeTypeResult::WEBMAudio;
+
+  if (mime_type == kWEBMVideoMimeType)
+    return DownloadMimeTypeResult::WEBMVideo;
+
+  if (mime_type == kWEBPImageMimeType)
+    return DownloadMimeTypeResult::WEBPImage;
+
+  if (mime_type == kWebOpenFontMimeType)
+    return DownloadMimeTypeResult::WebOpenFont;
+
+  if (mime_type == kWebOpenFont2MimeType)
+    return DownloadMimeTypeResult::WebOpenFont2;
+
+  if (mime_type == kXHTMLMimeType)
+    return DownloadMimeTypeResult::XHTML;
+
+  if (mime_type == kMicrosoftExcelMimeType)
+    return DownloadMimeTypeResult::MicrosoftExcel;
+
+  if (mime_type == kMicrosoftExcelOpenXMLMimeType)
+    return DownloadMimeTypeResult::MicrosoftExcelOpenXML;
+
+  if (mime_type == kXMLMimeType)
+    return DownloadMimeTypeResult::XML;
+
+  if (mime_type == kXULMimeType)
+    return DownloadMimeTypeResult::XUL;
+
+  if (mime_type == k3GPPVideoMimeType)
+    return DownloadMimeTypeResult::k3GPPVideo;
+
+  if (mime_type == k3GPPAudioMimeType)
+    return DownloadMimeTypeResult::k3GPPAudio;
+
+  if (mime_type == k3GPP2VideoMimeType)
+    return DownloadMimeTypeResult::k3GPP2Video;
+
+  if (mime_type == k3GPP2AudioMimeType)
+    return DownloadMimeTypeResult::k3GPPAudio;
+
+  return DownloadMimeTypeResult::Other;
+}
diff --git a/ios/chrome/browser/download/download_mimetype_util.h b/ios/chrome/browser/download/download_mimetype_util.h
new file mode 100644
index 0000000..3a7eaa2
--- /dev/null
+++ b/ios/chrome/browser/download/download_mimetype_util.h
@@ -0,0 +1,131 @@
+// 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 IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MIMETYPE_UTIL_H_
+#define IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MIMETYPE_UTIL_H_
+
+#include <string>
+
+// Enum for the Download.IOSDownloadMimeType UMA histogram to report the
+// MIME type of the download task.
+// Note: This enum is used to back an UMA histogram, and should be treated as
+// append-only.
+enum class DownloadMimeTypeResult {
+  // MIME type other than those listed below.
+  Other = 0,
+  // application/vnd.apple.pkpass MIME type.
+  PkPass = 1,
+  // application/x-apple-aspen-config MIME type.
+  iOSMobileConfig = 2,
+  // application/zip MIME type.
+  ZipArchive = 3,
+  // application/x-msdownload MIME type (.exe file).
+  MicrosoftApplication = 4,
+  // application/vnd.android.package-archive MIME type (.apk file).
+  AndroidPackageArchive = 5,
+  // text/vcard MIME type.
+  VirtualContactFile = 6,
+  // text/calendar MIME type.
+  Calendar = 7,
+  // model/usd MIME type.
+  LegacyUniversalSceneDescription = 8,
+  // application/x-apple-diskimage MIME type.
+  AppleDiskImage = 9,
+  // application/vnd.apple.installer+xml MIME type.
+  AppleInstallerPackage = 10,
+  // application/x-7z-compressed MIME type.
+  SevenZipArchive = 11,
+  // application/x-rar-compressed MIME type.
+  RARArchive = 12,
+  // application/x-tar MIME type.
+  TarArchive = 13,
+  // application/x-shockwave-flash MIME type.
+  AdobeFlash = 14,
+  // application/vnd.amazon.ebook MIME type.
+  AmazonKindleBook = 15,
+  // application/octet-stream MIME type.
+  BinaryData = 16,
+  // application/x-bittorrent MIME type.
+  BitTorrent = 17,
+  // application/java-archive MIME type.
+  JavaArchive = 18,
+  // model/vnd.pixar.usd MIME type.
+  LegacyPixarUniversalSceneDescription = 19,
+  // model/vnd.usdz+zip MIME type.
+  UniversalSceneDescription = 20,
+  // text/vcard MIME type.
+  Vcard = 21,
+  AACAudio = 22,
+  AbiWordDocument = 23,
+  ArchiveDocument = 24,
+  AVIFImage = 25,
+  AVIVideo = 26,
+  GenericBitmap = 27,
+  MicrosoftBitmap = 28,
+  BZip2Archive = 29,
+  CDAudio = 30,
+  CShellScript = 31,
+  CascadingStyleSheet = 32,
+  CommaSeparatedValues = 33,
+  MicrosoftWord = 34,
+  MicrosoftWordXML = 35,
+  MSEmbeddedOpenTypefont = 36,
+  ElectronicPublication = 37,
+  GZipCompressedArchive = 38,
+  GraphicsInterchangeFormat = 39,
+  HyperTextMarkupLanguage = 40,
+  IconFormat = 41,
+  JPEGImage = 42,
+  JavaScript = 43,
+  JSONFormat = 44,
+  JSONLDFormat = 45,
+  MusicalInstrumentDigitalInterface = 46,
+  XMusicalInstrumentDigitalInterface = 47,
+  MP3Audio = 48,
+  MP4Video = 49,
+  MPEGVideo = 50,
+  OpenDocumentPresentationDocument = 51,
+  OpenDocumentSpreadsheetDocument = 52,
+  OpenDocumentTextDocument = 53,
+  OGGAudio = 54,
+  OGGVideo = 55,
+  OGG = 56,
+  OpusAudio = 57,
+  OpenTypeFont = 58,
+  PortableNetworkGraphic = 59,
+  AdobePortableDocumentFormat = 60,
+  HypertextPreprocessor = 61,
+  MicrosoftPowerPoint = 62,
+  MicrosoftPowerPointOpenXML = 63,
+  RARArchiveVND = 64,
+  RichTextFormat = 65,
+  BourneShellScript = 66,
+  ScalableVectorGraphic = 67,
+  TaggedImageFileFormat = 68,
+  MPEGTransportStream = 69,
+  TrueTypeFont = 70,
+  Text = 71,
+  MicrosoftVisio = 72,
+  WaveformAudioFormat = 73,
+  WEBMAudio = 74,
+  WEBMVideo = 75,
+  WEBPImage = 76,
+  WebOpenFont = 77,
+  WebOpenFont2 = 78,
+  XHTML = 79,
+  MicrosoftExcel = 80,
+  MicrosoftExcelOpenXML = 81,
+  XML = 82,
+  XUL = 83,
+  k3GPPVideo = 84,
+  k3GPPAudio = 85,
+  k3GPP2Video = 86,
+  k3GPP2Audio = 87,
+  kMaxValue = k3GPP2Audio,
+};
+
+// Returns DownloadMimeTypeResult for the given MIME type.
+DownloadMimeTypeResult GetUmaResult(const std::string& mime_type);
+
+#endif  // IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MIMETYPE_UTIL_H_
diff --git a/ios/chrome/browser/download/mime_type_util.cc b/ios/chrome/browser/download/mime_type_util.cc
index 6fbc3ce..f6894edb 100644
--- a/ios/chrome/browser/download/mime_type_util.cc
+++ b/ios/chrome/browser/download/mime_type_util.cc
@@ -33,79 +33,79 @@
 char kBinaryDataMimeType[] = "application/octet-stream";
 char kBitTorrentMimeType[] = "application/x-bittorrent";
 char kJavaArchiveMimeType[] = "application/java-archive";
-char kAACAudioMimetype[] = "audio/aac";
-char kAbiWordDocumentMimetype[] = "application/x-abiword";
-char kArchiveDocumentMimetype[] = "application/x-freearc";
-char kAVIFImageMimetype[] = "image/avif";
-char kAVIVideoMimetype[] = "video/x-msvideo";
-char kGenericBitmapMimetype[] = "image/bmp";
-char kMicrosoftBitmapMimetype[] = "image/x-ms-bmp";
-char kBZipArchiveMimetype[] = "application/x-bzip";
-char kBZip2ArchiveMimetype[] = "application/x-bzip2";
-char kCDAudioMimetype[] = "application/x-cdf";
-char kCShellScriptMimetype[] = "application/x-csh";
-char kCascadingStyleSheetMimetype[] = "text/css";
-char kCommaSeparatedValuesMimetype[] = "text/csv";
-char kMicrosoftWordMimetype[] = "application/msword";
-char kMicrosoftWordXMLMimetype[] =
+char kAACAudioMimeType[] = "audio/aac";
+char kAbiWordDocumentMimeType[] = "application/x-abiword";
+char kArchiveDocumentMimeType[] = "application/x-freearc";
+char kAVIFImageMimeType[] = "image/avif";
+char kAVIVideoMimeType[] = "video/x-msvideo";
+char kGenericBitmapMimeType[] = "image/bmp";
+char kMicrosoftBitmapMimeType[] = "image/x-ms-bmp";
+char kBZipArchiveMimeType[] = "application/x-bzip";
+char kBZip2ArchiveMimeType[] = "application/x-bzip2";
+char kCDAudioMimeType[] = "application/x-cdf";
+char kCShellScriptMimeType[] = "application/x-csh";
+char kCascadingStyleSheetMimeType[] = "text/css";
+char kCommaSeparatedValuesMimeType[] = "text/csv";
+char kMicrosoftWordMimeType[] = "application/msword";
+char kMicrosoftWordXMLMimeType[] =
     "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
-char kMSEmbeddedOpenTypefontMimetype[] = "application/vnd.ms-fontobject";
-char kElectronicPublicationMimetype[] = "application/epub+zip";
-char kGZipCompressedArchiveMimetype[] = "application/gzip";
-char kGraphicsInterchangeFormatMimetype[] = "image/gif";
-char kHyperTextMarkupLanguageMimetype[] = "text/html";
-char kIconFormatMimetype[] = "image/vnd.microsoft.icon";
-char kJPEGImageMimetype[] = "image/jpeg";
-char kJavaScriptMimetype[] = "text/javascript";
-char kJSONFormatMimetype[] = "application/json";
-char kJSONLDFormatMimetype[] = "application/ld+json";
-char kMusicalInstrumentDigitalInterfaceMimetype[] = "audio/midi";
-char kXMusicalInstrumentDigitalInterfaceMimetype[] = "audio/x-midi";
-char kMP3AudioMimetype[] = "audio/mpeg";
-char kMP4VideoMimetype[] = "video/mp4";
-char kMPEGVideoMimetype[] = "video/mpeg";
-char kOpenDocumentPresentationDocumentMimetype[] =
+char kMSEmbeddedOpenTypefontMimeType[] = "application/vnd.ms-fontobject";
+char kElectronicPublicationMimeType[] = "application/epub+zip";
+char kGZipCompressedArchiveMimeType[] = "application/gzip";
+char kGraphicsInterchangeFormatMimeType[] = "image/gif";
+char kHyperTextMarkupLanguageMimeType[] = "text/html";
+char kIconFormatMimeType[] = "image/vnd.microsoft.icon";
+char kJPEGImageMimeType[] = "image/jpeg";
+char kJavaScriptMimeType[] = "text/javascript";
+char kJSONFormatMimeType[] = "application/json";
+char kJSONLDFormatMimeType[] = "application/ld+json";
+char kMusicalInstrumentDigitalInterfaceMimeType[] = "audio/midi";
+char kXMusicalInstrumentDigitalInterfaceMimeType[] = "audio/x-midi";
+char kMP3AudioMimeType[] = "audio/mpeg";
+char kMP4VideoMimeType[] = "video/mp4";
+char kMPEGVideoMimeType[] = "video/mpeg";
+char kOpenDocumentPresentationDocumentMimeType[] =
     "application/vnd.oasis.opendocument.presentation";
-char kOpenDocumentSpreadsheetDocumentMimetype[] =
+char kOpenDocumentSpreadsheetDocumentMimeType[] =
     "application/vnd.oasis.opendocument.spreadsheet";
-char kOpenDocumentTextDocumentMimetype[] =
+char kOpenDocumentTextDocumentMimeType[] =
     "application/vnd.oasis.opendocument.text";
-char kOGGAudioMimetype[] = "audio/ogg";
-char kOGGVideoMimetype[] = "video/ogg";
-char kOGGMimetype[] = "application/ogg";
-char kOpusAudioMimetype[] = "audio/opus";
-char kOpenTypeFontMimetype[] = "font/otf";
-char kPortableNetworkGraphicMimetype[] = "image/png";
-char kAdobePortableDocumentFormatMimetype[] = "application/pdf";
-char kHypertextPreprocessorMimetype[] = "application/x-httpd-php";
-char kMicrosoftPowerPointMimetype[] = "application/vnd.ms-powerpoint";
-char kMicrosoftPowerPointOpenXMLMimetype[] =
+char kOGGAudioMimeType[] = "audio/ogg";
+char kOGGVideoMimeType[] = "video/ogg";
+char kOGGMimeType[] = "application/ogg";
+char kOpusAudioMimeType[] = "audio/opus";
+char kOpenTypeFontMimeType[] = "font/otf";
+char kPortableNetworkGraphicMimeType[] = "image/png";
+char kAdobePortableDocumentFormatMimeType[] = "application/pdf";
+char kHypertextPreprocessorMimeType[] = "application/x-httpd-php";
+char kMicrosoftPowerPointMimeType[] = "application/vnd.ms-powerpoint";
+char kMicrosoftPowerPointOpenXMLMimeType[] =
     "application/vnd.openxmlformats-officedocument.presentationml.presentation";
-char kRARArchiveMimetype[] = "application/vnd.rar";
-char kRichTextFormatMimetype[] = "application/rtf";
-char kBourneShellScriptMimetype[] = "application/x-sh";
-char kScalableVectorGraphicMimetype[] = "image/svg+xml";
-char kTaggedImageFileFormatMimetype[] = "image/tiff";
-char kMPEGTransportStreamMimetype[] = "video/mp2t";
-char kTrueTypeFontMimetype[] = "font/ttf";
-char kTextMimetype[] = "text/plain";
-char kMicrosoftVisioMimetype[] = "application/vnd.visio";
-char kWaveformAudioFormatMimetype[] = "audio/wav";
-char kWEBMAudioMimetype[] = "audio/webm";
-char kWEBMVideoMimetype[] = "video/webm";
-char kWEBPImageMimetype[] = "image/webp";
-char kWebOpenFontMimetype[] = "font/woff";
-char kWebOpenFont2Mimetype[] = "font/woff2";
-char kXHTMLMimetype[] = "application/xhtml+xml";
-char kMicrosoftExcelMimetype[] = "application/vnd.ms-excel";
-char kMicrosoftExcelOpenXMLMimetype[] =
+char kRARArchiveVNDMimeType[] = "application/vnd.rar";
+char kRichTextFormatMimeType[] = "application/rtf";
+char kBourneShellScriptMimeType[] = "application/x-sh";
+char kScalableVectorGraphicMimeType[] = "image/svg+xml";
+char kTaggedImageFileFormatMimeType[] = "image/tiff";
+char kMPEGTransportStreamMimeType[] = "video/mp2t";
+char kTrueTypeFontMimeType[] = "font/ttf";
+char kTextMimeType[] = "text/plain";
+char kMicrosoftVisioMimeType[] = "application/vnd.visio";
+char kWaveformAudioFormatMimeType[] = "audio/wav";
+char kWEBMAudioMimeType[] = "audio/webm";
+char kWEBMVideoMimeType[] = "video/webm";
+char kWEBPImageMimeType[] = "image/webp";
+char kWebOpenFontMimeType[] = "font/woff";
+char kWebOpenFont2MimeType[] = "font/woff2";
+char kXHTMLMimeType[] = "application/xhtml+xml";
+char kMicrosoftExcelMimeType[] = "application/vnd.ms-excel";
+char kMicrosoftExcelOpenXMLMimeType[] =
     "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
-char kXMLMimetype[] = "application/xml";
-char kXULMimetype[] = "application/vnd.mozilla.xul+xml";
-char k3GPPVideoMimetype[] = "video/3gpp";
-char k3GPPAudioMimetype[] = "audio/3gpp";
-char k3GPP2VideoMimetype[] = "video/3gpp2";
-char k3GPP2AudioMimetype[] = "audio/3gpp2";
+char kXMLMimeType[] = "application/xml";
+char kXULMimeType[] = "application/vnd.mozilla.xul+xml";
+char k3GPPVideoMimeType[] = "video/3gpp";
+char k3GPPAudioMimeType[] = "audio/3gpp";
+char k3GPP2VideoMimeType[] = "video/3gpp2";
+char k3GPP2AudioMimeType[] = "audio/3gpp2";
 
 bool IsUsdzFileFormat(const std::string& mime_type,
                       const base::FilePath& suggested_path) {
diff --git a/ios/chrome/browser/download/mime_type_util.h b/ios/chrome/browser/download/mime_type_util.h
index 60eb38c..0bcdbaa 100644
--- a/ios/chrome/browser/download/mime_type_util.h
+++ b/ios/chrome/browser/download/mime_type_util.h
@@ -70,72 +70,72 @@
 extern char kLegacyPixarUsdzMimeType[];
 
 // MIME Types that don't have specific treatment.
-extern char kAACAudioMimetype[];
-extern char kAbiWordDocumentMimetype[];
-extern char kArchiveDocumentMimetype[];
-extern char kAVIFImageMimetype[];
-extern char kAVIVideoMimetype[];
-extern char kGenericBitmapMimetype[];
-extern char kMicrosoftBitmapMimetype[];
-extern char kBZip2ArchiveMimetype[];
-extern char kCDAudioMimetype[];
-extern char kCShellScriptMimetype[];
-extern char kCascadingStyleSheetMimetype[];
-extern char kCommaSeparatedValuesMimetype[];
-extern char kMicrosoftWordMimetype[];
-extern char kMicrosoftWordXMLMimetype[];
-extern char kMSEmbeddedOpenTypefontMimetype[];
-extern char kElectronicPublicationMimetype[];
-extern char kGZipCompressedArchiveMimetype[];
-extern char kGraphicsInterchangeFormatMimetype[];
-extern char kHyperTextMarkupLanguageMimetype[];
-extern char kIconFormatMimetype[];
-extern char kJPEGImageMimetype[];
-extern char kJavaScriptMimetype[];
-extern char kJSONFormatMimetype[];
-extern char kJSONLDFormatMimetype[];
-extern char kMusicalInstrumentDigitalInterfaceMimetype[];
-extern char kXMusicalInstrumentDigitalInterfaceMimetype[];
-extern char kMP3AudioMimetype[];
-extern char kMP4VideoMimetype[];
-extern char kMPEGVideoMimetype[];
-extern char kOpenDocumentPresentationDocumentMimetype[];
-extern char kOpenDocumentSpreadsheetDocumentMimetype[];
-extern char kOpenDocumentTextDocumentMimetype[];
-extern char kOGGAudioMimetype[];
-extern char kOGGVideoMimetype[];
-extern char kOGGMimetype[];
-extern char kOpusAudioMimetype[];
-extern char kOpenTypeFontMimetype[];
-extern char kPortableNetworkGraphicMimetype[];
-extern char kAdobePortableDocumentFormatMimetype[];
-extern char kHypertextPreprocessorMimetype[];
-extern char kMicrosoftPowerPointMimetype[];
-extern char kMicrosoftPowerPointOpenXMLMimetype[];
-extern char kRARArchiveMimetype[];
-extern char kRichTextFormatMimetype[];
-extern char kBourneShellScriptMimetype[];
-extern char kScalableVectorGraphicMimetype[];
-extern char kTaggedImageFileFormatMimetype[];
-extern char kMPEGTransportStreamMimetype[];
-extern char kTrueTypeFontMimetype[];
-extern char kTextMimetype[];
-extern char kMicrosoftVisioMimetype[];
-extern char kWaveformAudioFormatMimetype[];
-extern char kWEBMAudioMimetype[];
-extern char kWEBMVideoMimetype[];
-extern char kWEBPImageMimetype[];
-extern char kWebOpenFontMimetype[];
-extern char kWebOpenFont2Mimetype[];
-extern char kXHTMLMimetype[];
-extern char kMicrosoftExcelMimetype[];
-extern char kMicrosoftExcelOpenXMLMimetype[];
-extern char kXMLMimetype[];
-extern char kXULMimetype[];
-extern char k3GPPVideoMimetype[];
-extern char k3GPPAudioMimetype[];
-extern char k3GPP2VideoMimetype[];
-extern char k3GPP2AudioMimetype[];
+extern char kAACAudioMimeType[];
+extern char kAbiWordDocumentMimeType[];
+extern char kArchiveDocumentMimeType[];
+extern char kAVIFImageMimeType[];
+extern char kAVIVideoMimeType[];
+extern char kGenericBitmapMimeType[];
+extern char kMicrosoftBitmapMimeType[];
+extern char kBZip2ArchiveMimeType[];
+extern char kCDAudioMimeType[];
+extern char kCShellScriptMimeType[];
+extern char kCascadingStyleSheetMimeType[];
+extern char kCommaSeparatedValuesMimeType[];
+extern char kMicrosoftWordMimeType[];
+extern char kMicrosoftWordXMLMimeType[];
+extern char kMSEmbeddedOpenTypefontMimeType[];
+extern char kElectronicPublicationMimeType[];
+extern char kGZipCompressedArchiveMimeType[];
+extern char kGraphicsInterchangeFormatMimeType[];
+extern char kHyperTextMarkupLanguageMimeType[];
+extern char kIconFormatMimeType[];
+extern char kJPEGImageMimeType[];
+extern char kJavaScriptMimeType[];
+extern char kJSONFormatMimeType[];
+extern char kJSONLDFormatMimeType[];
+extern char kMusicalInstrumentDigitalInterfaceMimeType[];
+extern char kXMusicalInstrumentDigitalInterfaceMimeType[];
+extern char kMP3AudioMimeType[];
+extern char kMP4VideoMimeType[];
+extern char kMPEGVideoMimeType[];
+extern char kOpenDocumentPresentationDocumentMimeType[];
+extern char kOpenDocumentSpreadsheetDocumentMimeType[];
+extern char kOpenDocumentTextDocumentMimeType[];
+extern char kOGGAudioMimeType[];
+extern char kOGGVideoMimeType[];
+extern char kOGGMimeType[];
+extern char kOpusAudioMimeType[];
+extern char kOpenTypeFontMimeType[];
+extern char kPortableNetworkGraphicMimeType[];
+extern char kAdobePortableDocumentFormatMimeType[];
+extern char kHypertextPreprocessorMimeType[];
+extern char kMicrosoftPowerPointMimeType[];
+extern char kMicrosoftPowerPointOpenXMLMimeType[];
+extern char kRARArchiveVNDMimeType[];
+extern char kRichTextFormatMimeType[];
+extern char kBourneShellScriptMimeType[];
+extern char kScalableVectorGraphicMimeType[];
+extern char kTaggedImageFileFormatMimeType[];
+extern char kMPEGTransportStreamMimeType[];
+extern char kTrueTypeFontMimeType[];
+extern char kTextMimeType[];
+extern char kMicrosoftVisioMimeType[];
+extern char kWaveformAudioFormatMimeType[];
+extern char kWEBMAudioMimeType[];
+extern char kWEBMVideoMimeType[];
+extern char kWEBPImageMimeType[];
+extern char kWebOpenFontMimeType[];
+extern char kWebOpenFont2MimeType[];
+extern char kXHTMLMimeType[];
+extern char kMicrosoftExcelMimeType[];
+extern char kMicrosoftExcelOpenXMLMimeType[];
+extern char kXMLMimeType[];
+extern char kXULMimeType[];
+extern char k3GPPVideoMimeType[];
+extern char k3GPPAudioMimeType[];
+extern char k3GPP2VideoMimeType[];
+extern char k3GPP2AudioMimeType[];
 
 // Returns whether the content-type or the file extension match those of a USDZ
 // 3D model. The file extension is checked in addition to the content-type since
diff --git a/ios/chrome/browser/https_upgrades/https_only_mode_upgrade_tab_helper.mm b/ios/chrome/browser/https_upgrades/https_only_mode_upgrade_tab_helper.mm
index 85b00a1..98191285 100644
--- a/ios/chrome/browser/https_upgrades/https_only_mode_upgrade_tab_helper.mm
+++ b/ios/chrome/browser/https_upgrades/https_only_mode_upgrade_tab_helper.mm
@@ -147,7 +147,7 @@
     params.transition_type = navigation_transition_type_;
     params.is_renderer_initiated = navigation_is_renderer_initiated_;
     params.referrer = referrer_;
-    params.is_using_https_as_default_scheme = true;
+    params.https_upgrade_type = web::HttpsUpgradeType::kHttpsOnlyMode;
     web_state->GetNavigationManager()->LoadURLWithParams(params);
     return;
   }
@@ -165,7 +165,8 @@
   // The upgrade either failed or succeeded. In both cases, stop the timer.
   timer_.Stop();
 
-  if (navigation_context->IsFailedHTTPSUpgrade()) {
+  if (navigation_context->GetFailedHttpsUpgradeType() ==
+      web::HttpsUpgradeType::kHttpsOnlyMode) {
     RecordUMA(Event::kUpgradeFailed);
     FallbackToHttp();
     return;
@@ -204,7 +205,9 @@
   params.transition_type = navigation_transition_type_;
   params.is_renderer_initiated = navigation_is_renderer_initiated_;
   params.referrer = referrer_;
-  params.is_using_https_as_default_scheme = true;
+  // Even though this is an HTTP navigation, mark it as "upgraded" so that we
+  // don't attempt to upgrade it again.
+  params.https_upgrade_type = web::HttpsUpgradeType::kHttpsOnlyMode;
   // Post a task to navigate to the fallback URL. We don't want to navigate
   // synchronously from a DidNavigationFinish() call.
   base::SequencedTaskRunnerHandle::Get()->PostTask(
@@ -284,7 +287,7 @@
   }
 
   // Upgrade to HTTPS if the navigation wasn't upgraded before.
-  if (!item_pending->IsUpgradedToHttps()) {
+  if (item_pending->GetHttpsUpgradeType() == web::HttpsUpgradeType::kNone) {
     if (!prefs_ || !prefs_->GetBoolean(prefs::kHttpsOnlyModeEnabled) ||
         service_->IsLocalhost(url)) {
       // Don't upgrade if the feature is disabled or the URL is localhost.
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm
index 1171259..f2f4742 100644
--- a/ios/chrome/browser/tabs/tab_helper_util.mm
+++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -87,6 +87,7 @@
 #import "ios/chrome/browser/web/session_state/web_session_state_tab_helper.h"
 #import "ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_tab_helper.h"
 #import "ios/chrome/browser/webui/net_export_tab_helper.h"
+#include "ios/components/security_interstitials/https_only_mode/feature.h"
 #import "ios/components/security_interstitials/https_only_mode/https_only_mode_container.h"
 #import "ios/components/security_interstitials/ios_blocking_page_tab_helper.h"
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_container.h"
@@ -237,9 +238,12 @@
   RepostFormTabHelper::CreateForWebState(web_state);
   NetExportTabHelper::CreateForWebState(web_state);
 
-  HttpsOnlyModeUpgradeTabHelper::CreateForWebState(web_state,
-                                                   browser_state->GetPrefs());
-  HttpsOnlyModeContainer::CreateForWebState(web_state);
+  if (base::FeatureList::IsEnabled(
+          security_interstitials::features::kHttpsOnlyMode)) {
+    HttpsOnlyModeUpgradeTabHelper::CreateForWebState(web_state,
+                                                     browser_state->GetPrefs());
+    HttpsOnlyModeContainer::CreateForWebState(web_state);
+  }
 
   if (IsWebChannelsEnabled()) {
     FollowTabHelper::CreateForWebState(web_state);
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn
index d9f408c..dc88192f 100644
--- a/ios/chrome/browser/ui/browser_view/BUILD.gn
+++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -125,7 +125,6 @@
     "//ios/chrome/browser/ui/infobars:public",
     "//ios/chrome/browser/ui/keyboard",
     "//ios/chrome/browser/ui/lens:coordinator",
-    "//ios/chrome/browser/ui/location_bar:location_bar_model_delegate",
     "//ios/chrome/browser/ui/main:default_browser_scene_agent",
     "//ios/chrome/browser/ui/main:scene_state_header",
     "//ios/chrome/browser/ui/main_content:main_content_ui",
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 40bb1ca6..ce19745d 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -16,7 +16,6 @@
 #import "base/strings/sys_string_conversions.h"
 #import "components/feature_engagement/public/event_constants.h"
 #import "components/feature_engagement/public/tracker.h"
-#import "components/omnibox/browser/location_bar_model_impl.h"
 #import "components/reading_list/core/reading_list_model.h"
 #import "components/sessions/core/tab_restore_service_helper.h"
 #import "components/signin/ios/browser/active_state_manager.h"
@@ -82,7 +81,6 @@
 #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h"
 #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_view.h"
 #import "ios/chrome/browser/ui/infobars/infobar_positioner.h"
-#import "ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.h"
 #import "ios/chrome/browser/ui/main/scene_state.h"
 #import "ios/chrome/browser/ui/main/scene_state_browser_agent.h"
 #import "ios/chrome/browser/ui/main_content/main_content_ui.h"
@@ -150,7 +148,6 @@
 #import "ios/public/provider/chrome/browser/voice_search/voice_search_api.h"
 #import "ios/public/provider/chrome/browser/voice_search/voice_search_controller.h"
 #import "ios/web/public/deprecated/crw_js_injection_receiver.h"
-#import "ios/web/public/navigation/navigation_item.h"
 #import "ios/web/public/ui/crw_web_view_proxy.h"
 #import "ios/web/public/web_state_observer_bridge.h"
 #import "net/base/mac/url_conversions.h"
@@ -166,8 +163,6 @@
 
 namespace {
 
-const size_t kMaxURLDisplayChars = 32 * 1024;
-
 // When the tab strip moves beyond this origin offset, switch the status bar
 // appearance from light to dark.
 const CGFloat kTabStripAppearanceOffset = -29;
@@ -267,11 +262,6 @@
   // Identifier for each animation of an NTP opening.
   NSInteger _NTPAnimationIdentifier;
 
-  // Facade objects used by `_toolbarCoordinator`.
-  // Must outlive `_toolbarCoordinator`.
-  std::unique_ptr<LocationBarModelDelegateIOS> _locationBarModelDelegate;
-  std::unique_ptr<LocationBarModel> _locationBarModel;
-
   // Helper for the bvc.
   // TODO(crbug.com/1329102): Remove this property.
   BrowserViewControllerHelper* _browserViewControllerHelper;
@@ -417,11 +407,6 @@
 // A snapshot of the tab strip used on the thumb strip reveal/hide animation.
 @property(nonatomic, strong) UIView* tabStripSnapshot;
 
-// The user agent type used to load the currently visible page. User agent
-// type is NONE if there is no visible page.
-// TODO(crbug.com/1272534): Move BubblePresenter to BrowserCoordinator.
-@property(nonatomic, assign, readonly) web::UserAgentType userAgentType;
-
 // Returns the header views, all the chrome on top of the page, including the
 // ones that cannot be scrolled off screen by full screen.
 @property(nonatomic, strong, readonly) NSArray<HeaderDefinition*>* headerViews;
@@ -644,18 +629,6 @@
   return IsRegularXRegularSizeClass(self);
 }
 
-- (web::UserAgentType)userAgentType {
-  web::WebState* webState = self.currentWebState;
-  if (!webState)
-    return web::UserAgentType::NONE;
-  web::NavigationItem* visibleItem =
-      webState->GetNavigationManager()->GetVisibleItem();
-  if (!visibleItem)
-    return web::UserAgentType::NONE;
-
-  return visibleItem->GetUserAgentType();
-}
-
 - (void)setVisible:(BOOL)visible {
   if (_visible == visible)
     return;
@@ -1345,8 +1318,6 @@
     self.secondaryToolbarCoordinator = nil;
     self.toolbarInterface = nil;
     _toolbarUIState = nil;
-    _locationBarModelDelegate = nil;
-    _locationBarModel = nil;
     _browserViewControllerHelper = nil;
     if (base::FeatureList::IsEnabled(kModernTabStrip)) {
       [self.tabStripCoordinator stop];
@@ -1727,15 +1698,6 @@
 // or not browser state and browser are valid.
 - (void)buildToolbarAndTabStrip {
   DCHECK([self isViewLoaded]);
-  DCHECK(!_locationBarModelDelegate);
-
-  // Create the location bar model and controller.
-  // TODO(crbug.com/1329101): Move all of this to the coordinator which owns the
-  // location bar.
-  _locationBarModelDelegate.reset(
-      new LocationBarModelDelegateIOS(self.browser->GetWebStateList()));
-  _locationBarModel = std::make_unique<LocationBarModelImpl>(
-      _locationBarModelDelegate.get(), kMaxURLDisplayChars);
 
   // TODO(crbug.com/1329094): Move this coordinator to BrowserCoordinator
   self.popupMenuCoordinator =
@@ -1957,7 +1919,6 @@
 // `self.browser`.
 - (void)addUIFunctionalityForBrowserAndBrowserState {
   DCHECK(self.browserState);
-  DCHECK(_locationBarModel);
   DCHECK(self.browser);
   DCHECK([self isViewLoaded]);
 
@@ -3698,12 +3659,6 @@
   [self.primaryToolbarCoordinator transitionToLocationBarFocusedState:NO];
 }
 
-// TODO(crbug.com/1329101): Remove this method, since the BVC will stop owning
-// the location bar model.
-- (LocationBarModel*)locationBarModel {
-  return _locationBarModel.get();
-}
-
 #pragma mark - BrowserCommands
 
 - (void)bookmarkCurrentPage {
@@ -3730,24 +3685,6 @@
   [self addURLsToReadingList:command.URLs];
 }
 
-// TODO(crbug.com/1272534): Move this command implementation to
-// BrowserCoordinator, which should be owning bubblePresenter.
-- (void)showReadingListIPH {
-  [self.bubblePresenter presentReadingListBottomToolbarTipBubble];
-}
-
-// TODO(crbug.com/1272534): Move this command implementation to
-// BrowserCoordinator, which should be owning bubblePresenter.
-- (void)showFollowWhileBrowsingIPH {
-  [self.bubblePresenter presentFollowWhileBrowsingTipBubble];
-}
-
-// TODO(crbug.com/1272534): Move this command implementation to
-// BrowserCoordinator, which should be owning bubblePresenter.
-- (void)showDefaultSiteViewIPH {
-  [self.bubblePresenter presentDefaultSiteViewTipBubble];
-}
-
 // TODO(crbug.com/1329104): Move voice search handling to BrowserCoordinator
 - (void)preloadVoiceSearch {
   // Preload VoiceSearchController and views and view controllers needed
@@ -3841,6 +3778,10 @@
   [_ntpCoordinator updateFollowingFeedHasUnseenContent:hasUnseenContent];
 }
 
+- (void)handleFeedModelDidEndUpdates:(FeedType)feedType {
+  [_ntpCoordinator handleFeedModelDidEndUpdates:feedType];
+}
+
 #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/new_tab_page_commands.h b/ios/chrome/browser/ui/commands/new_tab_page_commands.h
index bf87d495..f81b7a3fe 100644
--- a/ios/chrome/browser/ui/commands/new_tab_page_commands.h
+++ b/ios/chrome/browser/ui/commands/new_tab_page_commands.h
@@ -19,6 +19,9 @@
 // feed.
 - (void)updateFollowingFeedHasUnseenContent:(BOOL)hasUnseenContent;
 
+// Notifies the new tab page that the |feedType|'s model has completed updates.
+- (void)handleFeedModelDidEndUpdates:(FeedType)feedType;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_COMMANDS_NEW_TAB_PAGE_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn
index 5794f082..f1b93d5 100644
--- a/ios/chrome/browser/ui/location_bar/BUILD.gn
+++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -22,6 +22,7 @@
   ]
   deps = [
     ":constants",
+    ":location_bar_model_delegate",
     "resources:location_bar_connection_dangerous",
     "resources:location_bar_connection_info",
     "resources:location_bar_connection_offline",
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 402b8b33..3b1758c3 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -10,6 +10,7 @@
 #import "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/sys_string_conversions.h"
+#import "components/omnibox/browser/location_bar_model_impl.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/open_from_clipboard/clipboard_recent_content.h"
@@ -41,6 +42,7 @@
 #import "ios/chrome/browser/ui/location_bar/location_bar_constants.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_consumer.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_mediator.h"
+#import "ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_steady_view_consumer.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_steady_view_mediator.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_url_loader.h"
@@ -73,6 +75,10 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+const size_t kMaxURLDisplayChars = 32 * 1024;
+}  // namespace
+
 @interface LocationBarCoordinator () <LoadQueryCommands,
                                       LocationBarDelegate,
                                       LocationBarViewControllerDelegate,
@@ -85,6 +91,11 @@
   std::unique_ptr<FullscreenUIUpdater> _omniboxFullscreenUIUpdater;
   // Observer that updates BadgeViewController for fullscreen events.
   std::unique_ptr<FullscreenUIUpdater> _badgeFullscreenUIUpdater;
+
+  // Facade objects used by `_toolbarCoordinator`.
+  // Must outlive `_toolbarCoordinator`.
+  std::unique_ptr<LocationBarModelDelegateIOS> _locationBarModelDelegate;
+  std::unique_ptr<LocationBarModel> _locationBarModel;
 }
 // Whether the coordinator is started.
 @property(nonatomic, assign, getter=isStarted) BOOL started;
@@ -206,6 +217,11 @@
   self.mediator.consumer = self;
   self.mediator.webStateList = self.webStateList;
 
+  _locationBarModelDelegate.reset(
+      new LocationBarModelDelegateIOS(self.browser->GetWebStateList()));
+  _locationBarModel = std::make_unique<LocationBarModelImpl>(
+      _locationBarModelDelegate.get(), kMaxURLDisplayChars);
+
   self.steadyViewMediator = [[LocationBarSteadyViewMediator alloc]
       initWithLocationBarModel:[self locationBarModel]];
   self.steadyViewMediator.webStateList = self.browser->GetWebStateList();
@@ -239,6 +255,9 @@
   [self.steadyViewMediator disconnect];
   self.steadyViewMediator = nil;
 
+  _locationBarModel = nullptr;
+  _locationBarModelDelegate = nullptr;
+
   _badgeFullscreenUIUpdater = nullptr;
   _omniboxFullscreenUIUpdater = nullptr;
   self.started = NO;
@@ -303,8 +322,9 @@
     // call to load.
     web::NavigationManager::WebLoadParams web_params =
         web_navigation_util::CreateWebLoadParams(url, transition, postContent);
-    web_params.is_using_https_as_default_scheme =
-        destination_url_entered_without_scheme;
+    if (destination_url_entered_without_scheme) {
+      web_params.https_upgrade_type = web::HttpsUpgradeType::kOmnibox;
+    }
     NSMutableDictionary* combinedExtraHeaders =
         [[self variationHeadersForURL:url] mutableCopy];
     [combinedExtraHeaders addEntriesFromDictionary:web_params.extra_headers];
@@ -369,7 +389,7 @@
 }
 
 - (LocationBarModel*)locationBarModel {
-  return [self.delegate locationBarModel];
+  return _locationBarModel.get();
 }
 
 - (void)locationBarRequestScribbleTargetFocus {
diff --git a/ios/chrome/browser/ui/ntp/discover_feed_wrapper_view_controller.mm b/ios/chrome/browser/ui/ntp/discover_feed_wrapper_view_controller.mm
index 52be827..a17e2999 100644
--- a/ios/chrome/browser/ui/ntp/discover_feed_wrapper_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/discover_feed_wrapper_view_controller.mm
@@ -75,6 +75,7 @@
   UICollectionView* emptyCollectionView =
       [[UICollectionView alloc] initWithFrame:CGRectZero
                          collectionViewLayout:layout];
+  [emptyCollectionView setShowsVerticalScrollIndicator:NO];
   [self.view addSubview:emptyCollectionView];
   self.contentCollectionView = emptyCollectionView;
   self.contentCollectionView.backgroundColor = ntp_home::kNTPBackgroundColor();
diff --git a/ios/chrome/browser/ui/ntp/feed_management/feed_management_egtest.mm b/ios/chrome/browser/ui/ntp/feed_management/feed_management_egtest.mm
index 7a8dcec..084e92a 100644
--- a/ios/chrome/browser/ui/ntp/feed_management/feed_management_egtest.mm
+++ b/ios/chrome/browser/ui/ntp/feed_management/feed_management_egtest.mm
@@ -55,6 +55,15 @@
   }
 }
 
+void SelectFeedMenu() {
+  [[[EarlGrey
+      selectElementWithMatcher:grey_allOf(FeedMenuButton(),
+                                          grey_sufficientlyVisible(), nil)]
+         usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 100.0f)
+      onElementWithMatcher:chrome_test_util::NTPCollectionView()]
+      performAction:grey_tap()];
+}
+
 }  // namespace
 
 @interface FeedManagementTestCase : ChromeTestCase
@@ -69,8 +78,7 @@
 }
 
 - (void)testSignedOutOpenAndCloseFeedMenu {
-  [[EarlGrey selectElementWithMatcher:FeedMenuButton()]
-      performAction:grey_tap()];
+  SelectFeedMenu();
 
   [[EarlGrey selectElementWithMatcher:TurnOffFeedMenuItem()]
       assertWithMatcher:grey_notNil()];
@@ -95,8 +103,7 @@
   [SigninEarlGrey addFakeIdentity:fakeIdentity1];
   [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity1];
 
-  [[EarlGrey selectElementWithMatcher:FeedMenuButton()]
-      performAction:grey_tap()];
+  SelectFeedMenu();
 
   [[EarlGrey selectElementWithMatcher:ManageFeedMenuItem()]
       assertWithMatcher:grey_notNil()];
@@ -121,8 +128,7 @@
   [SigninEarlGrey addFakeIdentity:fakeIdentity1];
   [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity1];
 
-  [[EarlGrey selectElementWithMatcher:FeedMenuButton()]
-      performAction:grey_tap()];
+  SelectFeedMenu();
   [[EarlGrey selectElementWithMatcher:ManageFeedMenuItem()]
       performAction:grey_tap()];
 
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h
index b595876..94206b7 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h
@@ -83,6 +83,9 @@
 // feed.
 - (void)updateFollowingFeedHasUnseenContent:(BOOL)hasUnseenContent;
 
+// Called when the given |feedType| has completed updates.
+- (void)handleFeedModelDidEndUpdates:(FeedType)feedType;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_NTP_NEW_TAB_PAGE_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
index c27cd52c..c8f00e5 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -604,6 +604,18 @@
   }
 }
 
+- (void)handleFeedModelDidEndUpdates:(FeedType)feedType {
+  DCHECK(self.ntpViewController);
+  if (!self.discoverFeedViewController) {
+    return;
+  }
+  // When the visible feed has been updated, recalculate the minimum NTP height.
+  if (![self isFollowingFeedAvailable] ||
+      ([self isFollowingFeedAvailable] && feedType == self.selectedFeed)) {
+    [self.ntpViewController updateFeedInsetsForMinimumHeight];
+  }
+}
+
 - (void)ntpDidChangeVisibility:(BOOL)visible {
   if (!self.browser->GetBrowserState()->IsOffTheRecord()) {
     if (visible && self.started) {
@@ -646,9 +658,11 @@
   [self updateNTPForFeed];
   [self updateFeedLayout];
 
+  [self.ntpViewController updateFeedInsetsForMinimumHeight];
+
   // Scroll position resets when changing the feed, so we set it back to what it
   // was.
-  [self.ntpViewController setContentOffsetUpToTopOfFeed:scrollPosition];
+  [self.ntpViewController setContentOffsetToTopOfFeed:scrollPosition];
 }
 
 - (void)handleSortTypeForFollowingFeed:(FollowingFeedSortType)sortType {
@@ -1104,8 +1118,9 @@
 
 // Creates, configures and returns a Discover feed view controller.
 - (UIViewController*)discoverFeed {
-  if (tests_hook::DisableDiscoverFeed())
+  if (tests_hook::DisableDiscoverFeed()) {
     return nil;
+  }
 
   UIViewController* discoverFeed =
       self.discoverFeedService->NewDiscoverFeedViewControllerWithConfiguration(
@@ -1115,8 +1130,9 @@
 
 // Creates, configures and returns a Following feed view controller.
 - (UIViewController*)followingFeed {
-  if (tests_hook::DisableDiscoverFeed())
+  if (tests_hook::DisableDiscoverFeed()) {
     return nil;
+  }
 
   UIViewController* followingFeed =
       self.discoverFeedService->NewFollowingFeedViewControllerWithConfiguration(
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h
index 19b3629..874e978 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h
@@ -132,7 +132,11 @@
 // Sets the NTP collection view's scroll position to |contentOffset|, unless it
 // is beyond the top of the feed. In that case, sets the scroll position to the
 // top of the feed.
-- (void)setContentOffsetUpToTopOfFeed:(CGFloat)contentOffset;
+- (void)setContentOffsetToTopOfFeed:(CGFloat)contentOffset;
+
+// Checks the content size of the feed and updates the bottom content inset to
+// ensure the feed is still scrollable to the minimum height.
+- (void)updateFeedInsetsForMinimumHeight;
 
 @end
 
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
index e02aaa4..b636d70 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
@@ -285,6 +285,9 @@
                       completion:^(
                           id<UIViewControllerTransitionCoordinatorContext>) {
                         [self updateNTPLayout];
+                        if (self.isFeedVisible) {
+                          [self updateFeedInsetsForMinimumHeight];
+                        }
                       }];
 }
 
@@ -493,7 +496,7 @@
   return self.collectionView.contentOffset.y;
 }
 
-- (void)setContentOffsetUpToTopOfFeed:(CGFloat)contentOffset {
+- (void)setContentOffsetToTopOfFeed:(CGFloat)contentOffset {
   if (contentOffset < [self offsetWhenScrolledIntoFeed]) {
     [self setContentOffset:contentOffset];
   } else {
@@ -501,6 +504,28 @@
   }
 }
 
+- (void)updateFeedInsetsForMinimumHeight {
+  DCHECK(self.isFeedVisible);
+  CGFloat minimumNTPHeight =
+      self.collectionView.bounds.size.height +
+      self.discoverFeedWrapperViewController.view.safeAreaInsets.top;
+  minimumNTPHeight -= [self feedHeaderHeight];
+  if ([self shouldPinFakeOmnibox]) {
+    minimumNTPHeight -= ([self.headerController headerHeight] +
+                         ntp_header::kScrolledToTopOmniboxBottomMargin);
+  }
+
+  if (self.collectionView.contentSize.height > minimumNTPHeight) {
+    self.collectionView.contentInset =
+        UIEdgeInsetsMake(self.collectionView.contentInset.top, 0, 0, 0);
+  } else {
+    CGFloat bottomInset =
+        minimumNTPHeight - self.collectionView.contentSize.height;
+    self.collectionView.contentInset = UIEdgeInsetsMake(
+        self.collectionView.contentInset.top, 0, bottomInset, 0);
+  }
+}
+
 #pragma mark - UIScrollViewDelegate
 
 - (void)scrollViewDidScroll:(UIScrollView*)scrollView {
@@ -827,8 +852,8 @@
 // then place the content above the feed in this space.
 - (void)updateFeedInsetsForContentAbove {
   // Adds inset to feed to create space for content above feed.
-  self.collectionView.contentInset =
-      UIEdgeInsetsMake([self heightAboveFeed], 0, 0, 0);
+  self.collectionView.contentInset = UIEdgeInsetsMake(
+      [self heightAboveFeed], 0, self.collectionView.contentInset.bottom, 0);
 
   // Sets the frame for feed header, top section and content suggestions within
   // the space from the inset.
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.mm
index 305cf3f..1f4fd51 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history.mm
@@ -30,6 +30,10 @@
 // places.
 constexpr double kDampening = 1.1;
 
+// kInitialBufferNumClicks represents the minimum number of clicks a destination
+// must have before the user notices a visible change in the carousel sort.
+constexpr int kInitialBufferNumClicks = 3;  // clicks
+
 // The dictionary key used for storing rankings.
 const std::string kRankingKey = "ranking";
 
@@ -233,9 +237,10 @@
   if (!self.prefService)
     return;
 
-  const base::Value* pref = self.prefService->GetDictionary(
-      prefs::kOverflowMenuDestinationUsageHistory);
-  const base::Value::Dict* history = pref->GetIfDict();
+  const base::Value::Dict* history =
+      self.prefService
+          ->GetDictionary(prefs::kOverflowMenuDestinationUsageHistory)
+          ->GetIfDict();
   const std::string path = base::NumberToString(TodaysDay()) + "." +
                            overflow_menu::StringNameForDestination(destination);
 
@@ -245,6 +250,10 @@
                               prefs::kOverflowMenuDestinationUsageHistory);
   update->SetIntPath(path, numClicks);
 
+  // User's very first time using Smart Sorting.
+  if (history->size() == 0)
+    [self injectDefaultNumClicksForAllDestinations];
+
   // Calculate new ranking and store to prefs; Calculate the new ranking
   // ahead of time so overflow menu presentation needn't run ranking algorithm
   // each time it presents.
@@ -257,6 +266,30 @@
 
 #pragma mark - Private
 
+// Injects a default number of clicks for all destinations in the history
+// dictonary.
+- (void)injectDefaultNumClicksForAllDestinations {
+  DCHECK_GT(kDampening, 1.0);
+  DCHECK_GT(kInitialBufferNumClicks, 1);
+
+  int defaultNumClicks =
+      (kInitialBufferNumClicks - 1) * (kDampening - 1.0) * 100.0;
+  std::string today = base::NumberToString(TodaysDay());
+  DictionaryPrefUpdate update(self.prefService,
+                              prefs::kOverflowMenuDestinationUsageHistory);
+  const base::Value::Dict* history =
+      self.prefService
+          ->GetDictionary(prefs::kOverflowMenuDestinationUsageHistory)
+          ->GetIfDict();
+
+  for (overflow_menu::Destination destination : kDefaultRanking) {
+    const std::string path =
+        today + "." + overflow_menu::StringNameForDestination(destination);
+    update->SetIntPath(path, history->FindIntByDottedPath(path).value_or(0) +
+                                 defaultNumClicks);
+  }
+}
+
 // Delete expired usage data (data older than |kDataExpirationWindow| days) and
 // saves back to prefs. Returns true if expired usage data was found/removed,
 // false otherwise.
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history_unittest.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history_unittest.mm
index 8ea31e8..57e96af 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history_unittest.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/destination_usage_history/destination_usage_history_unittest.mm
@@ -192,7 +192,54 @@
   ASSERT_NE(target, nullptr);
   EXPECT_TRUE(destination_usage_history.prefService->HasPrefPath(
       prefs::kOverflowMenuDestinationUsageHistory));
-  EXPECT_EQ(1, target->GetInt());
+  EXPECT_EQ(21, target->GetInt());
+}
+
+// Tests that each destination in the history is populated with a default number
+// of clicks.
+TEST_F(DestinationUsageHistoryTest, InjectsDefaultNumClicksForAllDestinations) {
+  DestinationUsageHistory* destination_usage_history =
+      CreateDestinationUsageHistory();
+
+  // Click bookmarks destination.
+  [destination_usage_history
+         trackDestinationClick:overflow_menu::Destination::Bookmarks
+      numAboveFoldDestinations:numAboveFoldDestinations];
+
+  // Fetch saved destination usage history.
+  const base::Value* history =
+      destination_usage_history.prefService->GetDictionary(
+          prefs::kOverflowMenuDestinationUsageHistory);
+  ASSERT_NE(history, nullptr);
+  ASSERT_TRUE(history->is_dict());
+
+  const base::Value::Dict* history_dict = history->GetIfDict();
+  ASSERT_NE(history, nullptr);
+
+  EXPECT_TRUE(destination_usage_history.prefService->HasPrefPath(
+      prefs::kOverflowMenuDestinationUsageHistory));
+
+  std::vector<overflow_menu::Destination> destinations = {
+      overflow_menu::Destination::Bookmarks,
+      overflow_menu::Destination::History,
+      overflow_menu::Destination::ReadingList,
+      overflow_menu::Destination::Passwords,
+      overflow_menu::Destination::Downloads,
+      overflow_menu::Destination::RecentTabs,
+      overflow_menu::Destination::SiteInfo,
+      overflow_menu::Destination::Settings,
+  };
+
+  int today = TodaysDay();
+  for (overflow_menu::Destination destination : destinations) {
+    const base::Value* target =
+        history_dict->FindByDottedPath(DottedPath(today, destination));
+    int expected_count =
+        destination == overflow_menu::Destination::Bookmarks ? 21 : 20;
+
+    EXPECT_NE(target, nullptr);
+    EXPECT_EQ(expected_count, target->GetInt());
+  }
 }
 
 // Tests that an existing destination click is incremented and written to Chrome
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift
index 0500f91..a5005b41 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift
@@ -41,6 +41,9 @@
   /// The current dynamic type size.
   @Environment(\.sizeCategory) var sizeCategory
 
+  /// The current environment layout direction.
+  @Environment(\.layoutDirection) var layoutDirection: LayoutDirection
+
   /// The destinations for this view.
   var destinations: [OverflowMenuDestination]
 
@@ -48,31 +51,39 @@
 
   var body: some View {
     GeometryReader { geometry in
-      ScrollView(.horizontal, showsIndicators: false) {
-        let spacing = destinationSpacing(forScreenWidth: geometry.size.width)
-        let layoutParameters: OverflowMenuDestinationView.LayoutParameters =
-          sizeCategory >= .accessibilityMedium
-          ? .horizontal(itemWidth: geometry.size.width - Constants.largeTextSizeSpace)
-          : .vertical(
-            iconSpacing: spacing.iconSpacing,
-            iconPadding: spacing.iconPadding)
-        let alignment: VerticalAlignment = sizeCategory >= .accessibilityMedium ? .center : .top
+      ScrollViewReader { proxy in
+        ScrollView(.horizontal, showsIndicators: false) {
+          let spacing = destinationSpacing(forScreenWidth: geometry.size.width)
+          let layoutParameters: OverflowMenuDestinationView.LayoutParameters =
+            sizeCategory >= .accessibilityMedium
+            ? .horizontal(itemWidth: geometry.size.width - Constants.largeTextSizeSpace)
+            : .vertical(
+              iconSpacing: spacing.iconSpacing,
+              iconPadding: spacing.iconPadding)
+          let alignment: VerticalAlignment = sizeCategory >= .accessibilityMedium ? .center : .top
 
-        VStack {
-          Spacer(minLength: Constants.topMargin)
-          LazyHStack(alignment: alignment, spacing: 0) {
-            ForEach(destinations) { destination in
-              OverflowMenuDestinationView(
-                destination: destination, layoutParameters: layoutParameters,
-                metricsHandler: metricsHandler)
+          VStack {
+            Spacer(minLength: Constants.topMargin)
+            LazyHStack(alignment: alignment, spacing: 0) {
+              ForEach(destinations) { destination in
+                OverflowMenuDestinationView(
+                  destination: destination, layoutParameters: layoutParameters,
+                  metricsHandler: metricsHandler
+                ).id(destination.destinationName)
+              }
             }
           }
+          // Make sure the space to the first icon is constant, so add extra
+          // spacing before the first item.
+          .padding([.leading], Constants.iconInitialSpace - spacing.iconSpacing)
         }
-        // Make sure the space to the first icon is constant, so add extra
-        // spacing before the first item.
-        .padding([.leading], Constants.iconInitialSpace - spacing.iconSpacing)
+        .accessibilityIdentifier(kPopupMenuToolsMenuTableViewId)
+        .onAppear {
+          if layoutDirection == .rightToLeft {
+            proxy.scrollTo(destinations.last?.destinationName)
+          }
+        }
       }
-      .accessibilityIdentifier(kPopupMenuToolsMenuTableViewId)
     }
   }
 
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
index 99c60ea..0ce3b31 100644
--- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
@@ -849,7 +849,7 @@
     self.settingsDestination,
   ];
 
-  if (IsSmartSortingNewOverflowMenuEnabled()) {
+  if (self.destinationUsageHistory && IsSmartSortingNewOverflowMenuEnabled()) {
     baseDestinations = [self.destinationUsageHistory
         generateDestinationsList:baseDestinations];
   }
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_coordinator_delegate.h b/ios/chrome/browser/ui/toolbar/toolbar_coordinator_delegate.h
index 2e7a718..802685f 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_coordinator_delegate.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_coordinator_delegate.h
@@ -17,8 +17,6 @@
 - (void)locationBarDidBecomeFirstResponder;
 // Called when the location bar loses keyboard focus.
 - (void)locationBarDidResignFirstResponder;
-// Returns the location bar model.
-- (LocationBarModel*)locationBarModel;
 
 @end
 
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm
index 2de7141c..2c3a473 100644
--- a/ios/web/navigation/crw_wk_navigation_handler.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -66,19 +66,25 @@
 // Returns true if the navigation was upgraded to HTTPS but failed due to an
 // SSL or net error. This can happen when HTTPS-Only Mode feature automatically
 // upgrades a navigation to HTTPS.
-bool IsFailedHttpsUpgrade(NSError* error,
-                          web::NavigationContextImpl* context,
-                          NSError* cancellationError) {
+web::HttpsUpgradeType GetFailedHttpsUpgradeType(
+    NSError* error,
+    web::NavigationContextImpl* context,
+    NSError* cancellationError) {
   if (!context || !context->GetItem() ||
-      !context->GetItem()->IsUpgradedToHttps() || cancellationError) {
-    return false;
+      context->GetItem()->GetHttpsUpgradeType() ==
+          web::HttpsUpgradeType::kNone ||
+      cancellationError) {
+    return web::HttpsUpgradeType::kNone;
   }
   int error_code = 0;
   if (!web::GetNetErrorFromIOSErrorCode(
           error.code, &error_code, net::NSURLWithGURL(context->GetUrl()))) {
     error_code = net::ERR_FAILED;
   }
-  return (error_code != net::OK || web::IsWKWebViewSSLCertError(error));
+  if (error_code != net::OK || web::IsWKWebViewSSLCertError(error)) {
+    return context->GetItem()->GetHttpsUpgradeType();
+  }
+  return web::HttpsUpgradeType::kNone;
 }
 
 }  // namespace
@@ -1685,10 +1691,11 @@
 
   web::NavigationContextImpl* navigationContext =
       [self.navigationStates contextForNavigation:navigation];
-  if (IsFailedHttpsUpgrade(error, navigationContext,
-                           policyDecisionCancellationError)) {
+  web::HttpsUpgradeType failed_upgrade_type = GetFailedHttpsUpgradeType(
+      error, navigationContext, policyDecisionCancellationError);
+  if (failed_upgrade_type != web::HttpsUpgradeType::kNone) {
     navigationContext->SetError(contextError);
-    navigationContext->SetIsFailedHTTPSUpgrade();
+    navigationContext->SetFailedHttpsUpgradeType(failed_upgrade_type);
     [self handleCancelledError:error
                  forNavigation:navigation
                provisionalLoad:provisionalLoad];
@@ -1815,8 +1822,7 @@
   self.navigationManagerImpl->AddPendingItem(
       blockedURL, web::Referrer(), transition,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   // Create context.
   std::unique_ptr<web::NavigationContextImpl> context =
@@ -1880,9 +1886,10 @@
 - (void)handleCancelledError:(NSError*)error
                forNavigation:(WKNavigation*)navigation
              provisionalLoad:(BOOL)provisionalLoad {
-  if (!IsFailedHttpsUpgrade(
-          error, [self.navigationStates contextForNavigation:navigation],
-          self.pendingNavigationInfo.cancellationError) &&
+  web::HttpsUpgradeType failed_upgrade_type = GetFailedHttpsUpgradeType(
+      error, [self.navigationStates contextForNavigation:navigation],
+      self.pendingNavigationInfo.cancellationError);
+  if (failed_upgrade_type == web::HttpsUpgradeType::kNone &&
       ![self shouldCancelLoadForCancelledError:error
                                provisionalLoad:provisionalLoad]) {
     return;
diff --git a/ios/web/navigation/crw_wk_navigation_handler_inttest.mm b/ios/web/navigation/crw_wk_navigation_handler_inttest.mm
index 66daae8..72a34c8 100644
--- a/ios/web/navigation/crw_wk_navigation_handler_inttest.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler_inttest.mm
@@ -8,6 +8,7 @@
 #import "base/test/ios/wait_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "ios/web/common/features.h"
+#import "ios/web/public/navigation/https_upgrade_type.h"
 #import "ios/web/public/navigation/navigation_context.h"
 #import "ios/web/public/navigation/navigation_item.h"
 #import "ios/web/public/test/fakes/fake_web_client.h"
@@ -25,6 +26,7 @@
 #endif
 
 using base::test::ios::kWaitForPageLoadTimeout;
+using web::HttpsUpgradeType;
 
 namespace {
 
@@ -49,7 +51,8 @@
       web::WebState* web_state,
       web::NavigationContext* navigation_context) override {
     did_finish_ = true;
-    failed_https_upgrade_ = navigation_context->IsFailedHTTPSUpgrade();
+    failed_https_upgrade_type_ =
+        navigation_context->GetFailedHttpsUpgradeType();
 
     DCHECK_EQ(ErrorType::kNone, error_type_);
     NSError* error = navigation_context->GetError();
@@ -71,12 +74,15 @@
   void WebStateDestroyed(web::WebState* web_state) override { NOTREACHED(); }
 
   bool did_finish() const { return did_finish_; }
-  bool failed_https_upgrade() const { return failed_https_upgrade_; }
+  web::HttpsUpgradeType failed_https_upgrade_type() const {
+    return failed_https_upgrade_type_;
+  }
   ErrorType error_type() const { return error_type_; }
 
  private:
   bool did_finish_ = false;
-  bool failed_https_upgrade_ = false;
+  web::HttpsUpgradeType failed_https_upgrade_type_ =
+      web::HttpsUpgradeType::kNone;
   ErrorType error_type_ = ErrorType::kNone;
 };
 
@@ -96,18 +102,18 @@
     return static_cast<FakeWebClient*>(WebIntTest::GetWebClient());
   }
 
-  // Tests IsFailedHTTPSUpgrade() status of a navigation. Navigates to `url`
-  // using `use_https_as_default` as the HTTPS upgrade status. Expects
-  // IsFailedHTTPSUpgrade() to be true if `expected_failed_upgrade` is true.
+  // Tests the failed HTTPS upgradestatus of a navigation. Navigates to `url`
+  // using `https_upgrade_type` as the HTTPS upgrade type. Expects
+  // GetFailedHTTPSUpgradeType() to be equal to `https_upgrade_type`.
   // Expects the navigation error to be of type `expected_error_type`.
   void TestFailedHttpsUpgrade(
       const GURL& url,
-      bool use_https_as_default,
-      bool expected_failed_upgrade,
+      HttpsUpgradeType https_upgrade_type,
+      HttpsUpgradeType expected_failed_upgrade_type,
       FailedWebStateObserver::ErrorType expected_error_type) {
     web::NavigationManager::WebLoadParams params(url);
     params.transition_type = ui::PAGE_TRANSITION_TYPED;
-    params.is_using_https_as_default_scheme = use_https_as_default;
+    params.https_upgrade_type = https_upgrade_type;
 
     FailedWebStateObserver observer;
     base::ScopedObservation<WebState, WebStateObserver> scoped_observer(
@@ -124,8 +130,8 @@
           // instead of failing with an SSL error.
           base::RunLoop().RunUntilIdle();
           return observer_ptr->did_finish() &&
-                 (observer_ptr->failed_https_upgrade() ==
-                  expected_failed_upgrade);
+                 (observer_ptr->failed_https_upgrade_type() ==
+                  expected_failed_upgrade_type);
         }));
     EXPECT_EQ(expected_error_type, observer.error_type());
   }
@@ -166,8 +172,7 @@
 TEST_F(CRWKNavigationHandlerIntTest, FailedHTTPSUpgrade_NotUpgraded_SSLError) {
   ASSERT_TRUE(https_server_.Start());
   GURL url(https_server_.GetURL("/"));
-  TestFailedHttpsUpgrade(url, /*use_https_as_default=*/false,
-                         /*expected_failed_upgrade=*/false,
+  TestFailedHttpsUpgrade(url, HttpsUpgradeType::kNone, HttpsUpgradeType::kNone,
                          FailedWebStateObserver::ErrorType::kSSLError);
 }
 
@@ -176,8 +181,8 @@
 TEST_F(CRWKNavigationHandlerIntTest, FailedHTTPSUpgrade_Upgraded_SSLError) {
   ASSERT_TRUE(https_server_.Start());
   GURL url(https_server_.GetURL("/"));
-  TestFailedHttpsUpgrade(url, /*use_https_as_default=*/true,
-                         /*expected_failed_upgrade=*/true,
+  TestFailedHttpsUpgrade(url, HttpsUpgradeType::kHttpsOnlyMode,
+                         HttpsUpgradeType::kHttpsOnlyMode,
                          FailedWebStateObserver::ErrorType::kSSLError);
 }
 
@@ -185,8 +190,7 @@
 // doesn't set the IsFailedHTTPSUpgrade() bit on the navigation context.
 TEST_F(CRWKNavigationHandlerIntTest, FailedHTTPSUpgrade_NotUpgraded_NetError) {
   GURL url("https://site.test");
-  TestFailedHttpsUpgrade(url, /*use_https_as_default=*/false,
-                         /*expected_failed_upgrade=*/false,
+  TestFailedHttpsUpgrade(url, HttpsUpgradeType::kNone, HttpsUpgradeType::kNone,
                          FailedWebStateObserver::ErrorType::kNetError);
 }
 
@@ -194,8 +198,8 @@
 // sets the IsFailedHTTPSUpgrade() bit on the navigation context.
 TEST_F(CRWKNavigationHandlerIntTest, FailedHTTPSUpgrade_Upgraded_NetError) {
   GURL url("https://site.test");
-  TestFailedHttpsUpgrade(url, /*use_https_as_default=*/true,
-                         /*expected_failed_upgrade=*/true,
+  TestFailedHttpsUpgrade(url, HttpsUpgradeType::kHttpsOnlyMode,
+                         HttpsUpgradeType::kHttpsOnlyMode,
                          FailedWebStateObserver::ErrorType::kNetError);
 }
 
diff --git a/ios/web/navigation/navigation_context_impl.h b/ios/web/navigation/navigation_context_impl.h
index 3a967a2..c30f465 100644
--- a/ios/web/navigation/navigation_context_impl.h
+++ b/ios/web/navigation/navigation_context_impl.h
@@ -92,8 +92,8 @@
   void SetMimeType(NSString* mime_type);
   NSString* GetMimeType() const;
 
-  bool IsFailedHTTPSUpgrade() const override;
-  void SetIsFailedHTTPSUpgrade();
+  HttpsUpgradeType GetFailedHttpsUpgradeType() const override;
+  void SetFailedHttpsUpgradeType(HttpsUpgradeType https_upgrade_type);
 
   // Returns pending navigation item.
   NavigationItemImpl* GetItem();
@@ -132,9 +132,9 @@
   bool is_loading_error_page_ = false;
   bool is_loading_html_string_ = false;
   NSString* mime_type_ = nil;
-  // If true, this navigation was an HTTPS upgrade from HTTP and
-  // failed due to an SSL error.
-  bool is_failed_https_upgrade_ = false;
+  // If not equal to kNone, this navigation was an HTTPS upgrade from HTTP and
+  // failed due to an SSL or net error.
+  HttpsUpgradeType failed_https_upgrade_type_ = HttpsUpgradeType::kNone;
   base::ElapsedTimer elapsed_timer_;
 
   // Holds pending navigation item in this object. Pending item is stored in
diff --git a/ios/web/navigation/navigation_context_impl.mm b/ios/web/navigation/navigation_context_impl.mm
index 51f186d..dac0b0112 100644
--- a/ios/web/navigation/navigation_context_impl.mm
+++ b/ios/web/navigation/navigation_context_impl.mm
@@ -131,12 +131,12 @@
   response_headers_ = response_headers;
 }
 
-bool NavigationContextImpl::IsFailedHTTPSUpgrade() const {
-  return is_failed_https_upgrade_;
+HttpsUpgradeType NavigationContextImpl::GetFailedHttpsUpgradeType() const {
+  return failed_https_upgrade_type_;
 }
 
-void NavigationContextImpl::SetIsFailedHTTPSUpgrade() {
-  is_failed_https_upgrade_ = true;
+void NavigationContextImpl::SetFailedHttpsUpgradeType(HttpsUpgradeType type) {
+  failed_https_upgrade_type_ = type;
 }
 
 int NavigationContextImpl::GetNavigationItemUniqueID() const {
diff --git a/ios/web/navigation/navigation_item_impl.h b/ios/web/navigation/navigation_item_impl.h
index cde870b..3038c30 100644
--- a/ios/web/navigation/navigation_item_impl.h
+++ b/ios/web/navigation/navigation_item_impl.h
@@ -61,8 +61,8 @@
   bool HasPostData() const override;
   NSDictionary* GetHttpRequestHeaders() const override;
   void AddHttpRequestHeaders(NSDictionary* additional_headers) override;
-  void SetUpgradedToHttps() override;
-  bool IsUpgradedToHttps() const override;
+  void SetHttpsUpgradeType(HttpsUpgradeType https_upgrade_type) override;
+  HttpsUpgradeType GetHttpsUpgradeType() const override;
 
   // Serialized representation of the state object that was used in conjunction
   // with a JavaScript window.history.pushState() or
@@ -162,9 +162,8 @@
   // virtual URL, or title is set, this should be cleared to force a refresh.
   mutable std::u16string cached_display_title_;
 
-  // True if this navigation was typed without a scheme and its URL is using
-  // https:// as the default scheme.
-  bool is_upgraded_to_https_;
+  // Type of the HTTPS upgrade applied to this navigation, if any.
+  HttpsUpgradeType https_upgrade_type_;
 
   // Copy and assignment is explicitly allowed for this class.
 };
diff --git a/ios/web/navigation/navigation_item_impl.mm b/ios/web/navigation/navigation_item_impl.mm
index 342c92fc..355c163 100644
--- a/ios/web/navigation/navigation_item_impl.mm
+++ b/ios/web/navigation/navigation_item_impl.mm
@@ -56,7 +56,7 @@
       should_skip_serialization_(false),
       navigation_initiation_type_(web::NavigationInitiationType::NONE),
       is_untrusted_(false),
-      is_upgraded_to_https_(false) {}
+      https_upgrade_type_(HttpsUpgradeType::kNone) {}
 
 NavigationItemImpl::~NavigationItemImpl() {
 }
@@ -84,7 +84,7 @@
       navigation_initiation_type_(item.navigation_initiation_type_),
       is_untrusted_(item.is_untrusted_),
       cached_display_title_(item.cached_display_title_),
-      is_upgraded_to_https_(item.is_upgraded_to_https_) {}
+      https_upgrade_type_(item.https_upgrade_type_) {}
 
 int NavigationItemImpl::GetUniqueID() const {
   return unique_id_;
@@ -235,12 +235,13 @@
     http_request_headers_ = [additional_headers mutableCopy];
 }
 
-void NavigationItemImpl::SetUpgradedToHttps() {
-  is_upgraded_to_https_ = true;
+void NavigationItemImpl::SetHttpsUpgradeType(
+    HttpsUpgradeType https_upgrade_type) {
+  https_upgrade_type_ = https_upgrade_type;
 }
 
-bool NavigationItemImpl::IsUpgradedToHttps() const {
-  return is_upgraded_to_https_;
+HttpsUpgradeType NavigationItemImpl::GetHttpsUpgradeType() const {
+  return https_upgrade_type_;
 }
 
 void NavigationItemImpl::SetSerializedStateObject(
@@ -353,7 +354,7 @@
            "displayState:%@ userAgent:%s "
            "is_created_from_hash_change: %@ "
            "navigation_initiation_type: %d "
-           "is_upgraded_to_https: %@",
+           "https_upgrade_type: %s",
           url_.spec().c_str(), virtual_url_.spec().c_str(),
           original_request_url_.spec().c_str(), referrer_.url.spec().c_str(),
           base::UTF16ToUTF8(title_).c_str(), transition_type_,
@@ -361,7 +362,7 @@
           GetUserAgentTypeDescription(user_agent_type_).c_str(),
           is_created_from_hash_change_ ? @"true" : @"false",
           navigation_initiation_type_,
-          is_upgraded_to_https_ ? @"true" : @"false"];
+          GetHttpsUpgradeTypeDescription(https_upgrade_type_).c_str()];
 }
 #endif
 
diff --git a/ios/web/navigation/navigation_item_impl_unittest.mm b/ios/web/navigation/navigation_item_impl_unittest.mm
index 5cc2cd9..c05f891 100644
--- a/ios/web/navigation/navigation_item_impl_unittest.mm
+++ b/ios/web/navigation/navigation_item_impl_unittest.mm
@@ -61,7 +61,7 @@
   EXPECT_TRUE(
       [description containsString:@"is_created_from_hash_change: false"]);
   EXPECT_TRUE([description containsString:@"navigation_initiation_type: 0"]);
-  EXPECT_TRUE([description containsString:@"is_upgraded_to_https: false"]);
+  EXPECT_TRUE([description containsString:@"https_upgrade_type: None"]);
 }
 #endif
 
diff --git a/ios/web/navigation/navigation_manager_impl.h b/ios/web/navigation/navigation_manager_impl.h
index 0ed34f8..923eaab 100644
--- a/ios/web/navigation/navigation_manager_impl.h
+++ b/ios/web/navigation/navigation_manager_impl.h
@@ -144,15 +144,14 @@
   // nil if there isn't one. The item starts out as pending, and will be lost
   // unless |-commitPendingItem| is called.
   // |is_post_navigation| is true if the navigation is using a POST HTTP method.
-  //|is_using_https_as_default_scheme| must be true for navigations that use
-  // https:// as the default scheme
-  // in their URL, if the user typed the URL without a scheme.
+  // |https_upgrade_type| indicates the type of the HTTPS upgrade applied on
+  // this navigation.
   void AddPendingItem(const GURL& url,
                       const web::Referrer& referrer,
                       ui::PageTransition navigation_type,
                       NavigationInitiationType initiation_type,
                       bool is_post_navigation,
-                      bool is_using_https_as_default_scheme);
+                      web::HttpsUpgradeType https_upgrade_type);
 
   // Commits the pending item, if any.
   // TODO(crbug.com/936933): Remove this method.
@@ -369,7 +368,7 @@
       const Referrer& referrer,
       ui::PageTransition transition,
       NavigationInitiationType initiation_type,
-      bool is_using_https_as_default_scheme,
+      HttpsUpgradeType https_upgrade_type,
       const GURL& previous_url,
       const std::vector<BrowserURLRewriter::URLRewriter>* url_rewriters) const;
 
diff --git a/ios/web/navigation/navigation_manager_impl.mm b/ios/web/navigation/navigation_manager_impl.mm
index 89f69119..c02e7e1c 100644
--- a/ios/web/navigation/navigation_manager_impl.mm
+++ b/ios/web/navigation/navigation_manager_impl.mm
@@ -66,7 +66,7 @@
       transition_type(ui::PAGE_TRANSITION_LINK),
       is_renderer_initiated(false),
       post_data(nil),
-      is_using_https_as_default_scheme(false) {}
+      https_upgrade_type(HttpsUpgradeType::kNone) {}
 
 NavigationManager::WebLoadParams::~WebLoadParams() {}
 
@@ -78,8 +78,7 @@
       is_renderer_initiated(other.is_renderer_initiated),
       extra_headers([other.extra_headers copy]),
       post_data([other.post_data copy]),
-      is_using_https_as_default_scheme(other.is_using_https_as_default_scheme) {
-}
+      https_upgrade_type(other.https_upgrade_type) {}
 
 NavigationManager::WebLoadParams& NavigationManager::WebLoadParams::operator=(
     const WebLoadParams& other) {
@@ -90,7 +89,7 @@
   transition_type = other.transition_type;
   extra_headers = [other.extra_headers copy];
   post_data = [other.post_data copy];
-  is_using_https_as_default_scheme = other.is_using_https_as_default_scheme;
+  https_upgrade_type = other.https_upgrade_type;
 
   return *this;
 }
@@ -180,15 +179,14 @@
     ui::PageTransition navigation_type,
     NavigationInitiationType initiation_type,
     bool is_post_navigation,
-    bool is_using_https_as_default_scheme) {
+    HttpsUpgradeType https_upgrade_type) {
   DiscardNonCommittedItems();
 
   pending_item_index_ = -1;
   NavigationItem* last_committed_item =
       GetLastCommittedItemInCurrentOrRestoredSession();
   pending_item_ = CreateNavigationItemWithRewriters(
-      url, referrer, navigation_type, initiation_type,
-      is_using_https_as_default_scheme,
+      url, referrer, navigation_type, initiation_type, https_upgrade_type,
       last_committed_item ? last_committed_item->GetURL() : GURL::EmptyGURL(),
       &transient_url_rewriters_);
   RemoveTransientURLRewriters();
@@ -659,7 +657,7 @@
           : NavigationInitiationType::BROWSER_INITIATED;
   AddPendingItem(params.url, params.referrer, params.transition_type,
                  initiation_type, /*is_post_navigation=*/false,
-                 params.is_using_https_as_default_scheme);
+                 params.https_upgrade_type);
 
   // Mark pending item as created from hash change if necessary. This is needed
   // because window.hashchange message may not arrive on time.
@@ -679,8 +677,7 @@
     if (params.virtual_url.is_valid())
       pending_item->SetVirtualURL(params.virtual_url);
 
-    if (params.is_using_https_as_default_scheme)
-      pending_item->SetUpgradedToHttps();
+    pending_item->SetHttpsUpgradeType(params.https_upgrade_type);
   }
 
   // Add additional headers to the NavigationItem before loading it in the web
@@ -692,8 +689,7 @@
   if (params.extra_headers)
     added_item->AddHttpRequestHeaders(params.extra_headers);
 
-  if (params.is_using_https_as_default_scheme)
-    added_item->SetUpgradedToHttps();
+  added_item->SetHttpsUpgradeType(params.https_upgrade_type);
 
   if (params.post_data) {
     DCHECK([added_item->GetHttpRequestHeaders() objectForKey:@"Content-Type"])
@@ -981,8 +977,7 @@
       last_committed_web_view_item_ = CreateNavigationItemWithRewriters(
           /*url=*/GURL::EmptyGURL(), Referrer(),
           ui::PageTransition::PAGE_TRANSITION_LINK,
-          NavigationInitiationType::RENDERER_INITIATED,
-          /*is_using_https_as_default_scheme=*/false,
+          NavigationInitiationType::RENDERER_INITIATED, HttpsUpgradeType::kNone,
           /*previous_url=*/GURL::EmptyGURL(),
           nullptr /* use default rewriters only */);
       last_committed_web_view_item_->SetUntrusted();
@@ -1176,7 +1171,7 @@
     const Referrer& referrer,
     ui::PageTransition transition,
     NavigationInitiationType initiation_type,
-    bool is_using_https_as_default_scheme,
+    HttpsUpgradeType https_upgrade_type,
     const GURL& previous_url,
     const std::vector<BrowserURLRewriter::URLRewriter>* additional_rewriters)
     const {
@@ -1218,8 +1213,7 @@
   item->SetReferrer(referrer);
   item->SetTransitionType(transition);
   item->SetNavigationInitiationType(initiation_type);
-  if (is_using_https_as_default_scheme)
-    item->SetUpgradedToHttps();
+  item->SetHttpsUpgradeType(https_upgrade_type);
 
   return item;
 }
@@ -1400,8 +1394,7 @@
                                         web::ReferrerPolicyAlways)
                         : web::Referrer()),
           ui::PageTransition::PAGE_TRANSITION_LINK,
-          NavigationInitiationType::RENDERER_INITIATED,
-          /*is_using_https_as_default_scheme=*/false,
+          NavigationInitiationType::RENDERER_INITIATED, HttpsUpgradeType::kNone,
           // Not using GetLastCommittedItem()->GetURL() in case the last
           // committed item in the WKWebView hasn't been linked to a
           // NavigationItem and this method is called in that code path to avoid
diff --git a/ios/web/navigation/navigation_manager_impl_unittest.mm b/ios/web/navigation/navigation_manager_impl_unittest.mm
index e53691f6..b0a306d 100644
--- a/ios/web/navigation/navigation_manager_impl_unittest.mm
+++ b/ios/web/navigation/navigation_manager_impl_unittest.mm
@@ -194,8 +194,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com"];
   navigation_manager()->CommitPendingItem();
@@ -208,8 +207,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com"];
   navigation_manager()->CommitPendingItem();
@@ -217,8 +215,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   EXPECT_EQ(-1, navigation_manager()->GetPendingItemIndex());
 }
 
@@ -227,8 +224,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.test"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.test"];
   navigation_manager()->CommitPendingItem();
 
@@ -241,8 +237,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com"];
   navigation_manager()->CommitPendingItem();
@@ -250,8 +245,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"
                   backListURLs:@[ @"http://www.url.com" ]
@@ -281,8 +275,7 @@
   navigation_manager()->AddPendingItem(
       url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_NE(item.get(), navigation_manager()->GetPendingItem());
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
@@ -295,8 +288,7 @@
   navigation_manager()->AddPendingItem(
       url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.test"];
   navigation_manager()->CommitPendingItem();
   navigation_manager()->SetPendingItemIndex(0);
@@ -322,8 +314,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com"];
   navigation_manager()->CommitPendingItem();
@@ -337,16 +328,14 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com"];
   navigation_manager()->CommitPendingItem();
 
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"
                   backListURLs:@[ @"http://www.url.com" ]
@@ -356,8 +345,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_
         setCurrentURL:@"http://www.url.com/1"
@@ -394,8 +382,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/"];
   navigation_manager()->CommitPendingItem();
 
@@ -408,8 +395,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com"];
   navigation_manager()->CommitPendingItem();
@@ -417,8 +403,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"
                   backListURLs:@[ @"http://www.url.com" ]
@@ -428,8 +413,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_
         setCurrentURL:@"http://www.url.com/1"
@@ -464,8 +448,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -474,8 +457,7 @@
       GURL("http://www.url.com/redirect"), Referrer(),
       ui::PAGE_TRANSITION_CLIENT_REDIRECT,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/redirect"
                   backListURLs:@[ @"http://www.url.com/0" ]
@@ -485,8 +467,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:@[
@@ -498,8 +479,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/2"), Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/2"
                   backListURLs:@[
@@ -513,8 +493,7 @@
       GURL("http://www.url.com/redirect"), Referrer(),
       ui::PAGE_TRANSITION_CLIENT_REDIRECT,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/redirect"
                   backListURLs:@[
@@ -535,33 +514,33 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_EQ(existing_url, navigation_manager()->GetPendingItem()->GetURL());
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 
   GURL new_url1 = GURL("http://www.new1.com");
   navigation_manager()->AddPendingItem(
       new_url1, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_EQ(new_url1, navigation_manager()->GetPendingItem()->GetURL());
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 
   GURL new_url2 = GURL("http://www.new2.com");
   navigation_manager()->AddPendingItem(
       new_url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/true);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kHttpsOnlyMode);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_EQ(new_url2, navigation_manager()->GetPendingItem()->GetURL());
-  EXPECT_TRUE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kHttpsOnlyMode,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 }
 
@@ -573,20 +552,19 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_TYPED));
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
 
   // NavigationManagerImpl assumes that AddPendingItem() is only called for
@@ -600,10 +578,10 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/true);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kHttpsOnlyMode);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
-  EXPECT_TRUE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kHttpsOnlyMode,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
 }
 
 // Tests that when given a pending item, adding a new pending item with the same
@@ -614,38 +592,38 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_TYPED));
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_FORM_SUBMIT,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_FORM_SUBMIT));
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 
   // Try again with a pending item that uses https as the default scheme.
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_FORM_SUBMIT,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/true);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kHttpsOnlyMode);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_FORM_SUBMIT));
-  EXPECT_TRUE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kHttpsOnlyMode,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 }
 
@@ -657,8 +635,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
@@ -669,8 +646,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
 
@@ -689,37 +665,37 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_TYPED));
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_RELOAD,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_RELOAD));
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_RELOAD,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/true);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kHttpsOnlyMode);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_RELOAD));
-  EXPECT_TRUE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kHttpsOnlyMode,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 }
 
@@ -730,8 +706,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   navigation_manager()->GetPendingItem()->SetUserAgentType(
       UserAgentType::DESKTOP);
@@ -740,31 +715,32 @@
       ui::PAGE_TRANSITION_TYPED));
   EXPECT_EQ(web::UserAgentType::DESKTOP,
             navigation_manager()->GetPendingItem()->GetUserAgentType());
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_RELOAD,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_RELOAD));
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_RELOAD,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/true);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kHttpsOnlyMode);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_RELOAD));
-  EXPECT_TRUE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kHttpsOnlyMode,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(0, navigation_manager()->GetItemCount());
 }
 
@@ -775,8 +751,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
   OCMStub([mock_web_view_ URL])
@@ -792,11 +767,11 @@
   navigation_manager()->AddPendingItem(
       new_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_EQ(new_url, navigation_manager()->GetPendingItem()->GetURL());
-  EXPECT_FALSE(navigation_manager()->GetPendingItem()->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone,
+            navigation_manager()->GetPendingItem()->GetHttpsUpgradeType());
   EXPECT_EQ(1, navigation_manager()->GetItemCount());
 }
 
@@ -807,8 +782,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
   OCMStub([mock_web_view_ URL])
@@ -825,8 +799,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   // NavigationManagerImpl assumes that AddPendingItem() is only called for
   // new navigation, so it always creates a new pending item.
@@ -847,8 +820,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
   OCMStub([mock_web_view_ URL])
@@ -866,8 +838,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_FORM_SUBMIT,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_EQ(navigation_manager()->GetPendingItem(),
             navigation_manager()->GetLastCommittedItem());
@@ -884,8 +855,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
   OCMStub([mock_web_view_ URL])
@@ -903,8 +873,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_FORM_SUBMIT,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/true,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/true, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_NE(navigation_manager()->GetPendingItem(),
             navigation_manager()->GetLastCommittedItem());
@@ -920,8 +889,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
   OCMStub([mock_web_view_ URL])
@@ -937,8 +905,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   // NavigationManagerImpl assumes that AddPendingItem() is only called for
   // new navigation, so it always creates a new pending item.
@@ -958,8 +925,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
   OCMStub([mock_web_view_ URL])
@@ -975,8 +941,7 @@
   navigation_manager()->AddPendingItem(
       existing_url, Referrer(), ui::PAGE_TRANSITION_RELOAD,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   EXPECT_EQ(navigation_manager()->GetPendingItem(),
@@ -1008,8 +973,7 @@
   navigation_manager()->AddPendingItem(
       url_before_reload, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_CALL(navigation_manager_delegate(), Reload()).Times(1);
   navigation_manager()->Reload(web::ReloadType::NORMAL,
@@ -1027,8 +991,7 @@
   navigation_manager()->AddPendingItem(
       url_before_reload, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_CALL(navigation_manager_delegate(), Reload()).Times(1);
   navigation_manager()->Reload(web::ReloadType::NORMAL,
@@ -1045,8 +1008,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -1055,8 +1017,7 @@
   navigation_manager()->AddPendingItem(
       url_before_reload, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:@[ @"http://www.url.com/0" ]
@@ -1080,8 +1041,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -1090,8 +1050,7 @@
   navigation_manager()->AddPendingItem(
       url_before_reload, Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:@[ @"http://www.url.com/0" ]
@@ -1101,8 +1060,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/2"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_
         setCurrentURL:@"http://www.url.com/2"
@@ -1143,8 +1101,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   GURL expected_original_url = GURL("http://www.url.com/original");
   navigation_manager()->GetPendingItem()->SetOriginalRequestURL(
@@ -1166,8 +1123,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   GURL expected_original_url = GURL("http://www.url.com/original");
   navigation_manager()->GetPendingItem()->SetOriginalRequestURL(
@@ -1189,8 +1145,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -1198,8 +1153,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   GURL expected_original_url = GURL("http://www.url.com/1/original");
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   navigation_manager()->GetPendingItem()->SetOriginalRequestURL(
@@ -1227,8 +1181,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -1236,8 +1189,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   GURL expected_original_url = GURL("http://www.url.com/1/original");
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
   navigation_manager()->GetPendingItem()->SetOriginalRequestURL(
@@ -1251,8 +1203,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/2"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/2"
                   backListURLs:@[
@@ -1280,8 +1231,7 @@
   navigation_manager()->AddPendingItem(
       url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   GURL virtual_url("http://www.1.com/virtual");
   navigation_manager()->GetPendingItem()->SetVirtualURL(virtual_url);
   [mock_wk_list_ setCurrentURL:@"http://www.1.com"];
@@ -1310,8 +1260,7 @@
   navigation_manager()->AddPendingItem(
       url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.1.com"];
   navigation_manager()->CommitPendingItem();
 
@@ -1319,8 +1268,7 @@
       GURL("http://www.redirect.com"), Referrer(),
       ui::PAGE_TRANSITION_CLIENT_REDIRECT,
       NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/redirect"
                   backListURLs:@[ @"http://www.1.com" ]
                forwardListURLs:nil];
@@ -1341,8 +1289,7 @@
   navigation_manager()->AddPendingItem(
       url, Referrer(), ui::PAGE_TRANSITION_CLIENT_REDIRECT,
       NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.1.com"];
   navigation_manager()->CommitPendingItem();
 
@@ -1362,8 +1309,7 @@
   navigation_manager()->AddPendingItem(
       url, Referrer(), ui::PAGE_TRANSITION_TYPED,
       NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   GURL virtual_url("http://www.1.com/virtual");
   navigation_manager()
       ->GetPendingItemInCurrentOrRestoredSession()
@@ -1387,8 +1333,7 @@
   navigation_manager()->AddPendingItem(
       url1, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   EXPECT_EQ(url1, navigation_manager()->GetPendingItem()->GetURL());
 
   // URL should not be rewritten because last committed URL is not app-specific.
@@ -1399,8 +1344,7 @@
   navigation_manager()->AddPendingItem(
       url2, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   EXPECT_EQ(url2, navigation_manager()->GetPendingItem()->GetURL());
 
   // URL should not be rewritten for user initiated reload navigations.
@@ -1409,8 +1353,7 @@
   navigation_manager()->AddPendingItem(
       url_reload, Referrer(), ui::PAGE_TRANSITION_RELOAD,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   EXPECT_EQ(url_reload, navigation_manager()->GetPendingItem()->GetURL());
 
   // URL should be rewritten for user initiated navigations.
@@ -1418,8 +1361,7 @@
   navigation_manager()->AddPendingItem(
       url3, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   GURL rewritten_url3(
       url::SchemeHostPort(kTestWebUIScheme, "test3", 0).Serialize());
   EXPECT_EQ(rewritten_url3, navigation_manager()->GetPendingItem()->GetURL());
@@ -1434,8 +1376,7 @@
   navigation_manager()->AddPendingItem(
       url4, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   GURL rewritten_url4(
       url::SchemeHostPort(kTestWebUIScheme, "test4", 0).Serialize());
   EXPECT_EQ(rewritten_url4, navigation_manager()->GetPendingItem()->GetURL());
@@ -1447,8 +1388,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   NavigationItem* pending_item = navigation_manager()->GetPendingItem();
   EXPECT_EQ(kRewrittenQueryParam, pending_item->GetURL().query());
@@ -1459,8 +1399,7 @@
   navigation_manager()->AddPendingItem(
       url, Referrer(), ui::PAGE_TRANSITION_LINK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_EQ(url, navigation_manager()->GetPendingItem()->GetURL());
 }
@@ -1478,8 +1417,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   mock_wk_list_.currentItem = wk_item0;
   navigation_manager()->CommitPendingItem();
@@ -1488,8 +1426,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   mock_wk_list_.currentItem = wk_item1;
   mock_wk_list_.backList = @[ wk_item0 ];
@@ -1510,8 +1447,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -1519,8 +1455,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:@[ @"http://www.url.com/0" ]
@@ -1530,8 +1465,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/2"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_
         setCurrentURL:@"http://www.url.com/2"
@@ -1651,8 +1585,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -1660,8 +1593,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:@[ @"http://www.url.com/0" ]
@@ -1671,8 +1603,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/2"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_EQ(1, navigation_manager()->GetLastCommittedItemIndex());
   EXPECT_TRUE(navigation_manager()->GetPendingItem());
@@ -1690,8 +1621,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   ASSERT_TRUE(navigation_manager()->GetVisibleItem());
   EXPECT_EQ("http://www.url.com/0",
@@ -1705,8 +1635,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   ASSERT_TRUE(navigation_manager()->GetVisibleItem());
   EXPECT_EQ("http://www.url.com/1",
@@ -1720,8 +1649,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_EQ(nullptr, navigation_manager()->GetVisibleItem());
 }
@@ -1730,8 +1658,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -1739,8 +1666,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:@[ @"http://www.url.com/0" ]
@@ -1757,8 +1683,7 @@
       GURL("http://www.url.com/0"), Referrer(),
       ui::PAGE_TRANSITION_FORWARD_BACK,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   ASSERT_EQ(0, navigation_manager()->GetPendingItemIndex());
 
   delegate_.SetWebState(&web_state_);
@@ -1779,8 +1704,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -1788,8 +1712,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::RENDERER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   OCMStub([mock_web_view_ URL])
       .andReturn([[NSURL alloc] initWithString:@"http://www.url.com/0"]);
@@ -1833,8 +1756,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
@@ -1861,7 +1783,7 @@
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(pending_item->GetTransitionType(),
                                            ui::PAGE_TRANSITION_TYPED));
   EXPECT_FALSE(pending_item->HasPostData());
-  EXPECT_FALSE(pending_item->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone, pending_item->GetHttpsUpgradeType());
 }
 
 TEST_F(NavigationManagerTest, UpdatePendingItemWithoutPendingItem) {
@@ -1873,8 +1795,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   navigation_manager()->UpdatePendingItemUrl(GURL("http://another.url.com"));
 
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
@@ -1887,8 +1808,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com"];
   navigation_manager()->CommitPendingItem();
@@ -1904,16 +1824,14 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
 
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:@[ @"http://www.url.com/0" ]
                forwardListURLs:nil];
@@ -1937,16 +1855,14 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
 
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0#hash"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   static_cast<NavigationItemImpl*>(navigation_manager()->GetPendingItem())
       ->SetIsCreatedFromHashChange(true);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0#hash"
@@ -1974,8 +1890,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:nil
@@ -2012,14 +1927,12 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.test/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   navigation_manager()->CommitPendingItem();
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.test/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   navigation_manager()->CommitPendingItem();
   SimulateGoToIndex(0);
   mock_wk_list_.backList = @[ mock_wk_list_.currentItem ];
@@ -2068,8 +1981,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   navigation_manager()->CommitPendingItem();
   NavigationItem* last_committed_item =
@@ -2080,8 +1992,7 @@
   navigation_manager()->AddPendingItem(
       GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   NavigationItem* pending_item = navigation_manager()->GetPendingItem();
   ASSERT_NE(pending_item, nullptr);
   EXPECT_EQ(pending_item, navigation_manager()->GetCurrentItemImpl());
@@ -2093,8 +2004,7 @@
       Referrer(GURL("http://referrer.com"), ReferrerPolicyDefault),
       ui::PAGE_TRANSITION_TYPED,
       web::NavigationInitiationType::BROWSER_INITIATED,
-      /*is_post_navigation=*/false,
-      /*is_using_https_as_default_scheme=*/false);
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   // Tests that pending item can be replaced.
   GURL replace_page_url("http://www.url.com/replace");
@@ -2160,7 +2070,7 @@
                                            item->GetTransitionType()));
   EXPECT_EQ(UserAgentType::NONE, item->GetUserAgentType());
   EXPECT_FALSE(item->GetTimestamp().is_null());
-  EXPECT_FALSE(item->IsUpgradedToHttps());
+  EXPECT_EQ(web::HttpsUpgradeType::kNone, item->GetHttpsUpgradeType());
 }
 
 // Tests that Referrer is inferred from the previous WKBackForwardListItem.
@@ -2221,7 +2131,7 @@
   manager_->AddPendingItem(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
                            web::NavigationInitiationType::BROWSER_INITIATED,
                            /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+                           web::HttpsUpgradeType::kNone);
   NavigationItem* pending_item = manager_->GetPendingItem();
   ASSERT_TRUE(pending_item);
   ASSERT_TRUE(web::GetWebClient()->IsAppSpecificURL(pending_item->GetURL()));
@@ -2238,11 +2148,10 @@
 // WKBackForwardList and the pending item NavigationItemImpl will be used.
 TEST_F(NavigationManagerTest, GetItemAtIndexAfterCommitPending) {
   // Simulate a main frame navigation.
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   NavigationItem* pending_item0 = manager_->GetPendingItem();
 
   [mock_wk_list_ setCurrentURL:@"http://www.0.com"];
@@ -2256,11 +2165,10 @@
                                            item->GetTransitionType()));
 
   // Simulate a second main frame navigation.
-  manager_->AddPendingItem(GURL("http://www.2.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.2.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   NavigationItem* pending_item2 = manager_->GetPendingItem();
 
   // Simulate an iframe navigation between the two main frame navigations.
@@ -2310,11 +2218,10 @@
   mock_wk_list_.forwardList = @[ wk_item1 ];
   OCMStub([mock_web_view_ URL])
       .andReturn([[NSURL alloc] initWithString:@"http://www.0.com"]);
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_EQ(original_item0, manager_->GetPendingItem());
 
@@ -2326,21 +2233,19 @@
                   backListURLs:nil
                forwardListURLs:nil];
   original_item0 = manager_->GetItemAtIndex(0);
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_RELOAD,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_RELOAD,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   EXPECT_EQ(original_item0, manager_->GetPendingItem());
 }
 
 // Tests that transient URL rewriters are only applied to a new pending item.
 TEST_F(NavigationManagerTest, TransientURLRewritersOnlyUsedForPendingItem) {
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   // Install transient URL rewriters.
   manager_->AddTransientURLRewriter(&AppendingUrlRewriter);
@@ -2351,21 +2256,19 @@
   EXPECT_EQ(GURL("http://www.0.com"), item0->GetURL());
 
   // Transient URL rewriters are applied to a new pending item.
-  manager_->AddPendingItem(GURL("http://www.2.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.2.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   EXPECT_EQ(kRewrittenQueryParam, manager_->GetPendingItem()->GetURL().query());
 }
 
 // Tests DiscardNonCommittedItems discards pending items.
 TEST_F(NavigationManagerTest, DiscardNonCommittedItems) {
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_NE(nullptr, manager_->GetPendingItem());
 
@@ -2377,18 +2280,16 @@
 TEST_F(NavigationManagerTest, GoBack) {
   ASSERT_FALSE(manager_->CanGoBack());
 
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.0.com"];
 
-  manager_->AddPendingItem(GURL("http://www.1.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.1.com"
                   backListURLs:@[ @"http://www.0.com" ]
                forwardListURLs:nil];
@@ -2407,19 +2308,17 @@
 // Tests that going forward is always delegated to the underlying WKWebView
 // without any sanity checks such as whether any forward history exists.
 TEST_F(NavigationManagerTest, GoForward) {
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.0.com"];
   manager_->CommitPendingItem();
 
-  manager_->AddPendingItem(GURL("http://www.1.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.1.com"
                   backListURLs:@[ @"http://www.0.com" ]
                forwardListURLs:nil];
@@ -2438,19 +2337,17 @@
 
 // Tests that going forward clears uncommitted items.
 TEST_F(NavigationManagerTest, GoForwardShouldDiscardsUncommittedItems) {
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.0.com"];
   manager_->CommitPendingItem();
 
-  manager_->AddPendingItem(GURL("http://www.1.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.1.com"
                   backListURLs:@[ @"http://www.0.com" ]
                forwardListURLs:nil];
@@ -2458,11 +2355,10 @@
   [mock_wk_list_ moveCurrentToIndex:0];
   ASSERT_TRUE(manager_->CanGoForward());
 
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_NE(nullptr, manager_->GetPendingItem());
 
@@ -2479,31 +2375,28 @@
 
 // Tests CanGoToOffset API for positive, negative and zero delta.
 TEST_F(NavigationManagerTest, CanGoToOffset) {
-  manager_->AddPendingItem(GURL("http://www.url.com/0"), Referrer(),
-                           ui::PAGE_TRANSITION_LINK,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_LINK,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   manager_->CommitPendingItem();
 
-  manager_->AddPendingItem(GURL("http://www.url.com/1"), Referrer(),
-                           ui::PAGE_TRANSITION_LINK,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_LINK,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:@[ @"http://www.url.com/0" ]
                forwardListURLs:nil];
   manager_->CommitPendingItem();
 
-  manager_->AddPendingItem(GURL("http://www.url.com/2"), Referrer(),
-                           ui::PAGE_TRANSITION_LINK,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.url.com/2"), Referrer(), ui::PAGE_TRANSITION_LINK,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   [mock_wk_list_
         setCurrentURL:@"http://www.url.com/2"
@@ -2559,11 +2452,10 @@
   [mock_wk_list_ moveCurrentToIndex:1];
   OCMExpect([mock_web_view_ URL])
       .andReturn([[NSURL alloc] initWithString:@"http://www.url.com/1"]);
-  manager_->AddPendingItem(GURL("http://www.url.com/1"), Referrer(),
-                           ui::PAGE_TRANSITION_LINK,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_LINK,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_EQ(3, manager_->GetItemCount());
   EXPECT_EQ(2, manager_->GetLastCommittedItemIndex());
@@ -2625,19 +2517,17 @@
   // Sets up the navigation history with 2 entries, and a pending back-forward
   // navigation so that last_committed_item_index is 1, pending_item_index is 0,
   // and previous_item_index is 0. Basically, none of them is -1.
-  manager_->AddPendingItem(GURL("http://www.url.com/0"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/0"];
   manager_->CommitPendingItem();
 
-  manager_->AddPendingItem(GURL("http://www.url.com/1"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.url.com/1"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   [mock_wk_list_ setCurrentURL:@"http://www.url.com/1"
                   backListURLs:@[ @"http://www.url.com/0" ]
                forwardListURLs:nil];
@@ -2646,11 +2536,10 @@
   [mock_wk_list_ moveCurrentToIndex:0];
   OCMStub([mock_web_view_ URL])
       .andReturn([NSURL URLWithString:@"http://www.url.com/0"]);
-  manager_->AddPendingItem(GURL("http://www.url.com/0"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   EXPECT_EQ(1, manager_->GetLastCommittedItemIndex());
   EXPECT_EQ(0, manager_->GetPendingItemIndex());
@@ -2715,11 +2604,10 @@
       .andReturn(net::NSURLWithGURL(GURL(url::kAboutBlankURL)));
   mock_wk_list_.currentItem = nil;
 
-  manager_->AddPendingItem(GURL(url::kAboutBlankURL), Referrer(),
-                           ui::PAGE_TRANSITION_LINK,
-                           web::NavigationInitiationType::RENDERER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL(url::kAboutBlankURL), Referrer(), ui::PAGE_TRANSITION_LINK,
+      web::NavigationInitiationType::RENDERER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   const NavigationItem* pending_item = manager_->GetPendingItem();
   ASSERT_TRUE(pending_item);
@@ -2755,11 +2643,10 @@
 
   // Add another navigation and verify that it replaces the empty window open
   // item.
-  manager_->AddPendingItem(GURL("http://www.2.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.2.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
 
   const NavigationItem* pending_item_2 = manager_->GetPendingItem();
   ASSERT_TRUE(pending_item_2);
@@ -2980,28 +2867,25 @@
 
 // Tests that pending item is set to serializable when appropriate.
 TEST_F(NavigationManagerDetachedModeTest, NotSerializable) {
-  manager_->AddPendingItem(GURL("http://www.0.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.0.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   EXPECT_FALSE(manager_->GetPendingItemInCurrentOrRestoredSession()
                    ->ShouldSkipSerialization());
 
   manager_->SetWKWebViewNextPendingUrlNotSerializable(GURL("http://www.1.com"));
-  manager_->AddPendingItem(GURL("http://www.1.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   EXPECT_TRUE(manager_->GetPendingItemInCurrentOrRestoredSession()
                   ->ShouldSkipSerialization());
 
-  manager_->AddPendingItem(GURL("http://www.1.com"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   EXPECT_FALSE(manager_->GetPendingItemInCurrentOrRestoredSession()
                    ->ShouldSkipSerialization());
 }
diff --git a/ios/web/navigation/navigation_manager_util_unittest.mm b/ios/web/navigation/navigation_manager_util_unittest.mm
index 1e63a4e..485921d 100644
--- a/ios/web/navigation/navigation_manager_util_unittest.mm
+++ b/ios/web/navigation/navigation_manager_util_unittest.mm
@@ -52,11 +52,10 @@
           /*web_state=*/nullptr, GURL::EmptyGURL(),
           /*has_user_gesture=*/false, ui::PAGE_TRANSITION_TYPED,
           /*is_renderer_initiated=*/false);
-  manager_->AddPendingItem(GURL("http://chromium.org"), Referrer(),
-                           ui::PAGE_TRANSITION_TYPED,
-                           web::NavigationInitiationType::BROWSER_INITIATED,
-                           /*is_post_navigation=*/false,
-                           /*is_using_https_as_default_scheme=*/false);
+  manager_->AddPendingItem(
+      GURL("http://chromium.org"), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      web::NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   NavigationItem* item = manager_->GetPendingItem();
   int unique_id = item->GetUniqueID();
   context->SetNavigationItemUniqueID(item->GetUniqueID());
diff --git a/ios/web/public/navigation/BUILD.gn b/ios/web/public/navigation/BUILD.gn
index f6e1400..6a5e66e 100644
--- a/ios/web/public/navigation/BUILD.gn
+++ b/ios/web/public/navigation/BUILD.gn
@@ -17,6 +17,8 @@
 
   sources = [
     "browser_url_rewriter.h",
+    "https_upgrade_type.h",
+    "https_upgrade_type.mm",
     "navigation_context.h",
     "navigation_item.h",
     "navigation_manager.h",
diff --git a/ios/web/public/navigation/https_upgrade_type.h b/ios/web/public/navigation/https_upgrade_type.h
new file mode 100644
index 0000000..4000f6f
--- /dev/null
+++ b/ios/web/public/navigation/https_upgrade_type.h
@@ -0,0 +1,39 @@
+// 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 IOS_WEB_PUBLIC_NAVIGATION_HTTPS_UPGRADE_TYPE_H_
+#define IOS_WEB_PUBLIC_NAVIGATION_HTTPS_UPGRADE_TYPE_H_
+
+#include <string>
+
+namespace web {
+
+// Used to specify the type of the HTTPS upgrade that was applied on a
+// navigation, if any. Presently, two features can upgrade HTTP navigations to
+// HTTPS:
+// - HTTPS-Only Mode (aka HTTPS-First Mode)
+// - Omnibox navigation upgrades
+//
+// In both cases, the relevant tab helpers need to know whether the upgraded
+// HTTPS navigation failed. They also need to know why the navigation was
+// upgraded in the first place so that they can take the appropriate action to
+// handle the failure case (e.g. by showing an interstitial in HTTPS-Only Mode
+// and by falling back to HTTP in omnibox navigation upgrades).
+enum class HttpsUpgradeType {
+  // The navigation was not upgraded to HTTPS.
+  kNone,
+
+  // Navigation was upgraded to HTTPS by the HTTPS-Only Mode feature.
+  kHttpsOnlyMode,
+
+  // Navigation was upgraded to HTTPS by the omnibox.
+  kOmnibox,
+};
+
+// Returns a string representation of |type|.
+std::string GetHttpsUpgradeTypeDescription(HttpsUpgradeType type);
+
+}  // namespace web
+
+#endif  // IOS_WEB_PUBLIC_NAVIGATION_HTTPS_UPGRADE_TYPE_H_
\ No newline at end of file
diff --git a/ios/web/public/navigation/https_upgrade_type.mm b/ios/web/public/navigation/https_upgrade_type.mm
new file mode 100644
index 0000000..df1a13b
--- /dev/null
+++ b/ios/web/public/navigation/https_upgrade_type.mm
@@ -0,0 +1,26 @@
+// 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 "ios/web/public/navigation/https_upgrade_type.h"
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace web {
+
+std::string GetHttpsUpgradeTypeDescription(HttpsUpgradeType type) {
+  switch (type) {
+    case HttpsUpgradeType::kNone:
+      return "None";
+    case HttpsUpgradeType::kHttpsOnlyMode:
+      return "HttpsOnlyMode";
+    case HttpsUpgradeType::kOmnibox:
+      return "Omnibox";
+  }
+}
+
+}  // namespace web
diff --git a/ios/web/public/navigation/navigation_context.h b/ios/web/public/navigation/navigation_context.h
index b517a0c..508c67da 100644
--- a/ios/web/public/navigation/navigation_context.h
+++ b/ios/web/public/navigation/navigation_context.h
@@ -7,6 +7,7 @@
 
 #import <Foundation/Foundation.h>
 
+#include "ios/web/public/navigation/https_upgrade_type.h"
 #include "ui/base/page_transition_types.h"
 
 class GURL;
@@ -92,10 +93,12 @@
   //  * using window.history.pushState
   virtual bool IsRendererInitiated() const = 0;
 
-  // Returns true if the current navigation is a failed HTTPS upgrade. This
-  // can happen when an HTTP navigation is upgraded to an HTTPS navigation
-  // by the HTTPS-Only mode feature and the HTTPS URL returns an SSL error.
-  virtual bool IsFailedHTTPSUpgrade() const = 0;
+  // Gets the type of the HTTPS upgrade if the current navigation was upgraded
+  // to HTTPS and failed to load. Otherwise, returns kNone. For example, if
+  // the navigation was upgraded to HTTPS by HTTPS-Ony Mode and failed with an
+  // SSL error, this will return kHttpsOnlyMode. If the HTTPS upgrade succeeded,
+  // will return kNone.
+  virtual HttpsUpgradeType GetFailedHttpsUpgradeType() const = 0;
 
   virtual ~NavigationContext() {}
 };
diff --git a/ios/web/public/navigation/navigation_item.h b/ios/web/public/navigation/navigation_item.h
index 600a0ce1..fd558e9f9 100644
--- a/ios/web/public/navigation/navigation_item.h
+++ b/ios/web/public/navigation/navigation_item.h
@@ -11,6 +11,7 @@
 #include "base/supports_user_data.h"
 #include "base/time/time.h"
 #import "ios/web/common/user_agent.h"
+#import "ios/web/public/navigation/https_upgrade_type.h"
 #import "ios/web/public/ui/page_display_state.h"
 #include "ui/base/page_transition_types.h"
 
@@ -129,16 +130,15 @@
   // Existing headers with the same key will be overridden.
   virtual void AddHttpRequestHeaders(NSDictionary* additional_headers) = 0;
 
-  // Returns true if the navigation was typed without a scheme and upgraded
-  // by the omnibox to use https:// as the scheme. (e.g. example.com is
-  // upgraded to https://example.com instead of http://example.com). This has
-  // the same purpose as
-  // ChromeNavigationUIData::is_using_https_as_default_scheme().
-  virtual bool IsUpgradedToHttps() const = 0;
-  // Sets the upgraded bit to true. Called from NavigationManager. Once this bit
-  // is set, it's never reset to false. Navigations defaulting to https but fail
-  // to load end up creating new navigations with this bit cleared.
-  virtual void SetUpgradedToHttps() = 0;
+  // Returns the type of the HTTPS upgrade that was applied to this navigation.
+  // If the navigation wasn't upgraded to HTTPS, returns kNone.
+  virtual HttpsUpgradeType GetHttpsUpgradeType() const = 0;
+  // Sets the type of the HTTPS upgrade that was applied to this navigation. If
+  // no upgrade was applied, should be kNone. This function is called from
+  // NavigationManager. Once this value is set, it's never reset. Navigations
+  // defaulting to https but fail to load end up creating new navigations with
+  // this value cleared.
+  virtual void SetHttpsUpgradeType(HttpsUpgradeType https_upgrade_type) = 0;
 };
 
 }  // namespace web
diff --git a/ios/web/public/navigation/navigation_manager.h b/ios/web/public/navigation/navigation_manager.h
index 60d37531..1365c4a1bb0 100644
--- a/ios/web/public/navigation/navigation_manager.h
+++ b/ios/web/public/navigation/navigation_manager.h
@@ -12,6 +12,7 @@
 #include "base/callback.h"
 #include "ios/web/common/user_agent.h"
 #include "ios/web/public/navigation/browser_url_rewriter.h"
+#include "ios/web/public/navigation/https_upgrade_type.h"
 #include "ios/web/public/navigation/referrer.h"
 #include "ios/web/public/navigation/reload_type.h"
 #include "ui/base/page_transition_types.h"
@@ -59,12 +60,9 @@
     // generally set a Content-Type header as well.
     NSData* post_data;
 
-    // True if the navigation was initiated by typing in the omnibox but the
-    // typed text didn't have a scheme such as http or https (e.g. google.com),
-    // and https was used as the default scheme for the navigation. This is used
-    // by TypedNavigationUpgradeThrottle to determine if the navigation should
-    // be observed and fall back to using http scheme if necessary.
-    bool is_using_https_as_default_scheme;
+    // Indicates the type of the HTTPS upgrade applied on the navigation, if
+    // any.
+    HttpsUpgradeType https_upgrade_type;
 
     // Create a new WebLoadParams with the given URL and defaults for all other
     // parameters.
diff --git a/ios/web/public/test/fakes/fake_navigation_context.h b/ios/web/public/test/fakes/fake_navigation_context.h
index 04b38617..73ebdc5c 100644
--- a/ios/web/public/test/fakes/fake_navigation_context.h
+++ b/ios/web/public/test/fakes/fake_navigation_context.h
@@ -37,7 +37,7 @@
   NSError* GetError() const override;
   net::HttpResponseHeaders* GetResponseHeaders() const override;
   bool IsRendererInitiated() const override;
-  bool IsFailedHTTPSUpgrade() const override;
+  HttpsUpgradeType GetFailedHttpsUpgradeType() const override;
 
   // Setters for navigation context data members.
   void SetWebState(std::unique_ptr<WebState> web_state);
diff --git a/ios/web/public/test/fakes/fake_navigation_context.mm b/ios/web/public/test/fakes/fake_navigation_context.mm
index b31406f..fceb8268 100644
--- a/ios/web/public/test/fakes/fake_navigation_context.mm
+++ b/ios/web/public/test/fakes/fake_navigation_context.mm
@@ -78,8 +78,8 @@
   return renderer_initiated_;
 }
 
-bool FakeNavigationContext::IsFailedHTTPSUpgrade() const {
-  return false;
+web::HttpsUpgradeType FakeNavigationContext::GetFailedHttpsUpgradeType() const {
+  return web::HttpsUpgradeType::kNone;
 }
 
 void FakeNavigationContext::SetWebState(std::unique_ptr<WebState> web_state) {
diff --git a/ios/web/public/test/web_test_with_web_state.mm b/ios/web/public/test/web_test_with_web_state.mm
index 4106cbc..756b3f9d 100644
--- a/ios/web/public/test/web_test_with_web_state.mm
+++ b/ios/web/public/test/web_test_with_web_state.mm
@@ -70,7 +70,7 @@
       .AddPendingItem(url, Referrer(), transition,
                       web::NavigationInitiationType::BROWSER_INITIATED,
                       /*is_post_navigation=*/false,
-                      /*is_using_https_as_default_scheme=*/false);
+                      web::HttpsUpgradeType::kNone);
 }
 
 bool WebTestWithWebState::LoadHtmlWithoutSubresources(const std::string& html) {
diff --git a/ios/web/security/crw_ssl_status_updater_unittest.mm b/ios/web/security/crw_ssl_status_updater_unittest.mm
index 6631ebd..18e9cf9 100644
--- a/ios/web/security/crw_ssl_status_updater_unittest.mm
+++ b/ios/web/security/crw_ssl_status_updater_unittest.mm
@@ -123,8 +123,7 @@
     nav_manager_.AddPendingItem(
         GURL(item_url_spec), Referrer(), ui::PAGE_TRANSITION_LINK,
         web::NavigationInitiationType::BROWSER_INITIATED,
-        /*is_post_navigation=*/false,
-        /*is_using_https_as_default_scheme=*/false);
+        /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
     nav_manager_.CommitPendingItem();
   }
 
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index 969873c63..4d2239c9 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -1300,11 +1300,10 @@
   // Change last committed URL to app-specific URL.
   NavigationManagerImpl& nav_manager =
       [web_controller() webStateImpl]->GetNavigationManagerImpl();
-  nav_manager.AddPendingItem(GURL(kTestAppSpecificURL), Referrer(),
-                             ui::PAGE_TRANSITION_TYPED,
-                             NavigationInitiationType::BROWSER_INITIATED,
-                             /*is_post_navigation=*/false,
-                             /*is_using_https_as_default_scheme=*/false);
+  nav_manager.AddPendingItem(
+      GURL(kTestAppSpecificURL), Referrer(), ui::PAGE_TRANSITION_TYPED,
+      NavigationInitiationType::BROWSER_INITIATED,
+      /*is_post_navigation=*/false, web::HttpsUpgradeType::kNone);
   nav_manager.CommitPendingItem();
 
   NSError* error = nil;
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 2efe5f1..86c251a 100644
--- a/ios/web/web_state/ui/crw_web_request_controller.mm
+++ b/ios/web/web_state/ui/crw_web_request_controller.mm
@@ -310,7 +310,7 @@
         requestURL, referrer, transition,
         rendererInitiated ? web::NavigationInitiationType::RENDERER_INITIATED
                           : web::NavigationInitiationType::BROWSER_INITIATED,
-        isPostNavigation, /*is_using_https_as_default_scheme=*/false);
+        isPostNavigation, web::HttpsUpgradeType::kNone);
     item =
         self.navigationManagerImpl->GetPendingItemInCurrentOrRestoredSession();
   }
diff --git a/ios/web/web_state/web_state_impl_unittest.mm b/ios/web/web_state/web_state_impl_unittest.mm
index 71ca93b..787825e 100644
--- a/ios/web/web_state/web_state_impl_unittest.mm
+++ b/ios/web/web_state/web_state_impl_unittest.mm
@@ -172,8 +172,7 @@
     web_state_->GetNavigationManagerImpl().AddPendingItem(
         GURL::EmptyGURL(), web::Referrer(), ui::PAGE_TRANSITION_LINK,
         NavigationInitiationType::RENDERER_INITIATED,
-        /*is_post_navigation=*/false,
-        /*is_using_https_as_default_scheme=*/false);
+        /*is_post_navigation=*/false, HttpsUpgradeType::kNone);
     web_state_->GetNavigationManagerImpl().CommitPendingItem();
   }
 
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn
index 0637152c..5f56977c 100644
--- a/ipc/BUILD.gn
+++ b/ipc/BUILD.gn
@@ -253,6 +253,8 @@
       "//base/test:test_support",
       "//mojo/core/embedder",
       "//mojo/core/test:test_support",
+      "//third_party/ipcz/src:ipcz_tests_sources_chromium",
+      "//third_party/ipcz/src:test_buildflags",
     ]
   }
 
diff --git a/ipc/DEPS b/ipc/DEPS
index ed7cd79f..d58fa4c1 100644
--- a/ipc/DEPS
+++ b/ipc/DEPS
@@ -21,4 +21,8 @@
     # Support serializing RepeatedField / RepeatedPtrField:
     "+third_party/protobuf/src/google/protobuf/repeated_field.h",
   ],
+  "run_all_unittests\.cc": [
+    "+third_party/ipcz/src/test_buildflags.h",
+    "+third_party/ipcz/src/test/test_child_launcher.h",
+  ],
 }
diff --git a/ipc/SECURITY_OWNERS b/ipc/SECURITY_OWNERS
index b2b27ad..9af1534 100644
--- a/ipc/SECURITY_OWNERS
+++ b/ipc/SECURITY_OWNERS
@@ -1,24 +1,42 @@
-# Changes to IPC messages require a security review to avoid introducing sandbox
-# escapes. The shared memory implementation code needs review from a security
-# owner. (Shared memory call sites should be reviewed as part of normal IPC
-# security review.)
+# Reviewers for security-sensitive CLs that cross process boundaries, e.g.:
 #
-# Security team: If you are uncomfortable reviewing a particular bit of code
-# yourself, don't hesitate to seek help from another security team member!
-# Nobody knows everything, and the only way to learn is from experience.
-ajgo@chromium.org
-danakj@chromium.org
-dcheng@chromium.org
-dominickn@chromium.org
-estark@chromium.org
-joenotcharles@chromium.org
-kenrb@chromium.org
-kinuko@chromium.org
-meacer@chromium.org
-mkwst@chromium.org
-mpdenton@chromium.org
-nasko@chromium.org
-rsesek@chromium.org
-sammc@chromium.org
-tsepez@chromium.org
-wfh@chromium.org
+# - CLs using Mojo IPC  [1]
+# - CLs using legacy IPC [2]
+# - CLs using Android IDL
+#
+# [1] reference: https://docs.google.com/document/d/1Kw4aTuISF7csHnjOpDJGc7JYIjlvOAKRprCTBVWw_E4/edit
+# [2] reference: https://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc/
+#
+# Things like the shared memory implementation in //base also fall under the
+# purview of //ipc/SECURITY_OWNERS (changes that *use* shared memory should
+# already be covered by the standard IPC review process, since the shared
+# memory regions themselves need to be sent over IPC).
+
+# Consider assigning IPC reviews to chrome-ipc-reviews@google.com rather than a
+# specific reviewer. This helps distribute review load and knowledge more evenly
+# amongst the team. Automation will select a random reviewer and reassign the
+# review within ~5 minutes. Googlers can read more about this at go/gwsq-gerrit.
+chrome-ipc-reviews@google.com
+
+# The find-owners plugin does not support groups, so the actual IPC reviewers
+# are listed below but tagged with {LAST_RESORT_SUGGESTION} so that Gerrit will
+# preferentially suggest the review alias above.
+#
+# Please keep this list alphabetized and in sync with the gwsq config (see
+# go/chrome-ipc-review).
+ajgo@chromium.org         #{{LAST_RESORT_SUGGESTION}}
+danakj@chromium.org       #{{LAST_RESORT_SUGGESTION}}
+dcheng@chromium.org       #{{LAST_RESORT_SUGGESTION}}
+dominickn@chromium.org    #{{LAST_RESORT_SUGGESTION}}
+estark@chromium.org       #{{LAST_RESORT_SUGGESTION}}
+joenotcharles@google.com  #{{LAST_RESORT_SUGGESTION}}
+kenrb@chromium.org        #{{LAST_RESORT_SUGGESTION}}
+kinuko@chromium.org       #{{LAST_RESORT_SUGGESTION}}
+meacer@chromium.org       #{{LAST_RESORT_SUGGESTION}}
+mkwst@chromium.org        #{{LAST_RESORT_SUGGESTION}}
+mpdenton@chromium.org     #{{LAST_RESORT_SUGGESTION}}
+nasko@chromium.org        #{{LAST_RESORT_SUGGESTION}}
+rsesek@chromium.org       #{{LAST_RESORT_SUGGESTION}}
+sammc@chromium.org        #{{LAST_RESORT_SUGGESTION}}
+tsepez@chromium.org       #{{LAST_RESORT_SUGGESTION}}
+wfh@chromium.org          #{{LAST_RESORT_SUGGESTION}}
diff --git a/ipc/run_all_unittests.cc b/ipc/run_all_unittests.cc
index 3a57bdde..bfd91e2 100644
--- a/ipc/run_all_unittests.cc
+++ b/ipc/run_all_unittests.cc
@@ -7,11 +7,19 @@
 #include "base/test/multiprocess_test.h"
 #include "base/test/test_io_thread.h"
 #include "base/test/test_suite.h"
-#include "build/build_config.h"
 #include "mojo/core/embedder/embedder.h"
 #include "mojo/core/embedder/scoped_ipc_support.h"
+#include "third_party/ipcz/src/test_buildflags.h"
+
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+#include "third_party/ipcz/src/test/test_child_launcher.h"
+#endif
 
 int main(int argc, char** argv) {
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+  ipcz::test::TestChildLauncher::Initialize(argc, argv);
+#endif
+
   base::TestSuite test_suite(argc, argv);
   mojo::core::Init();
   base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
diff --git a/media/BUILD.gn b/media/BUILD.gn
index c820538..9be78fdd 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -211,16 +211,18 @@
       "//media/fuchsia/video:unittests",
     ]
 
-    use_cfv2 = false
+    use_cfv1 = false
+
+    # TODO(https://crbug.com/1185811): Investigate removing the requirement for
+    # job_policy_ambient_mark_vmo_exec for the sake of V8's allocator in tests.
+    # PaintCanvasVideoRendererWithGLTest.CopyVideoFrameYUVDataToGLTexture
+    # crashes without it.
+    test_runner_shard = "//build/config/fuchsia/test/elf_test_ambient_exec_runner.shard.test-cml"
+
     additional_manifest_fragments = [
-      "//build/config/fuchsia/test/audio_capabilities.test-cmx",
-
-      # TODO(crbug.com/1185811): Figure out why
-      # PaintCanvasVideoRendererWithGLTest.CopyVideoFrameYUVDataToGLTexture
-      # crashes without "deprecated-ambient-replace-as-executable".
-      "//build/config/fuchsia/test/jit_capabilities.test-cmx",
-
-      "//build/config/fuchsia/test/vulkan_capabilities.test-cmx",
+      "//build/config/fuchsia/test/audio_output.shard.test-cml",
+      "//build/config/fuchsia/test/platform_video_codecs.shard.test-cml",
+      "//third_party/fuchsia-sdk/sdk/pkg/vulkan/client.shard.cml",
     ]
   }
 
@@ -281,9 +283,9 @@
   }
 
   if (is_fuchsia) {
-    use_cfv2 = false
+    use_cfv1 = false
     additional_manifest_fragments =
-        [ "//build/config/fuchsia/test/audio_capabilities.test-cmx" ]
+        [ "//build/config/fuchsia/test/audio_output.shard.test-cml" ]
   }
 }
 
diff --git a/media/audio/audio_encoders_unittest.cc b/media/audio/audio_encoders_unittest.cc
index 8db7f1e2..d6fc7216 100644
--- a/media/audio/audio_encoders_unittest.cc
+++ b/media/audio/audio_encoders_unittest.cc
@@ -19,6 +19,7 @@
 #include "media/base/audio_encoder.h"
 #include "media/base/audio_parameters.h"
 #include "media/base/audio_timestamp_helper.h"
+#include "media/base/converting_audio_fifo.h"
 #include "media/base/status.h"
 #include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -182,6 +183,8 @@
     } else {
       NOTREACHED();
     }
+
+    min_number_input_frames_needed_ = frames_per_buffer_;
   }
 
   void InitializeEncoder(
@@ -196,9 +199,10 @@
     bool called_done = false;
     AudioEncoder::EncoderStatusCB done_cb =
         base::BindLambdaForTesting([&](EncoderStatus error) {
-          if (!error.is_ok())
+          if (!error.is_ok()) {
             FAIL() << "Error code: " << EncoderStatusCodeToString(error.code())
                    << "\nError message: " << error.message();
+          }
           called_done = true;
         });
 
@@ -206,6 +210,12 @@
 
     RunLoop();
     EXPECT_TRUE(called_done);
+
+    if (options_.codec == AudioCodec::kOpus) {
+      min_number_input_frames_needed_ =
+          reinterpret_cast<AudioOpusEncoder*>(encoder_.get())
+              ->fifo_->min_number_input_frames_needed_for_testing();
+    }
   }
 
   // Produces an audio data with |num_frames| frames. The produced data is sent
@@ -257,9 +267,10 @@
       EncoderStatus::Codes status_code = EncoderStatus::Codes::kOk) {
     bool flush_done = false;
     auto flush_done_cb = base::BindLambdaForTesting([&](EncoderStatus error) {
-      if (error.code() != status_code)
+      if (error.code() != status_code) {
         FAIL() << "Expected " << EncoderStatusCodeToString(status_code)
                << " but got " << EncoderStatusCodeToString(error.code());
+      }
       flush_done = true;
     });
     encoder()->Flush(std::move(flush_done_cb));
@@ -327,6 +338,7 @@
 
   base::TimeDelta buffer_duration_;
   int frames_per_buffer_;
+  int min_number_input_frames_needed_;
 
   std::unique_ptr<AudioTimestampHelper> expected_duration_helper_;
   base::TimeDelta expected_output_duration_;
@@ -653,7 +665,8 @@
       });
 
   InitializeEncoder(std::move(output_cb));
-  ProduceAudioAndEncode();
+  ProduceAudioAndEncode(base::TimeTicks::Now(),
+                        min_number_input_frames_needed_);
   RunLoop();
 
   ASSERT_GT(extra.size(), 0u);
@@ -702,25 +715,22 @@
 
   base::TimeTicks time;
   int total_frames = 0;
-  while (total_frames < frames_per_buffer_) {
+
+  // Push data until we have a decoded output.
+  while (total_frames < min_number_input_frames_needed_) {
     total_frames += ProduceAudioAndEncode(time);
     time += buffer_duration_;
+
+    RunLoop();
   }
 
-  RunLoop();
+  EXPECT_GE(total_frames, frames_per_buffer_);
+  EXPECT_EQ(1, encode_callback_count);
 
-  // If there are remaining frames in the opus encoder FIFO, we need to flush
-  // them before we destroy the encoder. Also flush any encoders with delays.
-  bool needs_flushing = total_frames > frames_per_buffer_ || EncoderHasDelay();
-
-  if (!EncoderHasDelay())
-    EXPECT_EQ(1, encode_callback_count);
-
-  // Flushing should trigger the encode callback and we should be able to decode
-  // the resulting encoded frames.
-  if (needs_flushing) {
+  // If there is leftover data in the encoder, flush it. We can have leftover
+  // data from needing to push more than |frames_per_buffer_| to get one output.
+  if (total_frames > frames_per_buffer_) {
     FlushAndVerifyStatus();
-
     EXPECT_EQ(2, encode_callback_count);
   }
 
diff --git a/media/audio/audio_opus_encoder.cc b/media/audio/audio_opus_encoder.cc
index 13b9c6f..8337ff0 100644
--- a/media/audio/audio_opus_encoder.cc
+++ b/media/audio/audio_opus_encoder.cc
@@ -14,6 +14,7 @@
 #include "base/time/time.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/channel_mixer.h"
+#include "media/base/converting_audio_fifo.h"
 #include "media/base/encoder_status.h"
 #include "media/base/timestamp_constants.h"
 
@@ -75,97 +76,6 @@
 
 }  // namespace
 
-class AudioOpusEncoder::InputFramesFifo final
-    : public AudioConverter::InputCallback {
- public:
-  explicit InputFramesFifo(AudioConverter* converter) : converter_(converter) {
-    DCHECK(converter_);
-    converter_->AddInput(this);
-  }
-
-  ~InputFramesFifo() override { converter_->RemoveInput(this); }
-
-  // Releases all |inputs_| and resets internal state.
-  void Clear() {
-    inputs_.clear();
-    total_frames_ = 0;
-    front_frame_index_ = 0;
-    is_flushing_ = false;
-  }
-
-  // Add an input into the FIFO.
-  void Push(std::unique_ptr<AudioBus> input_bus) {
-    DCHECK(!is_flushing_);
-
-    total_frames_ += input_bus->frames();
-    inputs_.emplace_back(std::move(input_bus));
-  }
-
-  // Allows underflowing and filling data requests with silence.
-  void Flush() {
-    DCHECK(!is_flushing_);
-    is_flushing_ = true;
-  }
-
-  int frames() { return total_frames_; }
-  bool is_flushing() { return is_flushing_; }
-
-  // AudioConverted::InputCallback:
-  double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) override {
-    int frames_needed = audio_bus->frames();
-    int frames_written = 0;
-
-    // If we aren't flushing, this should only be called if we have enough
-    // frames to completey satisfy the request.
-    DCHECK(is_flushing_ || total_frames_ >= frames_needed);
-
-    // Write until we've fulfilled the request or run out of frames.
-    while (frames_written < frames_needed && total_frames_) {
-      const AudioBus* front = inputs_.front().get();
-
-      int frames_in_front = front->frames() - front_frame_index_;
-      int frames_to_write =
-          std::min(frames_needed - frames_written, frames_in_front);
-
-      front->CopyPartialFramesTo(front_frame_index_, frames_to_write,
-                                 frames_written, audio_bus);
-
-      frames_written += frames_to_write;
-      front_frame_index_ += frames_to_write;
-      total_frames_ -= frames_to_write;
-
-      if (front_frame_index_ == front->frames()) {
-        // We exhausted all frames in the front buffer, remove it.
-        inputs_.pop_front();
-        front_frame_index_ = 0;
-      }
-    }
-
-    // We should only run out of frames if we're flushing.
-    if (frames_written != frames_needed) {
-      DCHECK(is_flushing_);
-      DCHECK(!total_frames_);
-      DCHECK(!inputs_.size());
-      audio_bus->ZeroFramesPartial(frames_written,
-                                   frames_needed - frames_written);
-    }
-
-    return 1.0f;
-  }
-
- private:
-  bool is_flushing_ = false;
-
-  // Index to the first unused frame in |inputs_.front()|.
-  int front_frame_index_ = 0;
-
-  // How many frames are in |inputs_|.
-  int total_frames_ = 0;
-
-  const raw_ptr<AudioConverter> converter_;
-  base::circular_deque<std::unique_ptr<AudioBus>> inputs_;
-};
-
 // TODO: Remove after switching to C++17
 constexpr int AudioOpusEncoder::kMinBitrate;
 
@@ -202,14 +112,14 @@
     return;
   }
 
-  converter_ =
-      std::make_unique<AudioConverter>(input_params_, converted_params_,
-                                       /*disable_fifo=*/false);
+  // Unretained is safe here, because |this| owns |fifo_|.
+  fifo_ = std::make_unique<ConvertingAudioFifo>(
+      input_params_, converted_params_,
+      base::BindRepeating(&AudioOpusEncoder::OnFifoOutput,
+                          base::Unretained(this)));
+
   timestamp_tracker_ =
       std::make_unique<AudioTimestampHelper>(converted_params_.sample_rate());
-  fifo_ = std::make_unique<InputFramesFifo>(converter_.get());
-  converted_audio_bus_ = AudioBus::Create(
-      converted_params_.channels(), converted_params_.frames_per_buffer());
   buffer_.resize(converted_params_.channels() *
                  converted_params_.frames_per_buffer());
   auto status_or_encoder = CreateOpusEncoder();
@@ -219,9 +129,6 @@
   }
 
   opus_encoder_ = std::move(status_or_encoder).value();
-  converter_->PrimeWithSilence();
-  min_input_frames_needed_ = converter_->GetMaxInputFramesRequested(
-      converted_params_.frames_per_buffer());
 
   output_cb_ = BindToCurrentLoop(std::move(output_callback));
   std::move(done_cb).Run(EncoderStatus::Codes::kOk);
@@ -274,31 +181,6 @@
   return extra_data;
 }
 
-std::unique_ptr<AudioBus> AudioOpusEncoder::EnsureExpectedChannelCount(
-    std::unique_ptr<AudioBus> audio_bus) {
-  // No mixing required.
-  if (audio_bus->channels() == input_params_.channels())
-    return audio_bus;
-
-  const int& incoming_channels = audio_bus->channels();
-  if (!mixer_ || mixer_input_params_.channels() != incoming_channels) {
-    // Both the format and the sample rate are unused for mixing, but we still
-    // need to pass a value below.
-    mixer_input_params_.Reset(input_params_.format(),
-                              GuessChannelLayout(incoming_channels),
-                              incoming_channels, input_params_.sample_rate());
-
-    mixer_ = std::make_unique<ChannelMixer>(mixer_input_params_, input_params_);
-  }
-
-  auto mixed_bus =
-      AudioBus::Create(input_params_.channels(), audio_bus->frames());
-
-  mixer_->Transform(audio_bus.get(), mixed_bus.get());
-
-  return mixed_bus;
-}
-
 void AudioOpusEncoder::Encode(std::unique_ptr<AudioBus> audio_bus,
                               base::TimeTicks capture_time,
                               EncoderStatusCB done_cb) {
@@ -317,13 +199,11 @@
   if (timestamp_tracker_->base_timestamp() == kNoTimestamp)
     timestamp_tracker_->SetBaseTimestamp(capture_time - base::TimeTicks());
 
-  fifo_->Push(EnsureExpectedChannelCount(std::move(audio_bus)));
-
-  while (fifo_->frames() >= min_input_frames_needed_ && current_done_cb_)
-    OnEnoughInputFrames();
+  // This might synchronously call OnFifoOutput().
+  fifo_->Push(std::move(audio_bus));
 
   if (current_done_cb_) {
-    // Is |current_done_cb_| is null, it means OnEnoughInputFrames() has already
+    // Is |current_done_cb_| is null, it means OnFifoOutput() has already
     // reported an error.
     std::move(current_done_cb_).Run(EncoderStatus::Codes::kOk);
   }
@@ -341,21 +221,8 @@
 
   current_done_cb_ = std::move(done_cb);
 
-  // Start filling partially fulfilled ProvideInput() calls with silence.
   fifo_->Flush();
 
-  while (fifo_->frames())
-    OnEnoughInputFrames();
-
-  // Clear any excess buffered silence. Re-prime the |converter_|, otherwise
-  // the value of |min_input_frames_needed_| might be wrong for the first calls
-  // to Convert().
-  converter_->Reset();
-  converter_->PrimeWithSilence();
-
-  // Clear the flushing flag.
-  fifo_->Clear();
-
   timestamp_tracker_->SetBaseTimestamp(kNoTimestamp);
   if (current_done_cb_) {
     // Is |current_done_cb_| is null, it means OnFifoOutput() has already
@@ -364,15 +231,9 @@
   }
 }
 
-void AudioOpusEncoder::OnEnoughInputFrames() {
-  // We should have enough frames to satisfy all request, or be in the process
-  // of flushing the |fifo_|.
-  DCHECK(fifo_->frames() >= min_input_frames_needed_ || fifo_->is_flushing());
-
-  // Provides input to the converter from |output_bus| within this scope only.
-  converter_->Convert(converted_audio_bus_.get());
-  converted_audio_bus_->ToInterleaved<Float32SampleTypeTraits>(
-      converted_audio_bus_->frames(), buffer_.data());
+void AudioOpusEncoder::OnFifoOutput(AudioBus* audio_bus) {
+  audio_bus->ToInterleaved<Float32SampleTypeTraits>(audio_bus->frames(),
+                                                    buffer_.data());
 
   std::unique_ptr<uint8_t[]> encoded_data(new uint8_t[kOpusMaxDataBytes]);
   auto result = opus_encode_float(opus_encoder_.get(), buffer_.data(),
diff --git a/media/audio/audio_opus_encoder.h b/media/audio/audio_opus_encoder.h
index 8340a90f..d439c5b 100644
--- a/media/audio/audio_opus_encoder.h
+++ b/media/audio/audio_opus_encoder.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <vector>
 
-#include "base/containers/circular_deque.h"
 #include "media/base/audio_bus.h"
 #include "media/base/audio_converter.h"
 #include "media/base/audio_encoder.h"
@@ -18,6 +17,7 @@
 namespace media {
 
 class ChannelMixer;
+class ConvertingAudioFifo;
 
 using OpusEncoderDeleterType = void (*)(OpusEncoder* encoder_ptr);
 using OwnedOpusEncoder = std::unique_ptr<OpusEncoder, OpusEncoderDeleterType>;
@@ -46,19 +46,16 @@
   static constexpr int kMinBitrate = 6000;
 
  private:
-  class InputFramesFifo;
+  friend class AudioEncodersTest;
 
-  // Called synchronously by Encode() once enough audio frames have been
+  // Called synchronously by |fifo_| once enough audio frames have been
   // buffered in |fifo_|. Calls libopus to do actual encoding.
-  void OnEnoughInputFrames();
+  void OnFifoOutput(AudioBus* audio_bus);
 
   CodecDescription PrepareExtraData();
 
   EncoderStatus::Or<OwnedOpusEncoder> CreateOpusEncoder();
 
-  std::unique_ptr<AudioBus> EnsureExpectedChannelCount(
-      std::unique_ptr<AudioBus> audio_bus);
-
   AudioParameters input_params_;
 
   // Output parameters after audio conversion. This may differ from the input
@@ -66,26 +63,13 @@
   // (See CreateOpusInputParams() in the .cc file for details).
   AudioParameters converted_params_;
 
-  // Minimal amount of frames needed to satisfy one convert call.
-  int min_input_frames_needed_;
-
-  // Sample rate adapter from the input audio to what OpusEncoder desires.
-  // Note: Must outlive |fifo_|.
-  std::unique_ptr<AudioConverter> converter_;
-
-  // Fifo for holding the original input audio before it goes to the
-  // converter.
-  // Note: Must be destroyed before |converter_|.
-  std::unique_ptr<InputFramesFifo> fifo_;
+  std::unique_ptr<ConvertingAudioFifo> fifo_;
 
   // Used to mix incoming Encode() buffers to match the expect input channel
   // count.
   std::unique_ptr<ChannelMixer> mixer_;
   AudioParameters mixer_input_params_;
 
-  // This is the destination AudioBus where the |converter_| teh audio into.
-  std::unique_ptr<AudioBus> converted_audio_bus_;
-
   // Buffer for passing AudioBus data from the converter to the encoder.
   std::vector<float> buffer_;
 
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc
index 245a63c..05674f63 100644
--- a/media/audio/win/audio_low_latency_input_win.cc
+++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -14,6 +14,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/command_line.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -423,6 +424,14 @@
     }
   }
 
+  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+  use_fake_audio_capture_timestamps_ =
+      cmd_line->HasSwitch(switches::kUseFakeAudioCaptureTimestamps);
+  if (use_fake_audio_capture_timestamps_) {
+    SendLogMessage("%s => (WARNING: capture timestamps will be fake)",
+                   __func__);
+  }
+
   // Obtain an IAudioClient interface which enables us to create and initialize
   // an audio stream between an audio application and the audio engine.
   hr = endpoint_device_->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr,
@@ -944,7 +953,9 @@
     }
 
     base::TimeTicks capture_time;
-    if (!timestamp_error_was_detected) {
+    if (use_fake_audio_capture_timestamps_) {
+      capture_time = base::TimeTicks::Now();
+    } else if (!timestamp_error_was_detected) {
       // Use the latest |capture_time_100ns| since it is marked as valid.
       capture_time += base::Microseconds(capture_time_100ns / 10.0);
     }
diff --git a/media/audio/win/audio_low_latency_input_win.h b/media/audio/win/audio_low_latency_input_win.h
index caef8a2..26c7e379 100644
--- a/media/audio/win/audio_low_latency_input_win.h
+++ b/media/audio/win/audio_low_latency_input_win.h
@@ -352,6 +352,13 @@
   // raw (minimal) audio processing mode. Will be empty in most cases.
   std::vector<ABI::Windows::Media::Effects::AudioEffectType> raw_effect_types_;
 
+  // Will be enabled if "--use-fake-audio-capture-timestamps" has been added to
+  // the command line. This mode can be used in situations where the default
+  // capture timestamps are known to be invalid (e.g. for virtual devices) and
+  // must be emulated with local timeticks to ensure a monotonic timestamp
+  // sequence. See crbug.com/1315231 for more details.
+  bool use_fake_audio_capture_timestamps_ = false;
+
   SEQUENCE_CHECKER(sequence_checker_);
 };
 
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index 2485c8e..ac8d570 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -133,6 +133,8 @@
     "container_names.h",
     "content_decryption_module.cc",
     "content_decryption_module.h",
+    "converting_audio_fifo.cc",
+    "converting_audio_fifo.h",
     "crc_16.h",
     "data_buffer.cc",
     "data_buffer.h",
@@ -577,6 +579,7 @@
     "channel_mixer_unittest.cc",
     "channel_mixing_matrix_unittest.cc",
     "container_names_unittest.cc",
+    "converting_audio_fifo_unittest.cc",
     "crc_16_unittest.cc",
     "data_buffer_unittest.cc",
     "decoder_buffer_queue_unittest.cc",
diff --git a/media/base/converting_audio_fifo.cc b/media/base/converting_audio_fifo.cc
new file mode 100644
index 0000000..e74b5a7
--- /dev/null
+++ b/media/base/converting_audio_fifo.cc
@@ -0,0 +1,151 @@
+// 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 "media/base/converting_audio_fifo.h"
+
+#include "media/base/audio_bus.h"
+#include "media/base/audio_converter.h"
+#include "media/base/channel_mixer.h"
+
+namespace media {
+
+ConvertingAudioFifo::ConvertingAudioFifo(
+    const AudioParameters& input_params,
+    const AudioParameters& converted_params,
+    ConvertingAudioFifo::OuputCallback output_callback)
+    : output_callback_(std::move(output_callback)),
+      input_params_(input_params),
+      converted_params_(converted_params),
+      converter_(std::make_unique<AudioConverter>(input_params,
+                                                  converted_params,
+                                                  /*disable_fifo=*/true)) {
+  converter_->AddInput(this);
+  converter_->PrimeWithSilence();
+  min_input_frames_needed_ = converter_->GetMaxInputFramesRequested(
+      converted_params_.frames_per_buffer());
+
+  converted_audio_bus_ = AudioBus::Create(
+      converted_params_.channels(), converted_params_.frames_per_buffer());
+}
+
+ConvertingAudioFifo::~ConvertingAudioFifo() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  converter_->RemoveInput(this);
+}
+
+void ConvertingAudioFifo::Push(std::unique_ptr<AudioBus> input_bus) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!is_flushing_);
+
+  total_frames_ += input_bus->frames();
+  inputs_.emplace_back(EnsureExpectedChannelCount(std::move(input_bus)));
+
+  // Immediately convert frames if we have enough.
+  while (total_frames_ >= min_input_frames_needed_)
+    Convert();
+}
+
+void ConvertingAudioFifo::Convert() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  DCHECK(total_frames_ >= min_input_frames_needed_ || is_flushing_)
+      << "total_frames_=" << total_frames_
+      << ",min_input_frames_needed_=" << min_input_frames_needed_
+      << ",is_flushing_=" << is_flushing_;
+  converter_->Convert(converted_audio_bus_.get());
+  output_callback_.Run(converted_audio_bus_.get());
+}
+
+void ConvertingAudioFifo::Flush() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  is_flushing_ = true;
+
+  // Convert all remaining frames.
+  while (total_frames_)
+    Convert();
+
+  converter_->Reset();
+  converter_->PrimeWithSilence();
+
+  inputs_.clear();
+  total_frames_ = 0;
+  front_frame_index_ = 0;
+  is_flushing_ = false;
+}
+
+double ConvertingAudioFifo::ProvideInput(AudioBus* audio_bus,
+                                         uint32_t frames_delayed) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  int frames_needed = audio_bus->frames();
+  int frames_written = 0;
+
+  // If we aren't flushing, this should only be called if we have enough
+  // frames to completey satisfy the request.
+  DCHECK(is_flushing_ || total_frames_ >= frames_needed)
+      << "is_flushing_=" << is_flushing_ << ",total_frames_=" << total_frames_
+      << ",frames_needed=" << frames_needed;
+
+  // Write until we've fulfilled the request or run out of frames.
+  while (frames_written < frames_needed && total_frames_) {
+    const AudioBus* front = inputs_.front().get();
+
+    int frames_in_front = front->frames() - front_frame_index_;
+    int frames_to_write =
+        std::min(frames_needed - frames_written, frames_in_front);
+
+    front->CopyPartialFramesTo(front_frame_index_, frames_to_write,
+                               frames_written, audio_bus);
+
+    frames_written += frames_to_write;
+    front_frame_index_ += frames_to_write;
+    total_frames_ -= frames_to_write;
+
+    if (front_frame_index_ == front->frames()) {
+      // We exhausted all frames in the front buffer, remove it.
+      inputs_.pop_front();
+      front_frame_index_ = 0;
+    }
+  }
+
+  // We should only run out of frames if we're flushing.
+  if (frames_written != frames_needed) {
+    DCHECK(is_flushing_);
+    DCHECK(!total_frames_);
+    DCHECK(!inputs_.size());
+    audio_bus->ZeroFramesPartial(frames_written,
+                                 frames_needed - frames_written);
+  }
+
+  return 1.0f;
+}
+
+std::unique_ptr<AudioBus> ConvertingAudioFifo::EnsureExpectedChannelCount(
+    std::unique_ptr<AudioBus> audio_bus) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  // No mixing required.
+  if (audio_bus->channels() == input_params_.channels())
+    return audio_bus;
+
+  const int& incoming_channels = audio_bus->channels();
+  if (!mixer_ || mixer_input_params_.channels() != incoming_channels) {
+    // Both the format and the sample rate are unused for mixing, but we still
+    // need to pass a value below.
+    mixer_input_params_.Reset(input_params_.format(),
+                              GuessChannelLayout(incoming_channels),
+                              incoming_channels, input_params_.sample_rate());
+
+    mixer_ = std::make_unique<ChannelMixer>(mixer_input_params_, input_params_);
+  }
+
+  auto mixed_bus =
+      AudioBus::Create(input_params_.channels(), audio_bus->frames());
+
+  mixer_->Transform(audio_bus.get(), mixed_bus.get());
+
+  return mixed_bus;
+}
+
+}  // namespace media
diff --git a/media/base/converting_audio_fifo.h b/media/base/converting_audio_fifo.h
new file mode 100644
index 0000000..4350f6b
--- /dev/null
+++ b/media/base/converting_audio_fifo.h
@@ -0,0 +1,107 @@
+// 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 MEDIA_BASE_CONVERTING_AUDIO_FIFO_H_
+#define MEDIA_BASE_CONVERTING_AUDIO_FIFO_H_
+
+#include "base/callback.h"
+#include "base/containers/circular_deque.h"
+#include "base/sequence_checker.h"
+#include "media/base/audio_converter.h"
+#include "media/base/audio_parameters.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+class AudioBus;
+class ChannelMixer;
+
+// FIFO which uses an AudioConverter to convert input frames into an output
+// format. When enough input frames are pushed into the FIFO, it converts them
+// synchronously, and pushes that output via its |output_callback_|.
+class MEDIA_EXPORT ConvertingAudioFifo final
+    : public AudioConverter::InputCallback {
+ public:
+  using OuputCallback = base::RepeatingCallback<void(AudioBus*)>;
+
+  ConvertingAudioFifo(const AudioParameters& input_params,
+                      const AudioParameters& converted_params,
+                      OuputCallback output_callback);
+
+  ConvertingAudioFifo(const ConvertingAudioFifo&) = delete;
+  ConvertingAudioFifo& operator=(const ConvertingAudioFifo&) = delete;
+
+  ~ConvertingAudioFifo() override;
+
+  // Adds inputs into the FIFO. `input_bus` must have the same sample rate as
+  // |input_params_|, but the number of channels or frames can be different.
+  void Push(std::unique_ptr<AudioBus> input_bus);
+
+  // Forces all remaining frames to be converted, ouputing silence in case there
+  // isn't enough data. Noop if there aren't any available frames.
+  void Flush();
+
+  int min_number_input_frames_needed_for_testing() {
+    return min_input_frames_needed_;
+  }
+
+ private:
+  friend class ConvertingAudioFifoTest;
+
+  // AudioConverter::InputCallback implementation.
+  double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) override;
+
+  // Consumes frames from |inputs_|, converts them to match
+  // |output_params_| fills |dest|.
+  void Convert();
+
+  // Returns an AudioBus with the same number of channels as |input_params_|,
+  // mixing |audio_bus| if necessary.
+  std::unique_ptr<AudioBus> EnsureExpectedChannelCount(
+      std::unique_ptr<AudioBus> audio_bus);
+
+  // Callbacks through which converted frames are delivered.
+  const OuputCallback output_callback_;
+
+  const AudioParameters input_params_;
+  const AudioParameters converted_params_;
+
+  bool is_flushing_ = false;
+
+  // Index to the first unused frame in |inputs_.front()|.
+  int front_frame_index_ = 0;
+
+  // Total number of input frames currently in the FIFO.
+  int total_frames_ = 0;
+
+  // Number of input frames needed to fully fulfill one Convert() call.
+  int min_input_frames_needed_;
+
+  // Used to mix incoming Push()'ed buffers to match the |input_params_|'s
+  // channel count. This is needed because we can receive multiple inputs with
+  // varying channel counts before having the |min_input_frames_needed_|
+  // to satisfy one round of conversions. If we created a new |converter_| each
+  // time the input channel changes, we would risk introducing silence when
+  // flushing (or losing data if we didn't flush).
+  std::unique_ptr<ChannelMixer> mixer_ GUARDED_BY_CONTEXT(sequence_checker_);
+  AudioParameters mixer_input_params_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // Synchronously performs audio conversions.
+  std::unique_ptr<AudioConverter> converter_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // Destination bus for the |converter_|.
+  std::unique_ptr<AudioBus> converted_audio_bus_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // All current input frames.
+  base::circular_deque<std::unique_ptr<AudioBus>> inputs_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  SEQUENCE_CHECKER(sequence_checker_);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_CONVERTING_AUDIO_FIFO_H_
diff --git a/media/base/converting_audio_fifo_unittest.cc b/media/base/converting_audio_fifo_unittest.cc
new file mode 100644
index 0000000..1efff7c8
--- /dev/null
+++ b/media/base/converting_audio_fifo_unittest.cc
@@ -0,0 +1,253 @@
+// 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 "media/base/converting_audio_fifo.h"
+
+#include <stdint.h>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/test/bind.h"
+#include "base/time/time.h"
+#include "media/base/audio_bus.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+constexpr int kDefaultChannels = 2;
+constexpr int kDefaultFrames = 480;
+constexpr int kInputSampleRate = 48000;
+
+struct TestAudioParams {
+  const int channels;
+  const int sample_rate;
+};
+
+const AudioParameters kDefaultParams =
+    AudioParameters(AudioParameters::Format::AUDIO_PCM_LINEAR,
+                    GuessChannelLayout(kDefaultChannels),
+                    kInputSampleRate,
+                    kDefaultFrames);
+
+// The combination of these values should cover all combinationso of up/down
+// sampling/buffering/mixing, relative to a steady input of |kDefaultParams|.
+// This does result in 27 combinations.
+constexpr int kTestChannels[] = {1, 2, 3};
+constexpr int kTestSampleRates[] = {8000, 48000, 647744};
+constexpr int kTestOutputFrames[] = {395, 480, 512};
+
+class ConvertingAudioFifoTest
+    : public ::testing::TestWithParam<std::tuple<int, int, int>> {
+ public:
+  ConvertingAudioFifoTest() = default;
+
+  ConvertingAudioFifoTest(const ConvertingAudioFifoTest&) = delete;
+  ConvertingAudioFifoTest& operator=(const ConvertingAudioFifoTest&) = delete;
+
+  ~ConvertingAudioFifoTest() override = default;
+
+  AudioParameters TestOutputParams() {
+    return AudioParameters(AudioParameters::Format::AUDIO_PCM_LINEAR,
+                           GuessChannelLayout(output_channels()),
+                           output_sample_rate(), output_frames());
+  }
+
+  void CreateFifo(AudioParameters output_params) {
+    DCHECK(!fifo_);
+    fifo_ = std::make_unique<ConvertingAudioFifo>(
+        kDefaultParams, output_params, VerifyOutputCallback(output_params));
+  }
+
+  void PushFrames(int frames, int channels = kDefaultChannels) {
+    DCHECK(frames);
+    DCHECK(channels);
+    fifo_->Push(AudioBus::Create(channels, frames));
+  }
+
+  int min_number_input_frames_needed() {
+    return fifo_->min_input_frames_needed_;
+  }
+
+  int current_frames_in_fifo() { return fifo()->total_frames_; }
+
+  ConvertingAudioFifo* fifo() {
+    DCHECK(fifo_);
+    return fifo_.get();
+  }
+
+  int number_outputs() { return number_outputs_; }
+
+ private:
+  int output_channels() { return std::get<0>(GetParam()); }
+  int output_sample_rate() { return std::get<1>(GetParam()); }
+  int output_frames() { return std::get<2>(GetParam()); }
+
+  ConvertingAudioFifo::OuputCallback VerifyOutputCallback(
+      AudioParameters expected_params) {
+    return base::BindLambdaForTesting(
+        [this, expected_params](AudioBus* audio_bus) {
+          EXPECT_EQ(audio_bus->frames(), expected_params.frames_per_buffer());
+          EXPECT_EQ(audio_bus->channels(), expected_params.channels());
+          ++number_outputs_;
+        });
+  }
+
+  int number_outputs_ = 0;
+  std::unique_ptr<ConvertingAudioFifo> fifo_;
+};
+
+// Verify that construction works as intended.
+TEST_F(ConvertingAudioFifoTest, Construct) {
+  CreateFifo(kDefaultParams);
+  EXPECT_EQ(0, current_frames_in_fifo());
+  EXPECT_EQ(0, number_outputs());
+}
+
+// Verify that flushing an empty FIFO is a noop.
+TEST_F(ConvertingAudioFifoTest, EmptyFlush) {
+  CreateFifo(kDefaultParams);
+
+  fifo()->Flush();
+  EXPECT_EQ(0, current_frames_in_fifo());
+  EXPECT_EQ(0, number_outputs());
+}
+
+// Verify that the fifo can be flushed .
+TEST_F(ConvertingAudioFifoTest, PushFlush) {
+  CreateFifo(kDefaultParams);
+
+  // Push a single frame so the flush won't be a no-op.
+  PushFrames(1);
+  EXPECT_EQ(0, number_outputs());
+  EXPECT_EQ(1, current_frames_in_fifo());
+
+  fifo()->Flush();
+  EXPECT_EQ(1, number_outputs());
+  EXPECT_EQ(0, current_frames_in_fifo());
+}
+
+// Verify that the fifo can be flushed twice in a row.
+TEST_F(ConvertingAudioFifoTest, PushFlushFlush) {
+  CreateFifo(kDefaultParams);
+
+  // Push a single frame so the flush won't be a no-op.
+  PushFrames(1);
+  EXPECT_EQ(0, number_outputs());
+
+  fifo()->Flush();
+  EXPECT_EQ(1, number_outputs());
+
+  fifo()->Flush();
+  EXPECT_EQ(1, number_outputs());
+}
+
+// Verify that the fifo can be flushed twice.
+TEST_P(ConvertingAudioFifoTest, PushFlushTwice) {
+  CreateFifo(TestOutputParams());
+
+  // Push a single frame so the flush won't be a no-op.
+  PushFrames(1);
+  EXPECT_EQ(0, number_outputs());
+
+  fifo()->Flush();
+  EXPECT_EQ(1, number_outputs());
+
+  PushFrames(1);
+  fifo()->Flush();
+  EXPECT_EQ(2, number_outputs());
+}
+
+// Verify that the fifo doesn't output until it has enough frames.
+TEST_P(ConvertingAudioFifoTest, Push_NotEnoughFrames) {
+  CreateFifo(TestOutputParams());
+
+  int total_frames_pushed = 0;
+  int frames_to_push = min_number_input_frames_needed() / 5;
+
+  // Avoid pushing 0 frames.
+  DCHECK(frames_to_push);
+
+  // Push in multiple small batches, but not enough to force an output.
+  while (frames_to_push + total_frames_pushed <
+         min_number_input_frames_needed()) {
+    PushFrames(frames_to_push);
+    total_frames_pushed += frames_to_push;
+    EXPECT_EQ(0, number_outputs());
+    EXPECT_EQ(current_frames_in_fifo(), total_frames_pushed);
+  }
+
+  // One more push should be enough for a conversion.
+  PushFrames(frames_to_push);
+  EXPECT_EQ(1, number_outputs());
+
+  EXPECT_LT(current_frames_in_fifo(), min_number_input_frames_needed());
+
+  // Flush for added test coverage.
+  fifo()->Flush();
+}
+
+// Verify that the fifo outputs immediately if it has enough frames.
+TEST_P(ConvertingAudioFifoTest, Push_EnoughFrames) {
+  CreateFifo(TestOutputParams());
+
+  // Push enough frames to trigger an single output.
+  PushFrames(min_number_input_frames_needed());
+  EXPECT_EQ(1, number_outputs());
+}
+
+// Verify that the fifo produces more than one output if it has enough frames.
+TEST_P(ConvertingAudioFifoTest, Push_MoreThanEnoughFrames) {
+  CreateFifo(TestOutputParams());
+
+  // Push enough frames to trigger multiple outputs.
+  PushFrames(min_number_input_frames_needed() * 5);
+  EXPECT_GE(number_outputs(), 5);
+
+  // There should not be enough frames leftover to create a new output.
+  EXPECT_LT(current_frames_in_fifo(), min_number_input_frames_needed());
+}
+
+// Verify that the fifo can handle variable numbers of input frames.
+TEST_P(ConvertingAudioFifoTest, Push_VaryingFrames) {
+  CreateFifo(TestOutputParams());
+
+  int base_frame_count = min_number_input_frames_needed() / 4;
+  constexpr int kFrameVariations[] = {-3, 13, -10, 18};
+
+  // Push a varying amount of frames into |fifo_|.
+  for (const int& variation : kFrameVariations)
+    PushFrames(base_frame_count + variation);
+
+  // We should still get one output.
+  EXPECT_EQ(1, number_outputs());
+}
+
+// Verify that the fifo can handle variable numbers of input channels.
+TEST_P(ConvertingAudioFifoTest, Push_VaryingChannels) {
+  CreateFifo(TestOutputParams());
+
+  // Superpermutation of {1, 2, 3}, covering all transitions between upmixing,
+  // downmixing and not mixing.
+  const int kChannelCountSequence[] = {1, 2, 3, 1, 2, 2, 1, 3, 2, 1};
+
+  // Push frames with variable channels into |fifo_|.
+  for (const int& channels : kChannelCountSequence)
+    PushFrames(kDefaultFrames, channels);
+
+  // Flush to make sure we consume the frames.
+  fifo()->Flush();
+  EXPECT_GT(number_outputs(), 1);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    ConvertingAudioFifoTest,
+    ConvertingAudioFifoTest,
+    testing::Combine(testing::ValuesIn(kTestChannels),
+                     testing::ValuesIn(kTestSampleRates),
+                     testing::ValuesIn(kTestOutputFrames)));
+
+}  // namespace media
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 566f175..4414405 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -72,6 +72,12 @@
 
 // Number of buffers to use for WaveOut.
 const char kWaveOutBuffers[] = "waveout-buffers";
+
+// Emulates audio capture timestamps instead of using timestamps from the actual
+// audio device.
+// See crbug.com/1315231 for more details.
+const char kUseFakeAudioCaptureTimestamps[] =
+    "use-fake-audio-capture-timestamps";
 #endif  // BUILDFLAG(IS_WIN)
 
 #if BUILDFLAG(IS_FUCHSIA)
@@ -263,14 +269,8 @@
                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enable Picture-in-Picture.
-const base::Feature kPictureInPicture {
-  "PictureInPicture",
-#if BUILDFLAG(IS_ANDROID)
-      base::FEATURE_DISABLED_BY_DEFAULT
-#else
-      base::FEATURE_ENABLED_BY_DEFAULT
-#endif
-};
+const base::Feature kPictureInPicture{"PictureInPicture",
+                                      base::FEATURE_ENABLED_BY_DEFAULT};
 
 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
 // Enables HEVC hardware accelerated decoding.
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 54842af2..0f87c18d 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -48,6 +48,7 @@
 MEDIA_EXPORT extern const char kForceWaveAudio[];
 MEDIA_EXPORT extern const char kTrySupportedChannelLayouts[];
 MEDIA_EXPORT extern const char kWaveOutBuffers[];
+MEDIA_EXPORT extern const char kUseFakeAudioCaptureTimestamps[];
 #endif
 
 #if BUILDFLAG(IS_FUCHSIA)
diff --git a/media/capture/mojom/video_capture.mojom b/media/capture/mojom/video_capture.mojom
index a17142ad..fbbb8577 100644
--- a/media/capture/mojom/video_capture.mojom
+++ b/media/capture/mojom/video_capture.mojom
@@ -81,6 +81,9 @@
   // The buffer handle previously registered for |buffer_id| via OnNewBuffer(),
   // is no longer going to be used by the Browser/Host.
   OnBufferDestroyed(int32 buffer_id);
+
+  // All subsequent buffers are guaranteed to have this crop-version or higher.
+  OnNewCropVersion(uint32 crop_version);
 };
 
 interface VideoCaptureHost {
diff --git a/media/capture/video/mock_video_frame_receiver.h b/media/capture/video/mock_video_frame_receiver.h
index 37e0fc8..6582fc0 100644
--- a/media/capture/video/mock_video_frame_receiver.h
+++ b/media/capture/video/mock_video_frame_receiver.h
@@ -26,6 +26,7 @@
   MOCK_METHOD1(OnError, void(media::VideoCaptureError error));
   MOCK_METHOD1(OnFrameDropped, void(media::VideoCaptureFrameDropReason reason));
   MOCK_METHOD0(OnFrameWithEmptyRegionCapture, void());
+  MOCK_METHOD1(OnNewCropVersion, void(uint32_t));
   MOCK_METHOD1(OnLog, void(const std::string& message));
   MOCK_METHOD1(OnBufferRetired, void(int buffer_id));
   MOCK_METHOD0(OnStarted, void());
diff --git a/media/capture/video/video_frame_receiver.h b/media/capture/video/video_frame_receiver.h
index dfe6998..3b79b2e 100644
--- a/media/capture/video/video_frame_receiver.h
+++ b/media/capture/video/video_frame_receiver.h
@@ -92,6 +92,7 @@
 
   virtual void OnError(VideoCaptureError error) = 0;
   virtual void OnFrameDropped(VideoCaptureFrameDropReason reason) = 0;
+  virtual void OnNewCropVersion(uint32_t crop_version) = 0;
   virtual void OnFrameWithEmptyRegionCapture() = 0;
   virtual void OnLog(const std::string& message) = 0;
   virtual void OnStarted() = 0;
diff --git a/media/capture/video/video_frame_receiver_on_task_runner.cc b/media/capture/video/video_frame_receiver_on_task_runner.cc
index 527d389e6..37605ab 100644
--- a/media/capture/video/video_frame_receiver_on_task_runner.cc
+++ b/media/capture/video/video_frame_receiver_on_task_runner.cc
@@ -53,6 +53,12 @@
       base::BindOnce(&VideoFrameReceiver::OnFrameDropped, receiver_, reason));
 }
 
+void VideoFrameReceiverOnTaskRunner::OnNewCropVersion(uint32_t crop_version) {
+  task_runner_->PostTask(FROM_HERE,
+                         base::BindOnce(&VideoFrameReceiver::OnNewCropVersion,
+                                        receiver_, crop_version));
+}
+
 void VideoFrameReceiverOnTaskRunner::OnFrameWithEmptyRegionCapture() {
   task_runner_->PostTask(
       FROM_HERE,
diff --git a/media/capture/video/video_frame_receiver_on_task_runner.h b/media/capture/video/video_frame_receiver_on_task_runner.h
index 260d328..8204bf97a 100644
--- a/media/capture/video/video_frame_receiver_on_task_runner.h
+++ b/media/capture/video/video_frame_receiver_on_task_runner.h
@@ -31,6 +31,7 @@
   void OnBufferRetired(int buffer_id) override;
   void OnError(VideoCaptureError error) override;
   void OnFrameDropped(VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnLog(const std::string& message) override;
   void OnStarted() override;
diff --git a/media/formats/hls/media_playlist_unittest.cc b/media/formats/hls/media_playlist_unittest.cc
index a5729a13..dd82754 100644
--- a/media/formats/hls/media_playlist_unittest.cc
+++ b/media/formats/hls/media_playlist_unittest.cc
@@ -1240,6 +1240,21 @@
   fork.ExpectPlaylist(CanBlockReload, false);
   fork.ExpectOk();
 
+  // The 'HOLD-BACK' attribute must be at least three times the playlist's
+  // target duration
+  fork = builder;
+  fork.AppendLine("#EXT-X-SERVER-CONTROL:HOLD-BACK=18");
+  fork.ExpectPlaylist(HasHoldBackDistance, base::Seconds(18));
+  fork.ExpectOk();
+
+  fork = builder;
+  fork.AppendLine("#EXT-X-SERVER-CONTROL:HOLD-BACK=17");
+  fork.ExpectError(ParseStatusCode::kHoldBackDistanceTooLow);
+
+  fork = builder;
+  fork.AppendLine("#EXT-X-SERVER-CONTROL:HOLD-BACK=17.999");
+  fork.ExpectError(ParseStatusCode::kHoldBackDistanceTooLow);
+
   // The 'EXT-X-PART-INF' tag requires the 'PART-HOLD-BACK' field
   fork = builder;
   fork.AppendLine("#EXT-X-PART-INF:PART-TARGET=0.2");
diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn
index 1223202..a4a0d4d 100644
--- a/media/gpu/v4l2/BUILD.gn
+++ b/media/gpu/v4l2/BUILD.gn
@@ -7,6 +7,7 @@
 import("//build/config/ui.gni")
 import("//media/gpu/args.gni")
 import("//testing/test.gni")
+import("//third_party/libgav1/options.gni")
 import("//tools/generate_stubs/rules.gni")
 import("//ui/gl/features.gni")
 
@@ -177,6 +178,9 @@
     "//media",
     "//media:test_support",
     "//media/gpu:common",
-    "//third_party/libgav1:libgav1",
   ]
+
+  if (enable_libgav1_decoder || use_libgav1_parser) {
+    deps += [ "//third_party/libgav1:libgav1" ]
+  }
 }
diff --git a/media/gpu/vaapi/vaapi_unittest.cc b/media/gpu/vaapi/vaapi_unittest.cc
index 1df3d34..1a83c74 100644
--- a/media/gpu/vaapi/vaapi_unittest.cc
+++ b/media/gpu/vaapi/vaapi_unittest.cc
@@ -285,84 +285,6 @@
   return output;
 }
 
-int PictureBoundToInt(std::string picture_bound) {
-  const std::vector<std::string> split_bound = base::SplitString(
-      picture_bound, ":", base::WhitespaceHandling::TRIM_WHITESPACE,
-      base::SplitResult::SPLIT_WANT_ALL);
-  if (split_bound.size() != 2) {
-    LOG(ERROR) << "Unexpected picture bound line: " << picture_bound;
-    return -1;
-  }
-  const std::string bound = split_bound[1];
-  return atoi(bound.c_str());
-}
-
-bool isIntelDriver() {
-  const auto implementation = VaapiWrapper::GetImplementationType();
-  return implementation == VAImplementation::kIntelI965 ||
-         implementation == VAImplementation::kIntelIHD;
-}
-
-// Returns a map of strings of the form "VAProfileInfo/VAEntrypoint" to a map,
-// which itself maps Bitrate::Mode to the gfx::Size resolution supported for
-// that mode.
-std::map<std::string, std::map<Bitrate::Mode, gfx::Size>> ParseVerboseVainfo(
-    const std::string& output) {
-  const std::vector<std::string> lines =
-      base::SplitString(output, "\n", base::WhitespaceHandling::TRIM_WHITESPACE,
-                        base::SplitResult::SPLIT_WANT_ALL);
-  std::map<std::string, std::map<Bitrate::Mode, gfx::Size>> info;
-  std::string current_profile = "";
-  std::vector<Bitrate::Mode> supported_modes;
-  gfx::Size resolution;
-  bool current_attrib_rate_control = false;
-  for (const std::string& line : lines) {
-    if (base::StartsWith(line, "VAProfile",
-                         base::CompareCase::INSENSITIVE_ASCII)) {
-      current_profile = line;
-      // Reset tracking.
-      supported_modes = {};
-      resolution = gfx::Size();
-      current_attrib_rate_control = false;
-      continue;
-    }
-
-    if (base::StartsWith(line, "VAConfigAttrib")) {
-      if (base::StartsWith(line, "VAConfigAttribRateControl"))
-        current_attrib_rate_control = true;
-      else
-        current_attrib_rate_control = false;
-    }
-
-    if (current_attrib_rate_control) {
-      const std::vector<std::string> split_line =
-          base::SplitString(line, base::kWhitespaceASCII,
-                            base::WhitespaceHandling::TRIM_WHITESPACE,
-                            base::SplitResult::SPLIT_WANT_ALL);
-      for (const std::string& part : split_line) {
-        if (part == "VA_RC_CBR")
-          supported_modes.push_back(Bitrate::Mode::kConstant);
-        else if (part == "VA_RC_VBR")
-          supported_modes.push_back(Bitrate::Mode::kVariable);
-      }
-    }
-
-    // TODO(https://github.com/intel/libva/issues/603): Also check minimum
-    // resolution.
-    if (base::StartsWith(line, "VAConfigAttribMaxPicture")) {
-      if (base::StartsWith(line, "VAConfigAttribMaxPictureWidth"))
-        resolution.set_width(PictureBoundToInt(line));
-      if (base::StartsWith(line, "VAConfigAttribMaxPictureHeight"))
-        resolution.set_height(PictureBoundToInt(line));
-
-      for (auto const& mode : supported_modes) {
-        info[current_profile][mode] = resolution;
-      }
-    }
-  }
-  return info;
-}
-
 std::map<VAProfile, std::vector<VAEntrypoint>> RetrieveVAInfoOutput() {
   std::vector<std::string> argv = {"vainfo"};
   std::string output = GetVaInfo(argv);
@@ -419,29 +341,52 @@
   }
 }
 
-// Verifies that the resolutions of profiles for VBR and CBR are the same as
-// reported by vainfo.
+// Verifies that the resolutions of profiles for VBR and CBR are the same.
 TEST_F(VaapiTest, VbrAndCbrResolutionsMatch) {
-  // TODO(crbug.com/1334880): make a test that works on all platforms
-  if (!isIntelDriver()) {
-    GTEST_SKIP()
-        << "Non-Intel drivers do not output resolution in vainfo -a; skipping";
+  struct ResolutionInfo {
+    VaapiWrapper::CodecMode mode;
+    gfx::Size min;
+    gfx::Size max;
+  };
+  std::map<VAProfile, std::vector<ResolutionInfo>> supported_resolutions;
+  for (const VaapiWrapper::CodecMode codec_mode :
+       {VaapiWrapper::kEncodeConstantBitrate,
+        VaapiWrapper::kEncodeConstantQuantizationParameter,
+        VaapiWrapper::kEncodeVariableBitrate}) {
+    const std::map<VAProfile, std::vector<VAEntrypoint>> configurations =
+        VaapiWrapper::GetSupportedConfigurationsForCodecModeForTesting(
+            codec_mode);
+    for (const auto& configuration : configurations) {
+      const VAProfile va_profile = configuration.first;
+      ResolutionInfo res_info{.mode = codec_mode};
+      ASSERT_TRUE(VaapiWrapper::GetSupportedResolutions(
+          va_profile, codec_mode, res_info.min, res_info.max))
+          << " Failed get resolutions: "
+          << "profile=" << va_profile << ", mode=" << codec_mode;
+
+      supported_resolutions[va_profile].push_back(res_info);
+    }
   }
 
-  std::vector<std::string> argv = {"vainfo", "-a"};
-  std::string output = GetVaInfo(argv);
+  for (const auto& r : supported_resolutions) {
+    const VAProfile va_profile = r.first;
+    const auto& resolution_info = r.second;
 
-  const auto resolution_map = ParseVerboseVainfo(output);
-
-  for (const auto& resolution_info : resolution_map) {
-    const std::string profile_and_entrypoint = resolution_info.first;
-    const std::map<Bitrate::Mode, gfx::Size>& mode_and_resolution =
-        resolution_info.second;
-    if (mode_and_resolution.count(Bitrate::Mode::kConstant) == 1 &&
-        mode_and_resolution.count(Bitrate::Mode::kVariable) == 1) {
-      EXPECT_EQ(mode_and_resolution.at(Bitrate::Mode::kConstant),
-                mode_and_resolution.at(Bitrate::Mode::kVariable))
-          << "Resolution mismatch for " << profile_and_entrypoint;
+    for (size_t i = 0; i < resolution_info.size(); ++i) {
+      for (size_t j = i + 1; j < resolution_info.size(); ++j) {
+        EXPECT_EQ(resolution_info[i].min, resolution_info[j].min)
+            << " Minimum supported resolution mismatch for profile="
+            << VAProfileToString(va_profile) << ": " << resolution_info[i].mode
+            << " (" << resolution_info[i].min.ToString() << ") and "
+            << resolution_info[j].mode << " ("
+            << resolution_info[j].min.ToString() << ")";
+        EXPECT_EQ(resolution_info[i].max, resolution_info[j].max)
+            << " Maximum supported resolution mismatch for profile="
+            << VAProfileToString(va_profile) << ": " << resolution_info[i].mode
+            << " (" << resolution_info[i].max.ToString() << ") and "
+            << resolution_info[j].mode << " ("
+            << resolution_info[j].max.ToString() << ")";
+      }
     }
   }
 }
diff --git a/media/video/openh264_video_encoder.cc b/media/video/openh264_video_encoder.cc
index 23142af..3fe94ce 100644
--- a/media/video/openh264_video_encoder.cc
+++ b/media/video/openh264_video_encoder.cc
@@ -28,6 +28,7 @@
   params->iComplexityMode = MEDIUM_COMPLEXITY;
   params->iUsageType = CAMERA_VIDEO_REAL_TIME;
   params->bEnableDenoise = false;
+  params->eSpsPpsIdStrategy = SPS_LISTING;
   // Set to 1 due to https://crbug.com/583348
   params->iMultipleThreadIdc = 1;
   if (options.framerate.has_value())
diff --git a/mojo/public/cpp/test_support/test_utils.h b/mojo/public/cpp/test_support/test_utils.h
index 6247c52..327cdf9 100644
--- a/mojo/public/cpp/test_support/test_utils.h
+++ b/mojo/public/cpp/test_support/test_utils.h
@@ -139,6 +139,8 @@
     std::ignore = receiver_.SwapImplForTesting(old_impl_);
   }
 
+  ImplPointerType old_impl() const { return old_impl_; }
+
   ScopedSwapImplForTesting(const ScopedSwapImplForTesting&) = delete;
   ScopedSwapImplForTesting& operator=(const ScopedSwapImplForTesting&) = delete;
 
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl
index eba234e..7df521e 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl
@@ -34,7 +34,7 @@
 
 void {{struct.name}}::WriteIntoTrace(
     perfetto::TracedValue traced_context) const {
-  auto dict = std::move(traced_context).WriteDictionary();
+  [[maybe_unused]] auto dict = std::move(traced_context).WriteDictionary();
 {%-  for field in struct.fields %}
   perfetto::WriteIntoTracedValueWithFallback(
     dict.AddItem(
diff --git a/net/cert/internal/trust_store_mac_unittest.cc b/net/cert/internal/trust_store_mac_unittest.cc
index 2ac15591..d71c3250 100644
--- a/net/cert/internal/trust_store_mac_unittest.cc
+++ b/net/cert/internal/trust_store_mac_unittest.cc
@@ -358,7 +358,15 @@
                                               kSecTrustOptionAllowExpiredRoot));
 
       if (trust_domains == TrustStoreMac::TrustDomains::kUserAndAdmin &&
-          !find_certificate_default_search_list_certs.count(cert_der)) {
+          find_certificate_default_search_list_certs.count(cert_der) &&
+          find_certificate_system_roots_certs.count(cert_der)) {
+        // If the same certificate is present in both the System and User/Admin
+        // domains, and TrustStoreMac is only using trust settings from
+        // User/Admin, then it's not possible for this test to know whether the
+        // result from SecTrustEvaluate should match the TrustStoreMac result.
+        // Just ignore such certificates.
+      } else if (trust_domains == TrustStoreMac::TrustDomains::kUserAndAdmin &&
+                 !find_certificate_default_search_list_certs.count(cert_der)) {
         EXPECT_FALSE(is_trust_anchor);
       } else {
         SecTrustResultType trust_result;
diff --git a/net/docs/bug-triage.md b/net/docs/bug-triage.md
index 45780fc..1db4d62 100644
--- a/net/docs/bug-triage.md
+++ b/net/docs/bug-triage.md
@@ -8,7 +8,7 @@
 ## 1. Review untriaged bugs
 
 Look through [this list of untriaged
-bugs](https://bugs.chromium.org/p/chromium/issues/list?sort=pri%20-stars%20-opened&q=status%3Aunconfirmed%2Cuntriaged%20-Needs%3DFeedback%20-Label%3ANetwork-Triaged%20-has%3ANextAction%20component%3DInternals%3ENetwork%2CInternals%3ENetwork%3ECache%2CInternals%3ENetwork%3ESSL%2CInternals%3ENetwork%3EQUIC%2CInternals%3ENetwork%3EAuth%2CInternals%3ENetwork%3EHTTP2%2CInternals%3ENetwork%3EProxy%2CInternals%3ENetwork%3ELibrary%2CInternals%3ENetwork%3ELogging%2CInternals%3ENetwork%3EConnectivity%2CInternals%3ENetwork%3EDomainSecurityPolicy%2CInternals%3ENetwork%3EFTP).
+bugs](https://bugs.chromium.org/p/chromium/issues/list?sort=pri%20-stars%20-opened&q=status%3Aunconfirmed%2Cuntriaged%20-Needs%3DFeedback%20-Label%3ANetwork-Triaged%20-has%3ANextAction%20component%3DInternals%3ENetwork%2CInternals%3ENetwork%3ECache%2CInternals%3ENetwork%3ESSL%2CInternals%3ENetwork%3EQUIC%2CInternals%3ENetwork%3EAuth%2CInternals%3ENetwork%3EHTTP2%2CInternals%3ENetwork%3EProxy%2CInternals%3ENetwork%3ELibrary%2CInternals%3ENetwork%3ELogging%2CInternals%3ENetwork%3EConnectivity%2CInternals%3ENetwork%3EDomainSecurityPolicy%2CInternals%3ENetwork%3EFTP%2CInternals%3ENetwork%3EDNS).
 
 The goal is for this query to be empty. Bugs can be removed from the triage queue
 by doing any of the following:
@@ -72,7 +72,7 @@
 ## 2. Follow-up on issues with the Needs-Feedback label
 
 Look through [this list of Needs=Feedback
-bugs](https://bugs.chromium.org/p/chromium/issues/list?sort=-modified%20-modified&q=Needs%3DFeedback%20component%3DInternals%3ENetwork%2CInternals%3ENetwork%3ECache%2CInternals%3ENetwork%3ESSL%2CInternals%3ENetwork%3EQUIC%2CInternals%3ENetwork%3EAuth%2CInternals%3ENetwork%3EHTTP2%2CInternals%3ENetwork%3EProxy%2CInternals%3ENetwork%3ELibrary%2CInternals%3ENetwork%3ELogging%2CInternals%3ENetwork%3EConnectivity%2CInternals%3ENetwork%3EDomainSecurityPolicy%2CInternals%3ENetwork%3EFTP).
+bugs](https://bugs.chromium.org/p/chromium/issues/list?sort=-modified%20-modified&q=Needs%3DFeedback%20component%3DInternals%3ENetwork%2CInternals%3ENetwork%3ECache%2CInternals%3ENetwork%3ESSL%2CInternals%3ENetwork%3EQUIC%2CInternals%3ENetwork%3EAuth%2CInternals%3ENetwork%3EHTTP2%2CInternals%3ENetwork%3EProxy%2CInternals%3ENetwork%3ELibrary%2CInternals%3ENetwork%3ELogging%2CInternals%3ENetwork%3EConnectivity%2CInternals%3ENetwork%3EDomainSecurityPolicy%2CInternals%3ENetwork%3EFTP%2CInternals%3ENetwork%3EDNS).
 
 * If the requested feedback was provided, review the new information and repeat
   the same steps as (1) to re-triage based on the new information.
@@ -82,7 +82,7 @@
 ## 3. Ensure P0 and P1 bugs have an owner
 
 Look through [the list of unowned high priority
-bugs](https://bugs.chromium.org/p/chromium/issues/list?sort=pri%20-stars%20-opened&q=Pri%3A0%2C1%20-has%3Aowner%20-label%3ANetwork-Triaged%20component%3DInternals%3ENetwork%2CInternals%3ENetwork%3ECache%2CInternals%3ENetwork%3ESSL%2CInternals%3ENetwork%3EQUIC%2CInternals%3ENetwork%3EAuth%2CInternals%3ENetwork%3EHTTP2%2CInternals%3ENetwork%3EProxy%2CInternals%3ENetwork%3ELibrary%2CInternals%3ENetwork%3ELogging%2CInternals%3ENetwork%3EConnectivity%2CInternals%3ENetwork%3EDomainSecurityPolicy%2CInternals%3ENetwork%3EFTP).
+bugs](https://bugs.chromium.org/p/chromium/issues/list?sort=pri%20-stars%20-opened&q=Pri%3A0%2C1%20-has%3Aowner%20-label%3ANetwork-Triaged%20component%3DInternals%3ENetwork%2CInternals%3ENetwork%3ECache%2CInternals%3ENetwork%3ESSL%2CInternals%3ENetwork%3EQUIC%2CInternals%3ENetwork%3EAuth%2CInternals%3ENetwork%3EHTTP2%2CInternals%3ENetwork%3EProxy%2CInternals%3ENetwork%3ELibrary%2CInternals%3ENetwork%3ELogging%2CInternals%3ENetwork%3EConnectivity%2CInternals%3ENetwork%3EDomainSecurityPolicy%2CInternals%3ENetwork%3EFTP%2CInternals%3ENetwork%3EDNS).
 These bugs should either have an owner, or be downgraded to a lower priority.
 
 ## 4. (Optional) Look through crash reports
@@ -109,6 +109,7 @@
 Internals>Network
 Internals>Network>Auth
 Internals>Network>Cache
+Internals>Network>DNS
 Internals>Network>Connectivity
 Internals>Network>DomainSecurityPolicy
 Internals>Network>FTP
@@ -129,7 +130,6 @@
 Internals>Network>Cookies
 Internals>Network>DataProxy
 Internals>Network>DataUse
-Internals>Network>DNS
 Internals>Network>DoH
 Internals>Network>EV
 Internals>Network>NetInfo
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index 96a6e29..6214cfb 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -302,6 +302,7 @@
     "keep-alive",
     "origin",
     "referer",
+    "set-cookie",
     "te",
     "trailer",
     "transfer-encoding",
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc
index b2eb233..bbe87a4 100644
--- a/net/http/http_util_unittest.cc
+++ b/net/http/http_util_unittest.cc
@@ -38,6 +38,7 @@
       "keep-alive",
       "origin",
       "referer",
+      "set-cookie",
       "te",
       "trailer",
       "transfer-encoding",
diff --git a/net/tools/cache_transparency/generate_checksums.py b/net/tools/cache_transparency/generate_checksums.py
new file mode 100644
index 0000000..f99a9b5
--- /dev/null
+++ b/net/tools/cache_transparency/generate_checksums.py
@@ -0,0 +1,122 @@
+# 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.
+"""Generates checksums for URLs in the Pervasive Payload list."""
+
+import argparse
+import csv
+import requests
+import hashlib
+import urllib.parse
+
+INCLUDE_HEADERS = frozenset([
+    "access-control-allow-credentials", "access-control-allow-headers",
+    "access-control-allow-methods", "access-control-allow-origin",
+    "access-control-expose-headers", "access-control-max-age",
+    "access-control-request-headers", "access-control-request-method",
+    "clear-site-data", "content-encoding", "content-security-policy",
+    "content-type", "cross-origin-embedder-policy",
+    "cross-origin-opener-policy", "cross-origin-resource-policy", "location",
+    "sec-websocket-accept", "sec-websocket-extensions", "sec-websocket-key",
+    "sec-websocket-protocol", "sec-websocket-version", "upgrade", "vary"
+])
+
+
+def generate_list_with_checksums(data):
+  pairs_list = []
+  flat_list = []
+  for i, url_info in enumerate(data):
+    checksum_input = ""
+    url = url_info[0]
+    print(f"[{i}/{len(data)}] Fetching {url}")
+
+    with requests.get(url,
+                      headers={"Accept-Encoding": "gzip, deflate, br"},
+                      stream=True) as response:
+
+      headers = list(response.headers.items())
+      headers = [(name.lower(), value) for name, value in headers]
+      headers.sort()
+
+      for header in headers:
+        if header[0] in INCLUDE_HEADERS:
+          checksum_input += header[0] + ": " + header[1] + "\n"
+
+      checksum_input += "\n"
+      checksum_input = checksum_input.encode()
+
+      raw_body = response.raw.data
+      checksum_input += raw_body
+
+    checksum = hashlib.sha256(checksum_input).hexdigest().upper()
+    pairs_list.append([url, checksum])
+    flat_list.append(str(url))
+    flat_list.append(str(checksum))
+
+  return pairs_list, flat_list
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
+
+  parser.add_argument(
+      "input",
+      type=str,
+      nargs=1,
+      help="path for input csv file containing pervasive payloads list")
+
+  parser.add_argument("-v",
+                      "--list-version",
+                      "--version",
+                      dest="list_version",
+                      default="1",
+                      help="version of pervasive payloads list")
+
+  parser.add_argument("-f",
+                      "--format",
+                      dest="format",
+                      default="csv",
+                      choices=["csv", "comma_separated", "url_encoded"],
+                      help="output format to use. Default: csv")
+
+  parser.add_argument("output",
+                      type=str,
+                      nargs=1,
+                      help="path for output file for URLs and checksums")
+
+  args = parser.parse_args()
+
+  filename = args.input[0]
+
+  data = []
+  with open(filename, mode="r", newline="") as csvfile:
+    datareader = csv.reader(csvfile)
+    data = list(datareader)
+
+  pairs_list, flat_list = generate_list_with_checksums(data)
+
+  if args.format == "csv":
+    with open(args.output[0], mode="w", newline="") as f:
+      writer = csv.writer(f)
+      writer.writerows(pairs_list)
+
+  elif args.format == "comma_separated":
+    flat_list.insert(0, str(args.list_version))
+    with open(args.output[0], mode="w") as file:
+      file.write(",\n".join(flat_list))
+
+  elif args.format == "url_encoded":
+    concatenated = str(args.list_version) + ","
+    concatenated += ",".join(flat_list)
+    url_encoded_list = urllib.parse.quote_plus(concatenated)
+    with open(args.output[0], mode="w") as file:
+      file.write(url_encoded_list)
+    print(
+        "NOTE: To run the feature via commandline, use the following command:\n"
+        "out/Default/chrome --enable-features='PervasivePayloadsList:pervasive-payloads/(url_encoded_list),CacheTransparency,SplitCacheByNetworkIsolationKey'"
+    )
+
+
+if __name__ == "__main__":
+  main()
diff --git a/net/tools/cache_transparency/sample_pervasive_payloads_list.csv b/net/tools/cache_transparency/sample_pervasive_payloads_list.csv
new file mode 100644
index 0000000..8133c0c
--- /dev/null
+++ b/net/tools/cache_transparency/sample_pervasive_payloads_list.csv
@@ -0,0 +1,100 @@
+https://c.amazon-adsystem.com/aax2/apstag.js
+https://c.disquscdn.com/next/embed/common.bundle.9450cde9dd2c9d366781a8fc5ff6e933.js
+https://c.disquscdn.com/next/embed/styles/lounge.7ab903feba7624935283ca4c7d8c7203.css
+https://cdn.cookielaw.org/scripttemplates/otSDKStub.js
+https://cdn.onesignal.com/sdks/OneSignalPageSDKES6.js?v=151513
+https://cdn.onesignal.com/sdks/OneSignalSDK.js
+https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css
+https://connect.facebook.net/en_US/sdk.js
+https://connect.facebook.net/en_US/sdk.js?hash=80773c822cd6e51f7e963a4bf6a9793f
+https://connect.facebook.net/en_US/sdk.js?hash=a572daf7c4ec88ffab229a636a49a105
+https://disqus.com/next/config.js
+https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2
+https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxP.ttf
+https://fonts.gstatic.com/s/roboto/v29/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2
+https://imasdk.googleapis.com/js/sdkloader/ima3.js
+https://js-agent.newrelic.com/nr-1215.min.js
+https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css
+https://mc.yandex.com/metrika/advert.gif
+https://mc.yandex.com/sync_cookie_image_check
+https://mc.yandex.ru/metrika/advert.gif
+https://mc.yandex.ru/metrika/tag.js
+https://platform.twitter.com/embed/embed.i18n.0b77ee78a8e28a636331.js
+https://platform.twitter.com/embed/embed.i18n.293ca00a272b34d032a9.js
+https://platform.twitter.com/embed/embed.modules.aef85bf61d706d7edafa.js
+https://platform.twitter.com/embed/embed.modules.cb647a8c9f5f97575bd9.js
+https://platform.twitter.com/embed/embed.ondemand.en-js.77f81b914ed04ced0591.js
+https://platform.twitter.com/embed/embed.ondemand.en-js.e84cb370ed3e40856450.js
+https://platform.twitter.com/embed/embed.ondemand.i18n.en-js.536c09da9f27ad91baac.js
+https://platform.twitter.com/embed/embed.ondemand.i18n.en-js.5cdc09e4a37a07720433.js
+https://platform.twitter.com/embed/embed.ondemand.TimelineList~ondemand.TimelineProfile~ondemand.Tweet.44711848a6d644a51d82.js
+https://platform.twitter.com/embed/embed.ondemand.TimelineList~ondemand.TimelineProfile~ondemand.Tweet.4ec913c179dde91427eb.js
+https://platform.twitter.com/embed/embed.ondemand.Tweet.066c1f940105261b852e.js
+https://platform.twitter.com/embed/embed.ondemand.Tweet.3debca4342f31b7db9e1.js
+https://platform.twitter.com/embed/embed.ondemand.TweetVideo.40b1938448f69544d784.js
+https://platform.twitter.com/embed/embed.ondemand.TweetVideo.9677ea422e19142d19ec.js
+https://platform.twitter.com/embed/embed.runtime.1724480d574190f6b381.js
+https://platform.twitter.com/embed/embed.runtime.6b5d3661e7231f9606f3.js
+https://platform.twitter.com/embed/embed.Tweet.7e4521689aa2dd8195db.js
+https://platform.twitter.com/embed/embed.Tweet.c31baac24debe5533d7c.js
+https://platform.twitter.com/embed/embed.vendors~loaders.video.VideoPlayerDefaultUI.36474e74c34ad6f52990.js
+https://platform.twitter.com/embed/embed.vendors~loaders.video.VideoPlayerDefaultUI.96cf684c2f96172ada41.js
+https://platform.twitter.com/embed/embed.vendors~ondemand.en-js.2db7d4fd25a0403a936f.js
+https://platform.twitter.com/embed/embed.vendors~ondemand.en-js.fb959cd7154f3c56a8da.js
+https://platform.twitter.com/embed/embed.vendors~ondemand.TimelineList~ondemand.TimelineProfile~ondemand.Tweet.784c14fad3ed09aa7f26.js
+https://platform.twitter.com/embed/embed.vendors~ondemand.TimelineList~ondemand.TimelineProfile~ondemand.Tweet.8fd70d21755f2bcfae49.js
+https://platform.twitter.com/embed/embed.vendors~ondemand.TimelineList~ondemand.TimelineProfile~ondemand.TweetVideo.2690210765db59fa9244.js
+https://platform.twitter.com/embed/embed.vendors~ondemand.TimelineList~ondemand.TimelineProfile~ondemand.TweetVideo.bf89920680446a7cdc95.js
+https://platform.twitter.com/embed/embed.vendors~ondemand.Tweet.d4dc6d9f20302d27b041.js
+https://platform.twitter.com/embed/embed.vendors~ondemand.TweetVideo.98357008a9809fa238b9.js
+https://platform.twitter.com/embed/embed.vendors~ondemand.TweetVideo.c8873d7e5545d6c609c7.js
+https://platform.twitter.com/jot.html
+https://platform.twitter.com/js/button.1c2a6e168692ffea6cc8d4efc5b6f6bc.js
+https://platform.twitter.com/js/horizon_tweet.b9ac0a13a4a1d52c80651179f4fe9b68.js
+https://platform.twitter.com/js/moment~timeline.4391e0bf4053fbaa2a022e3fad2a1e1a.js
+https://platform.twitter.com/js/timeline.34cf38a85ac899f1d6a0438a1659decc.js
+https://platform.twitter.com/widgets.js
+https://s7.addthis.com/js/300/addthis_widget.js
+https://s7.addthis.com/static/layers.fa6cd1947ce26e890d3d.js
+https://s7.addthis.com/static/sh.f48a1a04fe8dbf021b4cda1d.html
+https://securepubads.g.doubleclick.net/gpt/pubads_impl_2022031601.js
+https://securepubads.g.doubleclick.net/gpt/pubads_impl_2022032101.js?cb=31065754
+https://securepubads.g.doubleclick.net/gpt/pubads_impl_2022032101.js?cb=31065822
+https://securepubads.g.doubleclick.net/gpt/pubads_impl_2022032201.js?cb=31065823
+https://snap.licdn.com/li.lms-analytics/insight.min.js
+https://ssl.google-analytics.com/ga.js
+https://static.addtoany.com/menu/page.js
+https://static.addtoany.com/menu/sm.23.html
+https://static.addtoany.com/menu/svg/icons.30.svg.js
+https://static.chartbeat.com/js/chartbeat.js
+https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194
+https://static.criteo.net/js/ld/ld.js
+https://static.doubleclick.net/instream/ad_status.js
+https://stats.wp.com/e-202212.js
+https://test.quantcast.mgr.consensu.org/GVL-v2/cmp-list.json
+https://www.google-analytics.com/analytics.js
+https://www.google-analytics.com/plugins/ua/ec.js
+https://www.google-analytics.com/plugins/ua/linkid.js
+https://www.google.com/js/th/Css0RoSI-HS3Ke9AuoQSWaa8zK9spjRs2QEDJP_UMgo.js
+https://www.google.com/js/th/eC3m08BWsKAgXdD56g8v-hRF27m9BLFWuq71lBVmRb0.js
+https://www.google.com/js/th/EplzmgSwEq1haJy_K7VkvamGBwhWugpG90UbraTSS_o.js
+https://www.google.com/js/th/GK9RXoYhzM9BS2DwszrzkGxxQbY5VR2mx9ED2vYLgv8.js
+https://www.google.com/js/th/iIdjuWWH5BicNn2_JadGpKIgqGW7lVC4-WD5EB_vw2g.js
+https://www.google.com/js/th/lgrQep_cHvWFMgJTnyMczGzKq0lFy3dFEtoDT0eWErg.js
+https://www.google.com/js/th/MKcwde2W9EpBjeUz-X8Qp_8IcWz9bCTkaBfeh4Am-J4.js
+https://www.google.com/js/th/nZvBJ6n5TdZ62aCM6LFj0MJnwO5NiOq1Qq9v_oTz3HU.js
+https://www.google.com/js/th/vUdUDDAd66Cx-AHksaT_xANRkhOhr-b_V9vr9VFFHpQ.js
+https://www.gstatic.com/recaptcha/releases/2uoiJ4hP3NUoP9v_eBNfU6CR/recaptcha__en.js
+https://www.instagram.com/embed.js
+https://www.instagram.com/static/bundles/metro/EmbedAsyncLogger.js/be2bbf5fd5e9.js
+https://www.instagram.com/static/bundles/metro/EmbedSDK.js/d9addf525b6a.js
+https://www.instagram.com/static/bundles/metro/EmbedSimple.js/0db99b108ff7.js
+https://www.instagram.com/static/bundles/metro/EmbedSimpleBase.css/d5d1c8482c44.css
+https://www.instagram.com/static/bundles/metro/en_US.js/23f9fb9aea85.js
+https://www.instagram.com/static/bundles/metro/en_US.js/2ec0b7dcc41c.js
+https://www.instagram.com/static/bundles/metro/Polyfills.js/a76474cce8e5.js
+https://www.instagram.com/static/bundles/metro/Polyfills.js/b1f149405b0e.js
+https://www.instagram.com/static/bundles/metro/Polyfills.js/fecde0d9ec0a.js
+https://www.instagram.com/static/bundles/metro/sprite_core_2x_bcd90c1d4868.png/bcd90c1d4868.png
+https://www.instagram.com/static/bundles/metro/sprite_embed_2x_644bc47b3106.png/644bc47b3106.png
+https://z.moatads.com/addthismoatframe568911941483/moatframe.js
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 59c2435a..f502e7b 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -808,6 +808,7 @@
 
 void URLRequest::NotifyReceivedRedirect(const RedirectInfo& redirect_info,
                                         bool* defer_redirect) {
+  DCHECK_EQ(OK, status_);
   is_redirecting_ = true;
   OnCallToDelegate(NetLogEventType::URL_REQUEST_DELEGATE_RECEIVED_REDIRECT);
   delegate_->OnReceivedRedirect(this, redirect_info, defer_redirect);
@@ -1019,6 +1020,7 @@
 
 void URLRequest::NotifyAuthRequired(
     std::unique_ptr<AuthChallengeInfo> auth_info) {
+  DCHECK_EQ(OK, status_);
   DCHECK(auth_info);
   // Check that there are no callbacks to already failed or cancelled requests.
   DCHECK(!failed());
@@ -1080,6 +1082,10 @@
 }
 
 void URLRequest::OnHeadersComplete() {
+  // The URLRequest status should still be IO_PENDING, which it was set to
+  // before the URLRequestJob was started.  On error or cancellation, this
+  // method should not be called.
+  DCHECK_EQ(ERR_IO_PENDING, status_);
   set_status(OK);
   // Cache load timing information now, as information will be lost once the
   // socket is closed and the ClientSocketHandle is Reset, which will happen
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index d18ee0b..bf4dd78 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -407,11 +407,6 @@
   if (has_handled_response_)
     return;
 
-  // The URLRequest status should still be IO_PENDING, which it was set to
-  // before the URLRequestJob was started.  On error or cancellation, this
-  // method should not be called.
-  DCHECK_EQ(ERR_IO_PENDING, request_->status());
-
   // Initialize to the current time, and let the subclass optionally override
   // the time stamps if it has that information.  The default request_time is
   // set by URLRequest before it calls our Start method.
diff --git a/ppapi/tests/test_utils.cc b/ppapi/tests/test_utils.cc
index 8a131193..9a14a5e 100644
--- a/ppapi/tests/test_utils.cc
+++ b/ppapi/tests/test_utils.cc
@@ -49,7 +49,8 @@
 
 std::string ReportError(const char* method, int32_t error) {
   char error_as_string[12];
-  sprintf(error_as_string, "%d", static_cast<int>(error));
+  snprintf(error_as_string, sizeof(error_as_string), "%d",
+           static_cast<int>(error));
   std::string result = method + std::string(" failed with error: ") +
       error_as_string;
   return result;
diff --git a/ppapi/tests/test_websocket.cc b/ppapi/tests/test_websocket.cc
index a5ac27d..ae1625eb 100644
--- a/ppapi/tests/test_websocket.cc
+++ b/ppapi/tests/test_websocket.cc
@@ -249,7 +249,7 @@
     rv += instance_->websocket_host();
   if (instance_->websocket_port() != -1) {
     char buffer[10];
-    sprintf(buffer, ":%d", instance_->websocket_port());
+    snprintf(buffer, sizeof(buffer), ":%d", instance_->websocket_port());
     rv += std::string(buffer);
   }
   rv += "/";
diff --git a/remoting/host/installer/mac/ChromotingHost.pkgproj b/remoting/host/installer/mac/ChromotingHost.pkgproj
index 9d93361..9f04ce3 100644
--- a/remoting/host/installer/mac/ChromotingHost.pkgproj
+++ b/remoting/host/installer/mac/ChromotingHost.pkgproj
@@ -616,48 +616,12 @@
 					<integer>3</integer>
 					<key>DICTIONARY</key>
 					<dict>
-						<key>IC_REQUIREMENT_CPU_ARCHITECTURE_FAMILY</key>
-						<integer>2</integer>
-						<key>IC_REQUIREMENT_CPU_INTEL_ARCHITECTURE_TYPE</key>
-						<integer>0</integer>
-						<key>IC_REQUIREMENT_CPU_MINIMUM_CPU_CORES_COUNT</key>
-						<integer>1</integer>
-						<key>IC_REQUIREMENT_CPU_MINIMUM_FREQUENCY</key>
-						<integer>866666</integer>
-						<key>IC_REQUIREMENT_CPU_POWERPC_ARCHITECTURE_TYPE</key>
-						<integer>0</integer>
-					</dict>
-					<key>IC_REQUIREMENT_CHECK_TYPE</key>
-					<integer>0</integer>
-					<key>IDENTIFIER</key>
-					<string>fr.whitebox.Packages.requirement.cpu</string>
-					<key>MESSAGE</key>
-					<array>
-						<dict>
-							<key>LANGUAGE</key>
-							<string>English</string>
-							<key>SECONDARY_VALUE</key>
-							<string></string>
-							<key>VALUE</key>
-							<string>@@HOST_NAME@@ requires an Intel processor.</string>
-						</dict>
-					</array>
-					<key>NAME</key>
-					<string>Processor</string>
-					<key>STATE</key>
-					<true/>
-				</dict>
-				<dict>
-					<key>BEHAVIOR</key>
-					<integer>3</integer>
-					<key>DICTIONARY</key>
-					<dict>
 						<key>IC_REQUIREMENT_OS_DISK_TYPE</key>
 						<integer>0</integer>
 						<key>IC_REQUIREMENT_OS_DISTRIBUTION_TYPE</key>
 						<integer>0</integer>
 						<key>IC_REQUIREMENT_OS_MINIMUM_VERSION</key>
-						<integer>100600</integer>
+						<integer>101300</integer>
 					</dict>
 					<key>IC_REQUIREMENT_CHECK_TYPE</key>
 					<integer>1</integer>
@@ -669,7 +633,7 @@
 							<key>LANGUAGE</key>
 							<string>English</string>
 							<key>VALUE</key>
-							<string>@@HOST_NAME@@ requires 10.10 or newer.</string>
+							<string>@@HOST_NAME@@ requires 10.13 or newer.</string>
 						</dict>
 					</array>
 					<key>NAME</key>
diff --git a/remoting/host/policy_watcher.cc b/remoting/host/policy_watcher.cc
index 54d2a6b..a8d94df 100644
--- a/remoting/host/policy_watcher.cc
+++ b/remoting/host/policy_watcher.cc
@@ -453,8 +453,7 @@
   std::unique_ptr<policy::AsyncPolicyLoader> policy_loader;
 #if BUILDFLAG(IS_WIN)
   policy_loader = std::make_unique<policy::PolicyLoaderWin>(
-      file_task_runner, management_service, kChromePolicyKey,
-      true /* is_dev_registry_key_supported */);
+      file_task_runner, management_service, kChromePolicyKey);
 #elif BUILDFLAG(IS_APPLE)
   CFStringRef bundle_id = CFSTR("com.google.Chrome");
   policy_loader = std::make_unique<policy::PolicyLoaderMac>(
diff --git a/sandbox/policy/BUILD.gn b/sandbox/policy/BUILD.gn
index 6b3f411..6b593acc 100644
--- a/sandbox/policy/BUILD.gn
+++ b/sandbox/policy/BUILD.gn
@@ -152,6 +152,7 @@
     ]
 
     deps += [
+      "//services/tracing/public/cpp",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.buildinfo",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.camera3",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.fonts",
@@ -164,6 +165,7 @@
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.memorypressure",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net.interfaces",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sysmem",
+      "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.tracing.perfetto",
       "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.scenic",
     ]
   }
diff --git a/sandbox/policy/fuchsia/DEPS b/sandbox/policy/fuchsia/DEPS
new file mode 100644
index 0000000..c92f537
--- /dev/null
+++ b/sandbox/policy/fuchsia/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+services/tracing/public/cpp",
+]
diff --git a/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc b/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc
index 3f5cbb9..8bcdca0a 100644
--- a/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc
+++ b/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc
@@ -19,6 +19,7 @@
 #include <fuchsia/memorypressure/cpp/fidl.h>
 #include <fuchsia/net/interfaces/cpp/fidl.h>
 #include <fuchsia/sysmem/cpp/fidl.h>
+#include <fuchsia/tracing/perfetto/cpp/fidl.h>
 #include <fuchsia/ui/scenic/cpp/fidl.h>
 #include <lib/sys/cpp/component_context.h>
 #include <lib/sys/cpp/service_directory.h>
@@ -45,6 +46,7 @@
 #include "printing/buildflags/buildflags.h"
 #include "sandbox/policy/mojom/sandbox.mojom.h"
 #include "sandbox/policy/switches.h"
+#include "services/tracing/public/cpp/tracing_features.h"
 
 namespace sandbox {
 namespace policy {
@@ -211,7 +213,21 @@
         base::SequenceBound<base::FilteredServiceDirectory>(
             GetServiceDirectoryTaskRunner(),
             base::ComponentContextForProcess()->svc());
-    for (const char* service_name : kMinimalServices) {
+
+    std::vector<const char*> services(kMinimalServices.begin(),
+                                      kMinimalServices.end());
+
+    // Grant access to the services required by the process type.
+    std::copy(config->services.begin(), config->services.end(),
+              std::back_inserter(services));
+
+    // If system tracing is enabled, then allow child processes to also make
+    // use of it.
+    if (tracing::ShouldSetupSystemTracing()) {
+      services.push_back(fuchsia::tracing::perfetto::ProducerConnector::Name_);
+    }
+
+    for (const char* service_name : services) {
       // |service_name_|  points to a compile-time constant in
       // |kMinimalServices|. It will remain valid for the duration of the task.
       filtered_service_directory_
@@ -219,14 +235,7 @@
           .WithArgs(service_name)
           .Then(base::BindOnce(&AddServiceCallback, service_name));
     }
-    for (const char* service_name : config->services) {
-      // |service_name_| comes from |config|, which points to a compile-time
-      // constant. It will remain valid for the duration of the task.
-      filtered_service_directory_
-          .AsyncCall(&base::FilteredServiceDirectory::AddService)
-          .WithArgs(service_name)
-          .Then(base::BindOnce(&AddServiceCallback, service_name));
-    }
+
     filtered_service_directory_
         .AsyncCall(&base::FilteredServiceDirectory::ConnectClient)
         .WithArgs(service_directory_client_.NewRequest())
diff --git a/services/audio/sync_reader.cc b/services/audio/sync_reader.cc
index 7513b59..44be1c5 100644
--- a/services/audio/sync_reader.cc
+++ b/services/audio/sync_reader.cc
@@ -14,6 +14,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
@@ -36,7 +37,8 @@
 
 void LogPerLatencyGlitchUma(AudioLatency::LatencyType latency,
                             int renderer_missed_callback_count,
-                            int renderer_callback_count) {
+                            int renderer_callback_count,
+                            bool mixing) {
   DCHECK_LE(renderer_missed_callback_count, renderer_callback_count);
 
   auto LatencyToString = [](AudioLatency::LatencyType latency) {
@@ -56,11 +58,12 @@
 
   const std::string suffix = LatencyToString(latency);
 
-  base::UmaHistogramEnumeration("Media.AudioRendererAudioGlitches2." + suffix,
-                                (renderer_missed_callback_count > 0)
-                                    ? AudioGlitchResult::kGlitches
-                                    : AudioGlitchResult::kNoGlitches);
-
+  if (!mixing) {
+    base::UmaHistogramEnumeration("Media.AudioRendererAudioGlitches2." + suffix,
+                                  (renderer_missed_callback_count > 0)
+                                      ? AudioGlitchResult::kGlitches
+                                      : AudioGlitchResult::kNoGlitches);
+  }
   const int kPermilleScaling = 1000;
   // 10%: if we have more that 10% of callbacks having issues, the details are
   // not very interesting any more, so we just log all those cases together to
@@ -78,12 +81,17 @@
       kPermilleScaling * static_cast<double>(renderer_missed_callback_count) /
       renderer_callback_count);
 
-  base::UmaHistogramCustomCounts(
-      ((renderer_callback_count < kShortStreamMaxCallbackCount)
-           ? "Media.AudioRendererMissedDeadline2.Short."
-           : "Media.AudioRendererMissedDeadline2.Long.") +
-          suffix,
-      std::min(missed_permille, kHistogramRange), 0, kHistogramRange + 1, 100);
+  std::string histogram_name = base::StrCat(
+      {"Media.AudioRendererMissedDeadline2.", mixing ? "Mixing." : "",
+       (renderer_callback_count < kShortStreamMaxCallbackCount) ? "Short"
+                                                                : "Long"});
+  base::UmaHistogramCustomCounts(histogram_name,
+                                 std::min(missed_permille, kHistogramRange), 0,
+                                 kHistogramRange + 1, 100);
+
+  base::UmaHistogramCustomCounts(histogram_name + "." + suffix,
+                                 std::min(missed_permille, kHistogramRange), 0,
+                                 kHistogramRange + 1, 100);
 }
 
 }  // namespace
@@ -107,14 +115,9 @@
       latency_tag_(params.latency_tag()),
       mute_audio_for_testing_(base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kMuteAudio)),
-      had_socket_error_(false),
       output_bus_buffer_size_(
           media::AudioBus::CalculateMemorySize(params.channels(),
-                                               params.frames_per_buffer())),
-      renderer_callback_count_(0),
-      renderer_missed_callback_count_(0),
-      trailing_renderer_missed_callback_count_(0),
-      buffer_index_(0) {
+                                               params.frames_per_buffer())) {
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH) || \
     BUILDFLAG(IS_CHROMEOS_LACROS)
   maximum_wait_time_ = params.GetBufferDuration() / 2;
@@ -126,6 +129,7 @@
   } else {
     maximum_wait_time_ = base::Milliseconds(20);
   }
+  maximum_wait_time_for_mixing_ = maximum_wait_time_;
 
 #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
   if (base::FeatureList::IsEnabled(media::kChromeWideEchoCancellation)) {
@@ -133,17 +137,12 @@
         media::kChromeWideEchoCancellationDynamicMixingTimeout.Get();
 
     // The default negative value means we should ignore this parameter.
-    if (mixing_timeout_percent < 0) {
-      maximum_wait_time_for_mixing_ = maximum_wait_time_;
-    } else {
+    if (mixing_timeout_percent > 0) {
       maximum_wait_time_for_mixing_ =
           params.GetBufferDuration() * mixing_timeout_percent;
     }
-  } else
-#endif
-  {
-    maximum_wait_time_for_mixing_ = maximum_wait_time_;
   }
+#endif
 
 #endif
 
@@ -166,6 +165,8 @@
 }
 
 SyncReader::~SyncReader() {
+  DCHECK_GE(renderer_callback_count_, mixing_renderer_callback_count_);
+
   if (!renderer_callback_count_)
     return;
 
@@ -181,6 +182,18 @@
   renderer_missed_callback_count_ -= trailing_renderer_missed_callback_count_;
   renderer_callback_count_ -= trailing_renderer_missed_callback_count_;
 
+  DCHECK_LE(mixing_trailing_renderer_missed_callback_count_,
+            mixing_renderer_missed_callback_count_);
+  DCHECK_LE(mixing_trailing_renderer_missed_callback_count_,
+            mixing_renderer_callback_count_);
+
+  mixing_renderer_missed_callback_count_ -=
+      mixing_trailing_renderer_missed_callback_count_;
+  mixing_renderer_callback_count_ -=
+      mixing_trailing_renderer_missed_callback_count_;
+
+  DCHECK_GE(renderer_callback_count_, mixing_renderer_callback_count_);
+
   if (!renderer_callback_count_)
     return;
 
@@ -195,7 +208,10 @@
                                percentage_missed);
 
   LogPerLatencyGlitchUma(latency_tag_, renderer_missed_callback_count_,
-                         renderer_callback_count_);
+                         renderer_callback_count_, /*mixing=*/false);
+
+  LogPerLatencyGlitchUma(latency_tag_, mixing_renderer_missed_callback_count_,
+                         mixing_renderer_callback_count_, /*mixing=*/true);
 
   TRACE_EVENT_INSTANT1("audio", "~SyncReader", TRACE_EVENT_SCOPE_THREAD,
                        "Missed callback percentage", percentage_missed);
@@ -267,9 +283,16 @@
 
 void SyncReader::Read(media::AudioBus* dest, bool is_mixing) {
   ++renderer_callback_count_;
+  if (is_mixing)
+    ++mixing_renderer_callback_count_;
+
   if (!WaitUntilDataIsReady(is_mixing)) {
     ++trailing_renderer_missed_callback_count_;
     ++renderer_missed_callback_count_;
+    if (is_mixing) {
+      ++mixing_trailing_renderer_missed_callback_count_;
+      ++mixing_renderer_missed_callback_count_;
+    }
     if (renderer_missed_callback_count_ <= 100 &&
         renderer_missed_callback_count_ % 10 == 0) {
       LOG(WARNING) << "SyncReader::Read timed out, audio glitch count="
@@ -282,6 +305,7 @@
   }
 
   trailing_renderer_missed_callback_count_ = 0;
+  mixing_trailing_renderer_missed_callback_count_ = 0;
 
   // Zeroed buffers may be discarded immediately when outputing compressed
   // bitstream.
diff --git a/services/audio/sync_reader.h b/services/audio/sync_reader.h
index 8261d27..274173a9 100644
--- a/services/audio/sync_reader.h
+++ b/services/audio/sync_reader.h
@@ -79,7 +79,7 @@
 
   // Denotes that the most recent socket error has been logged. Used to avoid
   // log spam.
-  bool had_socket_error_;
+  bool had_socket_error_{false};
 
   // Socket for transmitting audio data.
   base::CancelableSyncSocket socket_;
@@ -91,9 +91,12 @@
 
   // Track the number of times the renderer missed its real-time deadline and
   // report a UMA stat during destruction.
-  size_t renderer_callback_count_;
-  size_t renderer_missed_callback_count_;
-  size_t trailing_renderer_missed_callback_count_;
+  size_t renderer_callback_count_{0};
+  size_t renderer_missed_callback_count_{0};
+  size_t trailing_renderer_missed_callback_count_{0};
+  size_t mixing_renderer_callback_count_{0};
+  size_t mixing_renderer_missed_callback_count_{0};
+  size_t mixing_trailing_renderer_missed_callback_count_{0};
 
   // The maximum amount of time to wait for data from the renderer.  Calculated
   // from the parameters given at construction.
@@ -102,7 +105,7 @@
 
   // The index of the audio buffer we're expecting to be sent from the renderer;
   // used to block with timeout for audio data.
-  uint32_t buffer_index_;
+  uint32_t buffer_index_{0};
 };
 
 }  // namespace audio
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn
index 949297d..1795206 100644
--- a/services/device/BUILD.gn
+++ b/services/device/BUILD.gn
@@ -234,8 +234,8 @@
     ]
     deps += [
       "//chromeos/ash/components/dbus/biod:test_support",
+      "//chromeos/ash/components/network:test_support",
       "//chromeos/dbus:test_support",
-      "//chromeos/network:test_support",
       "//services/device/bluetooth:bluetooth_system_tests",
       "//services/device/fingerprint",
       "//third_party/protobuf:protobuf_lite",
diff --git a/services/device/generic_sensor/platform_sensor_util.cc b/services/device/generic_sensor/platform_sensor_util.cc
index c7bbfe5..1ecdf32 100644
--- a/services/device/generic_sensor/platform_sensor_util.cc
+++ b/services/device/generic_sensor/platform_sensor_util.cc
@@ -14,6 +14,7 @@
 
 namespace {
 
+// Check that each rounding multiple is positive number.
 static_assert(kAccelerometerRoundingMultiple > 0.0,
               "Rounding multiple must be positive.");
 
@@ -29,6 +30,10 @@
 static_assert(kOrientationQuaternionRoundingMultiple > 0.0,
               "Rounding multiple must be positive.");
 
+// Check that threshold value is at least half of rounding multiple.
+static_assert(kAlsSignificanceThreshold >= (kAlsRoundingMultiple / 2),
+              "Threshold must be at least half of rounding multiple.");
+
 template <typename T>
 T square(T x) {
   return x * x;
diff --git a/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc b/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc
index 360c0937..e296c84 100644
--- a/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc
+++ b/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc
@@ -9,10 +9,10 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
+#include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/geolocation_handler.h"
-#include "chromeos/network/network_handler_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
diff --git a/services/device/usb/usb_device_handle_android.cc b/services/device/usb/usb_device_handle_android.cc
index 417aeef..197b567 100644
--- a/services/device/usb/usb_device_handle_android.cc
+++ b/services/device/usb/usb_device_handle_android.cc
@@ -32,10 +32,12 @@
     scoped_refptr<UsbDevice> device,
     base::ScopedFD fd,
     const base::android::JavaRef<jobject>& wrapper)
-    : UsbDeviceHandleUsbfs(device,
-                           std::move(fd),
-                           base::ScopedFD(),
-                           UsbService::CreateBlockingTaskRunner()),
+    : UsbDeviceHandleUsbfs(
+          device,
+          std::move(fd),
+          base::ScopedFD(),
+          "",  // Empty string to indicate an invalid client id.
+          UsbService::CreateBlockingTaskRunner()),
       j_object_(wrapper) {}
 
 UsbDeviceHandleAndroid::~UsbDeviceHandleAndroid() {}
diff --git a/services/device/usb/usb_device_handle_usbfs.cc b/services/device/usb/usb_device_handle_usbfs.cc
index 976f587..31e6595 100644
--- a/services/device/usb/usb_device_handle_usbfs.cc
+++ b/services/device/usb/usb_device_handle_usbfs.cc
@@ -28,6 +28,10 @@
 #include "services/device/public/cpp/usb/usb_utils.h"
 #include "services/device/usb/usb_device_linux.h"
 
+#if BUILDFLAG(IS_CHROMEOS)
+#include "chromeos/dbus/permission_broker/permission_broker_client.h"
+#endif
+
 namespace device {
 
 using mojom::UsbControlTransferRecipient;
@@ -419,6 +423,7 @@
     scoped_refptr<UsbDevice> device,
     base::ScopedFD fd,
     base::ScopedFD lifeline_fd,
+    const std::string& client_id,
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
     : device_(std::move(device)),
       fd_(fd.get()),
@@ -426,6 +431,10 @@
   DCHECK(device_);
   DCHECK(fd.is_valid());
 
+  if (!client_id.empty()) {
+    client_id_ = client_id;
+  }
+
   helper_ = base::SequenceBound<BlockingTaskRunnerHelper>(
       std::move(blocking_task_runner), std::move(fd), std::move(lifeline_fd),
       weak_factory_.GetWeakPtr(), task_runner_);
@@ -494,16 +503,16 @@
     return;
   }
 
-  // It appears safe to assume that this ioctl will not block.
-  int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_CLAIMINTERFACE, &interface_number));
-  if (rc) {
-    USB_PLOG(DEBUG) << "Failed to claim interface " << interface_number;
-  } else {
-    interfaces_[interface_number].alternate_setting = 0;
-    RefreshEndpointInfo();
+#if BUILDFLAG(IS_CHROMEOS)
+  if (client_id_.has_value()) {
+    chromeos::PermissionBrokerClient::Get()->DetachInterface(
+        client_id_.value(), interface_number,
+        base::BindOnce(&UsbDeviceHandleUsbfs::DetachInterfaceComplete, this,
+                       interface_number, std::move(callback)));
+    return;
   }
-  task_runner_->PostTask(FROM_HERE,
-                         base::BindOnce(std::move(callback), rc == 0));
+#endif
+  DetachInterfaceComplete(interface_number, std::move(callback), true);
 }
 
 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number,
@@ -753,12 +762,39 @@
     bool success) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (success && device_) {
-    interfaces_[interface_number].alternate_setting = alternate_setting;
-    RefreshEndpointInfo();
+    auto it = interfaces_.find(interface_number);
+    if (it != interfaces_.end()) {
+      it->second.alternate_setting = alternate_setting;
+      RefreshEndpointInfo();
+    }
   }
   std::move(callback).Run(success);
 }
 
+void UsbDeviceHandleUsbfs::DetachInterfaceComplete(int interface_number,
+                                                   ResultCallback callback,
+                                                   bool success) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!success) {
+    task_runner_->PostTask(FROM_HERE,
+                           base::BindOnce(std::move(callback), false));
+    return;
+  }
+
+  // It appears safe to assume that this ioctl will not block.
+  int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_CLAIMINTERFACE, &interface_number));
+  if (rc) {
+    USB_PLOG(DEBUG) << "Failed to claim interface " << interface_number;
+  } else {
+    interfaces_[interface_number].alternate_setting = 0;
+    RefreshEndpointInfo();
+  }
+
+  task_runner_->PostTask(FROM_HERE,
+                         base::BindOnce(std::move(callback), rc == 0));
+}
+
 void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete(int interface_number,
                                                     ResultCallback callback,
                                                     bool success) {
@@ -775,6 +811,14 @@
     // Only refresh endpoints if a device is still attached.
     RefreshEndpointInfo();
   }
+
+#if BUILDFLAG(IS_CHROMEOS)
+  if (client_id_.has_value()) {
+    chromeos::PermissionBrokerClient::Get()->ReattachInterface(
+        client_id_.value(), interface_number, std::move(callback));
+    return;
+  }
+#endif
   std::move(callback).Run(true);
 }
 
diff --git a/services/device/usb/usb_device_handle_usbfs.h b/services/device/usb/usb_device_handle_usbfs.h
index f4e7e796..225a32e 100644
--- a/services/device/usb/usb_device_handle_usbfs.h
+++ b/services/device/usb/usb_device_handle_usbfs.h
@@ -16,6 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/threading/sequence_bound.h"
 #include "services/device/usb/usb_device_handle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 struct usbdevfs_urb;
 
@@ -36,6 +37,7 @@
       scoped_refptr<UsbDevice> device,
       base::ScopedFD fd,
       base::ScopedFD lifeline_fd,
+      const std::string& client_id,
       scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
 
   // UsbDeviceHandle implementation.
@@ -110,6 +112,9 @@
                                             int alternate_setting,
                                             ResultCallback callback,
                                             bool success);
+  void DetachInterfaceComplete(int interface_number,
+                               ResultCallback callback,
+                               bool success);
   void ReleaseInterfaceComplete(int interface_number,
                                 ResultCallback callback,
                                 bool success);
@@ -135,6 +140,8 @@
 
   scoped_refptr<UsbDevice> device_;
   int fd_;  // Copy of the base::ScopedFD held by |helper_|. Valid if |device_|.
+  absl::optional<std::string>
+      client_id_;  // Client ID assigned by the Permission Broker.
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   // Maps claimed interfaces by interface number to their current alternate
diff --git a/services/device/usb/usb_device_linux.cc b/services/device/usb/usb_device_linux.cc
index dde015a..f4f5451 100644
--- a/services/device/usb/usb_device_linux.cc
+++ b/services/device/usb/usb_device_linux.cc
@@ -63,7 +63,7 @@
   }
 
   auto split_callback = base::SplitOnceCallback(std::move(callback));
-  chromeos::PermissionBrokerClient::Get()->ClaimDevicePath(
+  chromeos::PermissionBrokerClient::Get()->OpenPathAndRegisterClient(
       device_path_, kAllInterfacesMask, read_end.get(),
       base::BindOnce(&UsbDeviceLinux::OnOpenRequestComplete, this,
                      std::move(split_callback.first), std::move(write_end)),
@@ -84,13 +84,14 @@
 
 void UsbDeviceLinux::OnOpenRequestComplete(OpenCallback callback,
                                            base::ScopedFD lifeline_fd,
+                                           const std::string& client_id,
                                            base::ScopedFD fd) {
   if (!fd.is_valid()) {
     USB_LOG(EVENT) << "Did not get valid device handle from permission broker.";
     std::move(callback).Run(nullptr);
     return;
   }
-  Opened(std::move(fd), std::move(lifeline_fd), std::move(callback),
+  Opened(std::move(fd), std::move(lifeline_fd), client_id, std::move(callback),
          UsbService::CreateBlockingTaskRunner());
 }
 
@@ -109,11 +110,14 @@
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
   base::ScopedFD fd(HANDLE_EINTR(open(device_path_.c_str(), O_RDWR)));
+  // Client id is only used for ChromeOS so pass empty string here to indicate
+  // an invalid client id.
+  std::string empty_client_id = "";
   if (fd.is_valid()) {
     task_runner->PostTask(
         FROM_HERE, base::BindOnce(&UsbDeviceLinux::Opened, this, std::move(fd),
-                                  base::ScopedFD(), std::move(callback),
-                                  blocking_task_runner));
+                                  base::ScopedFD(), empty_client_id,
+                                  std::move(callback), blocking_task_runner));
   } else {
     USB_PLOG(EVENT) << "Failed to open " << device_path_;
     task_runner->PostTask(FROM_HERE,
@@ -126,11 +130,13 @@
 void UsbDeviceLinux::Opened(
     base::ScopedFD fd,
     base::ScopedFD lifeline_fd,
+    const std::string& client_id,
     OpenCallback callback,
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  scoped_refptr<UsbDeviceHandle> device_handle = new UsbDeviceHandleUsbfs(
-      this, std::move(fd), std::move(lifeline_fd), blocking_task_runner);
+  scoped_refptr<UsbDeviceHandle> device_handle =
+      new UsbDeviceHandleUsbfs(this, std::move(fd), std::move(lifeline_fd),
+                               client_id, blocking_task_runner);
   handles().push_back(device_handle.get());
   std::move(callback).Run(device_handle);
 }
diff --git a/services/device/usb/usb_device_linux.h b/services/device/usb/usb_device_linux.h
index f7dbfa0b..1f99013 100644
--- a/services/device/usb/usb_device_linux.h
+++ b/services/device/usb/usb_device_linux.h
@@ -56,6 +56,7 @@
 #if BUILDFLAG(IS_CHROMEOS)
   void OnOpenRequestComplete(OpenCallback callback,
                              base::ScopedFD fd,
+                             const std::string& client_id,
                              base::ScopedFD lifeline_fd);
   void OnOpenRequestError(OpenCallback callback,
                           const std::string& error_name,
@@ -68,6 +69,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
   void Opened(base::ScopedFD fd,
               base::ScopedFD lifeline_fd,
+              const std::string& client_id,
               OpenCallback callback,
               scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
 
diff --git a/services/network/first_party_sets/first_party_sets_access_delegate.h b/services/network/first_party_sets/first_party_sets_access_delegate.h
index b7193bc..8066aba 100644
--- a/services/network/first_party_sets/first_party_sets_access_delegate.h
+++ b/services/network/first_party_sets/first_party_sets_access_delegate.h
@@ -80,15 +80,18 @@
   [[nodiscard]] absl::optional<SetsByOwner> Sets(
       base::OnceCallback<void(SetsByOwner)> callback);
 
-  // Returns nullopt if First-Party Sets is disabled or if the input is not in
-  // a nontrivial set.
+  // Returns optional(nullopt) if First-Party Sets is disabled or if the input
+  // is not in a nontrivial set.
   // If FPS is enabled and the input site is in a nontrivial set, then this
-  // returns the owner site of that set.
+  // returns a non-empty optional containing the owner site of that set.
   //
   // This may return a result synchronously, or asynchronously invoke `callback`
   // with the result. The callback will be invoked iff the return value is
   // nullopt; i.e. a result will be provided via return value or callback, but
   // not both, and not neither.
+  //
+  // Note that there is a semantic difference between optional(nullopt) and
+  // nullopt.
   [[nodiscard]] absl::optional<OwnerResult> FindOwner(
       const net::SchemefulSite& site,
       base::OnceCallback<void(OwnerResult)> callback);
diff --git a/services/network/first_party_sets/first_party_sets_manager.h b/services/network/first_party_sets/first_party_sets_manager.h
index c4e3588..d168117 100644
--- a/services/network/first_party_sets/first_party_sets_manager.h
+++ b/services/network/first_party_sets/first_party_sets_manager.h
@@ -80,15 +80,18 @@
   // Sets the enabled_ attribute for testing.
   void SetEnabledForTesting(bool enabled);
 
-  // Returns nullopt if First-Party Sets is disabled or if the input is not in
-  // a nontrivial set.
+  // Returns optional(nullopt) if First-Party Sets is disabled or if the input
+  // is not in a nontrivial set.
   // If FPS is enabled and the input site is in a nontrivial set, then this
-  // returns the owner site of that set.
+  // returns a non-empty optional containing the owner site of that set.
   //
   // This may return a result synchronously, or asynchronously invoke `callback`
   // with the result. The callback will be invoked iff the return value is
   // nullopt; i.e. a result will be provided via return value or callback, but
   // not both, and not neither.
+  //
+  // Note that there is a semantic difference between optional(nullopt) and
+  // nullopt.
   [[nodiscard]] absl::optional<OwnerResult> FindOwner(
       const net::SchemefulSite& site,
       const FirstPartySetsContextConfig& fps_context_config,
diff --git a/services/network/public/cpp/content_security_policy/csp_source_list.cc b/services/network/public/cpp/content_security_policy/csp_source_list.cc
index 29412c3..d7c9a704 100644
--- a/services/network/public/cpp/content_security_policy/csp_source_list.cc
+++ b/services/network/public/cpp/content_security_policy/csp_source_list.cc
@@ -47,13 +47,15 @@
 bool IsScriptDirective(CSPDirectiveName directive) {
   return directive == CSPDirectiveName::ScriptSrc ||
          directive == CSPDirectiveName::ScriptSrcAttr ||
-         directive == CSPDirectiveName::ScriptSrcElem;
+         directive == CSPDirectiveName::ScriptSrcElem ||
+         directive == CSPDirectiveName::DefaultSrc;
 }
 
 bool IsStyleDirective(CSPDirectiveName directive) {
   return directive == CSPDirectiveName::StyleSrc ||
          directive == CSPDirectiveName::StyleSrcAttr ||
-         directive == CSPDirectiveName::StyleSrcElem;
+         directive == CSPDirectiveName::StyleSrcElem ||
+         directive == CSPDirectiveName::DefaultSrc;
 }
 
 bool AllowAllInline(CSPDirectiveName directive,
diff --git a/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc b/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc
index 2864773..47f3e2b2 100644
--- a/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc
+++ b/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc
@@ -544,6 +544,10 @@
        {"http://example1.com/foo/ 'unsafe-inline' 'nonce-yay'",
         "http://example1.com/foo/ 'unsafe-inline' 'sha512-321cba'"},
        true},
+      {mojom::CSPDirectiveName::DefaultSrc,
+       "http://example1.com/foo/ 'unsafe-inline' 'strict-dynamic'",
+       {"http://example1.com/foo/ 'unsafe-inline'"},
+       false},
   };
 
   auto origin_b =
diff --git a/services/network/public/cpp/header_util.cc b/services/network/public/cpp/header_util.cc
index c8d3353..add07344 100644
--- a/services/network/public/cpp/header_util.cc
+++ b/services/network/public/cpp/header_util.cc
@@ -51,6 +51,9 @@
     // Forbidden by the fetch spec.
     net::HttpRequestHeaders::kTransferEncoding,
 
+    // Semantically a response header, so not useuful on requests.
+    "Set-Cookie",
+
     // TODO(mmenke): Figure out what to do about the remaining headers:
     // Connection, Cookie, Date, Expect, Referer, Via.
 };
diff --git a/services/network/public/cpp/header_util_unittest.cc b/services/network/public/cpp/header_util_unittest.cc
index a87c2296..769bb66 100644
--- a/services/network/public/cpp/header_util_unittest.cc
+++ b/services/network/public/cpp/header_util_unittest.cc
@@ -67,6 +67,7 @@
       {"Cookie2", "tastiness=5", false},
       {"Keep-Alive", "timeout=5, max=1000", false},
       {net::HttpRequestHeaders::kTransferEncoding, "gzip", false},
+      {"Set-Cookie", "foo=bar", false},
 
       {net::HttpRequestHeaders::kConnection, "Upgrade", false},
       {net::HttpRequestHeaders::kConnection, "Close", true},
diff --git a/services/network/url_loader_factory.cc b/services/network/url_loader_factory.cc
index 21966a9..0453f01 100644
--- a/services/network/url_loader_factory.cc
+++ b/services/network/url_loader_factory.cc
@@ -114,12 +114,13 @@
     mojo::PendingReceiver<mojom::URLLoader> receiver,
     int32_t request_id,
     uint32_t options,
-    const ResourceRequest& url_request,
+    const ResourceRequest& resource_request,
     mojo::PendingRemote<mojom::URLLoaderClient> client,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
-  CreateLoaderAndStartWithSyncClient(
-      std::move(receiver), request_id, options, url_request, std::move(client),
-      /* sync_client= */ nullptr, traffic_annotation);
+  CreateLoaderAndStartWithSyncClient(std::move(receiver), request_id, options,
+                                     resource_request, std::move(client),
+                                     /* sync_client= */ nullptr,
+                                     traffic_annotation);
 }
 
 void URLLoaderFactory::Clone(
@@ -175,18 +176,20 @@
     mojo::PendingReceiver<mojom::URLLoader> receiver,
     int32_t request_id,
     uint32_t options,
-    const ResourceRequest& url_request,
+    const ResourceRequest& resource_request,
     mojo::PendingRemote<mojom::URLLoaderClient> client,
     base::WeakPtr<mojom::URLLoaderClient> sync_client,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   // Requests with |trusted_params| when params_->is_trusted is not set should
   // have been rejected at the CorsURLLoader layer.
-  DCHECK(!url_request.trusted_params || params_->is_trusted);
+  DCHECK(!resource_request.trusted_params || params_->is_trusted);
 
   std::string origin_string;
-  bool has_origin = url_request.headers.GetHeader("Origin", &origin_string) &&
-                    origin_string != "null";
-  absl::optional<url::Origin> request_initiator = url_request.request_initiator;
+  bool has_origin =
+      resource_request.headers.GetHeader("Origin", &origin_string) &&
+      origin_string != "null";
+  absl::optional<url::Origin> request_initiator =
+      resource_request.request_initiator;
   if (has_origin && request_initiator.has_value()) {
     bool origin_head_same_as_request_origin =
         request_initiator.value().IsSameOriginWith(GURL(origin_string));
@@ -195,8 +198,8 @@
         origin_head_same_as_request_origin);
   }
 
-  if (url_request.web_bundle_token_params.has_value() &&
-      url_request.destination !=
+  if (resource_request.web_bundle_token_params.has_value() &&
+      resource_request.destination !=
           network::mojom::RequestDestination::kWebBundle) {
     mojo::Remote<mojom::TrustedHeaderClient> trusted_header_client;
     if (header_client_ && (options & mojom::kURLLoadOptionUseHeaderClient)) {
@@ -208,7 +211,7 @@
 
     // Load a subresource from a WebBundle.
     context_->GetWebBundleManager().StartSubresourceRequest(
-        std::move(receiver), url_request, std::move(client),
+        std::move(receiver), resource_request, std::move(client),
         params_->process_id, std::move(trusted_header_client));
     return;
   }
@@ -226,12 +229,12 @@
   }
 
   int keepalive_request_size = 0;
-  if (url_request.keepalive && keepalive_statistics_recorder) {
-    const size_t url_size = url_request.url.spec().size();
+  if (resource_request.keepalive && keepalive_statistics_recorder) {
+    const size_t url_size = resource_request.url.spec().size();
     size_t headers_size = 0;
 
-    net::HttpRequestHeaders merged_headers = url_request.headers;
-    merged_headers.MergeFrom(url_request.cors_exempt_headers);
+    net::HttpRequestHeaders merged_headers = resource_request.headers;
+    merged_headers.MergeFrom(resource_request.cors_exempt_headers);
 
     for (const auto& pair : merged_headers.GetHeaderVector()) {
       headers_size += (pair.key.size() + pair.value.size());
@@ -266,7 +269,7 @@
   MaybeStartUpdateLoadInfoTimer();
 
   std::unique_ptr<TrustTokenRequestHelperFactory> trust_token_factory;
-  if (url_request.trust_token_params) {
+  if (resource_request.trust_token_params) {
     trust_token_factory = std::make_unique<TrustTokenRequestHelperFactory>(
         context_->trust_token_store(),
         context_->network_service()->trust_token_key_commitments(),
@@ -292,36 +295,36 @@
   }
 
   mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer;
-  if (url_request.trusted_params &&
-      url_request.trusted_params->cookie_observer) {
+  if (resource_request.trusted_params &&
+      resource_request.trusted_params->cookie_observer) {
     cookie_observer =
         std::move(const_cast<mojo::PendingRemote<mojom::CookieAccessObserver>&>(
-            url_request.trusted_params->cookie_observer));
+            resource_request.trusted_params->cookie_observer));
   }
   mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
       url_loader_network_observer;
-  if (url_request.trusted_params &&
-      url_request.trusted_params->url_loader_network_observer) {
+  if (resource_request.trusted_params &&
+      resource_request.trusted_params->url_loader_network_observer) {
     url_loader_network_observer =
         std::move(const_cast<
                   mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>&>(
-            url_request.trusted_params->url_loader_network_observer));
+            resource_request.trusted_params->url_loader_network_observer));
   }
 
   mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer;
-  if (url_request.trusted_params &&
-      url_request.trusted_params->devtools_observer) {
+  if (resource_request.trusted_params &&
+      resource_request.trusted_params->devtools_observer) {
     devtools_observer =
         std::move(const_cast<mojo::PendingRemote<mojom::DevToolsObserver>&>(
-            url_request.trusted_params->devtools_observer));
+            resource_request.trusted_params->devtools_observer));
   }
 
   mojo::PendingRemote<mojom::AcceptCHFrameObserver> accept_ch_frame_observer;
-  if (url_request.trusted_params &&
-      url_request.trusted_params->accept_ch_frame_observer) {
+  if (resource_request.trusted_params &&
+      resource_request.trusted_params->accept_ch_frame_observer) {
     accept_ch_frame_observer = std::move(
         const_cast<mojo::PendingRemote<mojom::AcceptCHFrameObserver>&>(
-            url_request.trusted_params->accept_ch_frame_observer));
+            resource_request.trusted_params->accept_ch_frame_observer));
   }
 
   // Check for third party cookies being disabled by testing a non-existant
@@ -340,7 +343,7 @@
       *this,
       base::BindOnce(&cors::CorsURLLoaderFactory::DestroyURLLoader,
                      base::Unretained(cors_url_loader_factory_)),
-      std::move(receiver), options, url_request, std::move(client),
+      std::move(receiver), options, resource_request, std::move(client),
       std::move(sync_client),
       static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
       request_id, keepalive_request_size,
diff --git a/services/network/url_loader_factory.h b/services/network/url_loader_factory.h
index 123b717..976ef1c 100644
--- a/services/network/url_loader_factory.h
+++ b/services/network/url_loader_factory.h
@@ -60,7 +60,7 @@
   void CreateLoaderAndStart(mojo::PendingReceiver<mojom::URLLoader> receiver,
                             int32_t request_id,
                             uint32_t options,
-                            const ResourceRequest& url_request,
+                            const ResourceRequest& resource_request,
                             mojo::PendingRemote<mojom::URLLoaderClient> client,
                             const net::MutableNetworkTrafficAnnotationTag&
                                 traffic_annotation) override;
@@ -90,7 +90,7 @@
       mojo::PendingReceiver<mojom::URLLoader> receiver,
       int32_t request_id,
       uint32_t options,
-      const ResourceRequest& url_request,
+      const ResourceRequest& resource_request,
       mojo::PendingRemote<mojom::URLLoaderClient> client,
       base::WeakPtr<mojom::URLLoaderClient> sync_client,
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
diff --git a/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc b/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
index 495944a..176dc196 100644
--- a/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
+++ b/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
@@ -619,7 +619,7 @@
       request->failed_memory_dump_count);
 
   char guid_str[20];
-  sprintf(guid_str, "0x%" PRIx64, request->dump_guid);
+  snprintf(guid_str, sizeof(guid_str), "0x%" PRIx64, request->dump_guid);
   TRACE_EVENT_NESTABLE_ASYNC_END2(
       base::trace_event::MemoryDumpManager::kTraceCategory, "GlobalMemoryDump",
       TRACE_ID_LOCAL(request->dump_guid), "dump_guid", TRACE_STR_COPY(guid_str),
diff --git a/services/tracing/public/cpp/perfetto/perfetto_config.cc b/services/tracing/public/cpp/perfetto/perfetto_config.cc
index cb9bbf9..3ac10a7c 100644
--- a/services/tracing/public/cpp/perfetto/perfetto_config.cc
+++ b/services/tracing/public/cpp/perfetto/perfetto_config.cc
@@ -73,6 +73,10 @@
     }
     te_cfg.set_enable_thread_time_sampling(true);
     te_cfg.set_timestamp_unit_multiplier(1000);
+    if (privacy_filtering_enabled) {
+      te_cfg.set_filter_dynamic_event_names(true);
+      te_cfg.set_filter_debug_annotations(true);
+    }
     source_config->set_track_event_config_raw(te_cfg.SerializeAsString());
   }
 #endif  // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
index 3a0ee4e..5aa48af8 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -1301,8 +1301,7 @@
     base::PlatformThreadId thread_id,
     bool explicit_timestamps,
     const base::TimeTicks& now,
-    const base::ThreadTicks& thread_now,
-    base::trace_event::ThreadInstructionCount thread_instruction_now) {
+    const base::ThreadTicks& thread_now) {
   if (base::tracing::GetThreadIsInTraceEventTLS()->Get()) {
     return;
   }
@@ -1315,7 +1314,7 @@
   if (thread_local_event_sink) {
     thread_local_event_sink->UpdateDuration(
         category_group_enabled, name, handle, thread_id, explicit_timestamps,
-        now, thread_now, thread_instruction_now);
+        now, thread_now);
   }
 }
 
@@ -1582,6 +1581,7 @@
 }  // namespace tracing
 
 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(
+    COMPONENT_EXPORT(TRACING_CPP),
     tracing::TraceEventMetadataSource::DataSourceProxy);
 #endif  // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.h b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
index 2fc07bfb..88329a6e 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.h
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
@@ -35,7 +35,6 @@
 class HistogramSamples;
 
 namespace trace_event {
-class ThreadInstructionCount;
 class TraceEvent;
 struct TraceEventHandle;
 }  // namespace trace_event
@@ -247,15 +246,13 @@
       base::trace_event::TraceEventHandle* handle);
   static base::trace_event::TrackEventHandle OnAddTypedTraceEvent(
       base::trace_event::TraceEvent* trace_event);
-  static void OnUpdateDuration(
-      const unsigned char* category_group_enabled,
-      const char* name,
-      base::trace_event::TraceEventHandle handle,
-      base::PlatformThreadId thread_id,
-      bool explicit_timestamps,
-      const base::TimeTicks& now,
-      const base::ThreadTicks& thread_now,
-      base::trace_event::ThreadInstructionCount thread_instruction_now);
+  static void OnUpdateDuration(const unsigned char* category_group_enabled,
+                               const char* name,
+                               base::trace_event::TraceEventHandle handle,
+                               base::PlatformThreadId thread_id,
+                               bool explicit_timestamps,
+                               const base::TimeTicks& now,
+                               const base::ThreadTicks& thread_now);
   static base::trace_event::TracePacketHandle OnAddTracePacket();
   static void OnAddEmptyPacket();
 
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
index 76b4920..2923bcf 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
@@ -27,7 +27,6 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "base/trace_event/task_execution_macros.h"
-#include "base/trace_event/thread_instruction_count.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_log.h"
 #include "base/tracing/trace_time.h"
@@ -72,9 +71,11 @@
 
 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
 std::unique_ptr<perfetto::TracingSession> g_tracing_session;
+constexpr const char kPrivacyFiltered[] = "";
 #else
 constexpr uint32_t kClockIdAbsolute = 64;
 constexpr uint32_t kClockIdIncremental = 65;
+constexpr const char kPrivacyFiltered[] = "PRIVACY_FILTERED";
 #endif
 
 class TraceEventDataSourceTest
@@ -474,7 +475,9 @@
     EXPECT_NE(packet->track_descriptor().process().pid(), 0);
 
     if (filtering_enabled) {
+#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
       EXPECT_FALSE(packet->track_descriptor().process().has_process_name());
+#endif
     } else {
       EXPECT_EQ(packet->track_descriptor().process().process_name(),
                 kTestProcess);
@@ -639,9 +642,9 @@
     }
 
     if (name.iid > 0) {
-      EXPECT_EQ(packet->track_event().name_iid(), name.iid);
+      EXPECT_EQ(name.iid, packet->track_event().name_iid());
     } else if (!name.value.empty()) {
-      EXPECT_EQ(packet->track_event().name(), name.value);
+      EXPECT_EQ(name.value, packet->track_event().name());
     }
 
     TrackEvent::Type track_event_type;
@@ -1551,7 +1554,7 @@
   base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDurationExplicit(
       category_group_enabled, kEventName, handle, /*thread_id=*/1,
       /*explicit_timestamps=*/true, base::TimeTicks() + base::Microseconds(30),
-      base::ThreadTicks(), base::trace_event::ThreadInstructionCount());
+      base::ThreadTicks());
 
   // Updating the duration of an event that wasn't added before tracing begun
   // will only emit an END event, again without category or name.
@@ -1559,7 +1562,7 @@
   base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDurationExplicit(
       category_group_enabled, "other_event_name", handle, /*thread_id=*/1,
       /*explicit_timestamps=*/true, base::TimeTicks() + base::Microseconds(40),
-      base::ThreadTicks(), base::trace_event::ThreadInstructionCount());
+      base::ThreadTicks());
 
   // Complete event for the current thread emits thread time, too.
   trace_event_internal::AddTraceEventWithThreadIdAndTimestamp(
@@ -1916,7 +1919,6 @@
 }
 
 // TODO(skyostil): Implement post-process event filtering.
-#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
 TEST_F(TraceEventDataSourceTest, FilteringSimpleTraceEvent) {
   StartTraceEventDataSource(/* privacy_filtering_enabled =*/true);
   TRACE_EVENT_BEGIN0(kCategoryGroup, "bar");
@@ -1936,8 +1938,13 @@
 
 TEST_F(TraceEventDataSourceTest, FilteringEventWithArgs) {
   StartTraceEventDataSource(/* privacy_filtering_enabled =*/true);
+#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
+  // New SDK does not accept TRACE_EVENT_FLAG values.
+  TRACE_EVENT_INSTANT(kCategoryGroup, "bar", "foo", 42, "bar", "string_val");
+#else
   TRACE_EVENT_INSTANT2(kCategoryGroup, "bar", TRACE_EVENT_SCOPE_THREAD, "foo",
                        42, "bar", "string_val");
+#endif
 
   size_t packet_index = ExpectStandardPreamble(
       /*start_packet_index=*/0u,
@@ -1957,6 +1964,18 @@
 
 TEST_F(TraceEventDataSourceTest, FilteringEventWithFlagCopy) {
   StartTraceEventDataSource(/* privacy_filtering_enabled =*/true);
+#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
+  // 1). Perfetto SDK does not accept TRACE_EVENT_FLAG values.
+  // 2). To include dynamic event names despite privacy filtering, we need to
+  //     manually `set event()->set_name()`. Java names are a valid use case of
+  //     this.
+  TRACE_EVENT_INSTANT(kCategoryGroup, TRACE_STR_COPY(std::string("bar")), "arg1_name",
+                      "arg1_val", "arg2_name", "arg2_val");
+  TRACE_EVENT_INSTANT(
+      kCategoryGroup, nullptr,
+      [](perfetto::EventContext& ev) { ev.event()->set_name("javaName"); },
+      "arg1_name", "arg1_val", "arg2_name", "arg2_val");
+#else
   TRACE_EVENT_INSTANT2(kCategoryGroup, "bar",
                        TRACE_EVENT_SCOPE_THREAD | TRACE_EVENT_FLAG_COPY,
                        "arg1_name", "arg1_val", "arg2_name", "arg2_val");
@@ -1964,13 +1983,14 @@
                        TRACE_EVENT_SCOPE_THREAD | TRACE_EVENT_FLAG_COPY |
                            TRACE_EVENT_FLAG_JAVA_STRING_LITERALS,
                        "arg1_name", "arg1_val", "arg2_name", "arg2_val");
+#endif
 
   size_t packet_index = ExpectStandardPreamble(
       /*start_packet_index=*/0u,
       /*privacy_filtering_enabled=*/true);
 
   auto* e_packet = GetFinalizedPacket(packet_index++);
-  ExpectTraceEvent(e_packet, /*category_iid=*/1u, "PRIVACY_FILTERED",
+  ExpectTraceEvent(e_packet, /*category_iid=*/1u, kPrivacyFiltered,
                    TRACE_EVENT_PHASE_INSTANT, TRACE_EVENT_SCOPE_THREAD);
 
   const auto& annotations = e_packet->track_event().debug_annotations();
@@ -1988,7 +2008,6 @@
 
   ExpectInternedDebugAnnotationNames(e_packet, {});
 }
-#endif  // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
 
 TEST_F(TraceEventDataSourceTest, FilteringMetadataSource) {
   auto* metadata_source = TraceEventMetadataSource::GetInstance();
diff --git a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
index 9c3447a..838d6e929 100644
--- a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
+++ b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
@@ -66,14 +66,12 @@
 constexpr uint32_t kClockIdIncremental = 65;
 
 // Bits xor-ed into the track uuid of a thread track to make the track uuid of
-// a thread time / instruction count track. These bits are chosen from the
+// a thread time track. These bits are chosen from the
 // upper end of the uint64_t bytes, because the tid of the thread is hashed
 // into the least significant 32 bits of the uuid.
 constexpr uint64_t kThreadTimeTrackUuidBit = static_cast<uint64_t>(1u) << 32;
 constexpr uint64_t kAbsoluteThreadTimeTrackUuidBit = static_cast<uint64_t>(1u)
                                                      << 33;
-constexpr uint64_t kThreadInstructionCountTrackUuidBit =
-    static_cast<uint64_t>(1u) << 34;
 
 void AddConvertableToTraceFormat(
     base::trace_event::ConvertableToTraceFormat* value,
@@ -382,9 +380,6 @@
         extra_emitted_track_descriptor_uuids_.push_back(thread_time_track_uuid);
       }
     }
-
-    // We never emit instruction count for different threads.
-    DCHECK(trace_event->thread_instruction_count().is_null());
   }
 }
 
@@ -474,24 +469,13 @@
     }
   }
 
-  bool has_thread_time = !trace_event->thread_timestamp().is_null();
-  bool has_instruction_count =
-      !trace_event->thread_instruction_count().is_null();
-
-  // We always snapshot the thread timestamp when we snapshot instruction
-  // count. If we didn't do this, we'd have to make sure to override the
-  // value of extra_counter_track_uuids.
-  DCHECK(has_thread_time || !has_instruction_count);
-
-  if (has_thread_time) {
+  if (!trace_event->thread_timestamp().is_null()) {
     if (is_for_different_thread) {
       // EarlyJava events are emitted on the main thread but may actually be for
       // different threads and specify their thread time.
 
-      // EarlyJava events are always for the same process and don't set
-      // instruction counts.
+      // EarlyJava events are always for the same process.
       DCHECK(!is_for_different_process);
-      DCHECK(!has_instruction_count);
 
       // Emit a value onto the absolute thread time track for the other thread.
       // We emit a descriptor for this in UpdateIncrementalStateIfNeeded().
@@ -514,22 +498,6 @@
           (trace_event->thread_timestamp() - last_thread_time_)
               .InMicroseconds());
       last_thread_time_ = trace_event->thread_timestamp();
-
-      if (has_instruction_count) {
-        // Thread instruction counts are never user-provided, and since we split
-        // COMPLETE events into BEGIN+END event pairs, they should not appear
-        // out of order.
-        DCHECK(trace_event->thread_instruction_count().ToInternalValue() >=
-               last_thread_instruction_count_.ToInternalValue());
-
-        // TODO(crbug.com/925589): Add tests for instruction counts.
-        track_event->add_extra_counter_values(
-            (trace_event->thread_instruction_count() -
-             last_thread_instruction_count_)
-                .ToInternalValue());
-        last_thread_instruction_count_ =
-            trace_event->thread_instruction_count();
-      }
     }
   }
 
@@ -695,11 +663,10 @@
     int thread_id,
     bool explicit_timestamps,
     const base::TimeTicks& now,
-    const base::ThreadTicks& thread_now,
-    base::trace_event::ThreadInstructionCount thread_instruction_now) {
+    const base::ThreadTicks& thread_now) {
   base::trace_event::TraceEvent new_trace_event(
-      thread_id, now, thread_now, thread_instruction_now, TRACE_EVENT_PHASE_END,
-      category_group_enabled, name, trace_event_internal::kGlobalScope,
+      thread_id, now, thread_now, TRACE_EVENT_PHASE_END, category_group_enabled,
+      name, trace_event_internal::kGlobalScope,
       trace_event_internal::kNoId /* id */,
       trace_event_internal::kNoId /* bind_id */, nullptr,
       explicit_timestamps ? TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP
@@ -818,15 +785,10 @@
     tp_defaults->set_timestamp_clock_id(kClockIdIncremental);
     TrackEventDefaults* te_defaults = tp_defaults->set_track_event_defaults();
 
-    // Default to thread track, with counter values for thread time and
-    // instruction count, if supported.
+    // Default to thread track, with counter values for thread time.
     te_defaults->set_track_uuid(thread_track_uuid);
     te_defaults->add_extra_counter_track_uuids(thread_track_uuid ^
                                                kThreadTimeTrackUuidBit);
-    if (base::trace_event::ThreadInstructionCount::IsSupported()) {
-      te_defaults->add_extra_counter_track_uuids(
-          thread_track_uuid ^ kThreadInstructionCountTrackUuidBit);
-    }
 
     ClockSnapshot* clocks = packet->set_clock_snapshot();
     // Reference clock is in nanoseconds.
@@ -854,15 +816,9 @@
         timestamp, thread_track_uuid, kThreadTimeTrackUuidBit,
         CounterDescriptor::COUNTER_THREAD_TIME_NS, 1000u);
   }
-  if (base::trace_event::ThreadInstructionCount::IsSupported()) {
-    EmitCounterTrackDescriptor(
-        timestamp, thread_track_uuid, kThreadInstructionCountTrackUuidBit,
-        CounterDescriptor::COUNTER_THREAD_INSTRUCTION_COUNT);
-  }
 
   // The first set of counter values should be absolute.
   last_thread_time_ = base::ThreadTicks();
-  last_thread_instruction_count_ = base::trace_event::ThreadInstructionCount();
 
   reset_incremental_state_ = false;
 }
diff --git a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
index 69d51b3..1e06060 100644
--- a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
+++ b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
@@ -15,7 +15,6 @@
 #include "base/component_export.h"
 #include "base/threading/thread_id_name_manager.h"
 #include "base/time/time.h"
-#include "base/trace_event/thread_instruction_count.h"
 #include "base/trace_event/typed_macros.h"
 #include "base/trace_event/typed_macros_embedder_support.h"
 #include "services/tracing/public/cpp/perfetto/interning_index.h"
@@ -60,15 +59,13 @@
   base::trace_event::TracePacketHandle AddTracePacket();
   void AddEmptyPacket();
 
-  void UpdateDuration(
-      const unsigned char* category_group_enabled,
-      const char* name,
-      base::trace_event::TraceEventHandle handle,
-      int thread_id,
-      bool explicit_timestamps,
-      const base::TimeTicks& now,
-      const base::ThreadTicks& thread_now,
-      base::trace_event::ThreadInstructionCount thread_instruction_now);
+  void UpdateDuration(const unsigned char* category_group_enabled,
+                      const char* name,
+                      base::trace_event::TraceEventHandle handle,
+                      int thread_id,
+                      bool explicit_timestamps,
+                      const base::TimeTicks& now,
+                      const base::ThreadTicks& thread_now);
   void Flush();
 
   uint32_t session_id() const { return session_id_; }
@@ -143,7 +140,6 @@
   uint32_t last_incremental_state_reset_id_ = 0;
   base::TimeTicks last_timestamp_;
   base::ThreadTicks last_thread_time_;
-  base::trace_event::ThreadInstructionCount last_thread_instruction_count_;
   base::ProcessId process_id_;
   base::PlatformThreadId thread_id_;
   std::string thread_name_;
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
index 9cc4d06..a2bdf66 100644
--- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
+++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
@@ -924,6 +924,7 @@
 }  // namespace tracing
 
 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS_WITH_ATTRS(
+    COMPONENT_EXPORT(TRACING_CPP),
     tracing::TracingSamplerProfilerDataSource::DataSourceProxy);
 #endif  // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
diff --git a/services/video_capture/broadcasting_receiver.cc b/services/video_capture/broadcasting_receiver.cc
index 1a3035d..59ee3028 100644
--- a/services/video_capture/broadcasting_receiver.cc
+++ b/services/video_capture/broadcasting_receiver.cc
@@ -471,6 +471,13 @@
   }
 }
 
+void BroadcastingReceiver::OnNewCropVersion(uint32_t crop_version) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  for (auto& client : clients_) {
+    client.second.client()->OnNewCropVersion(crop_version);
+  }
+}
+
 void BroadcastingReceiver::OnFrameWithEmptyRegionCapture() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& client : clients_) {
diff --git a/services/video_capture/broadcasting_receiver.h b/services/video_capture/broadcasting_receiver.h
index aaaf67a7..c57fc10e 100644
--- a/services/video_capture/broadcasting_receiver.h
+++ b/services/video_capture/broadcasting_receiver.h
@@ -95,6 +95,7 @@
   void OnBufferRetired(int32_t buffer_id) override;
   void OnError(media::VideoCaptureError error) override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnLog(const std::string& message) override;
   void OnStarted() override;
diff --git a/services/video_capture/lacros/video_frame_handler_proxy_lacros.cc b/services/video_capture/lacros/video_frame_handler_proxy_lacros.cc
index 3dd195b..8a4a626 100644
--- a/services/video_capture/lacros/video_frame_handler_proxy_lacros.cc
+++ b/services/video_capture/lacros/video_frame_handler_proxy_lacros.cc
@@ -146,6 +146,10 @@
   handler_->OnFrameDropped(reason);
 }
 
+void VideoFrameHandlerProxyLacros::OnNewCropVersion(uint32_t crop_version) {
+  handler_->OnNewCropVersion(crop_version);
+}
+
 void VideoFrameHandlerProxyLacros::OnFrameWithEmptyRegionCapture() {
   handler_->OnFrameWithEmptyRegionCapture();
 }
diff --git a/services/video_capture/lacros/video_frame_handler_proxy_lacros.h b/services/video_capture/lacros/video_frame_handler_proxy_lacros.h
index d4f4013..4a3b889 100644
--- a/services/video_capture/lacros/video_frame_handler_proxy_lacros.h
+++ b/services/video_capture/lacros/video_frame_handler_proxy_lacros.h
@@ -49,6 +49,7 @@
                                 scaled_buffers) override;
   void OnBufferRetired(int buffer_id) override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnStarted() override;
   void OnStartedUsingGpuDecode() override;
diff --git a/services/video_capture/public/cpp/mock_video_frame_handler.h b/services/video_capture/public/cpp/mock_video_frame_handler.h
index c9aa91d..a4f67cb 100644
--- a/services/video_capture/public/cpp/mock_video_frame_handler.h
+++ b/services/video_capture/public/cpp/mock_video_frame_handler.h
@@ -46,6 +46,7 @@
   MOCK_METHOD1(DoOnBufferRetired, void(int32_t));
   MOCK_METHOD1(OnError, void(media::VideoCaptureError));
   MOCK_METHOD1(OnFrameDropped, void(media::VideoCaptureFrameDropReason));
+  MOCK_METHOD1(OnNewCropVersion, void(uint32_t));
   MOCK_METHOD0(OnFrameWithEmptyRegionCapture, void());
   MOCK_METHOD1(OnLog, void(const std::string&));
   MOCK_METHOD0(OnStarted, void());
diff --git a/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.cc b/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.cc
index b73ae92..a9e3662e 100644
--- a/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.cc
+++ b/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.cc
@@ -79,6 +79,10 @@
   receiver_->OnFrameDropped(reason);
 }
 
+void ReceiverMediaToMojoAdapter::OnNewCropVersion(uint32_t crop_version) {
+  receiver_->OnNewCropVersion(crop_version);
+}
+
 void ReceiverMediaToMojoAdapter::OnFrameWithEmptyRegionCapture() {
   receiver_->OnFrameWithEmptyRegionCapture();
 }
diff --git a/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.h b/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.h
index a4b9c612..d8318aa 100644
--- a/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.h
+++ b/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.h
@@ -32,6 +32,7 @@
   void OnBufferRetired(int32_t buffer_id) override;
   void OnError(media::VideoCaptureError error) override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnLog(const std::string& message) override;
   void OnStarted() override;
diff --git a/services/video_capture/public/cpp/receiver_mojo_to_media_adapter.cc b/services/video_capture/public/cpp/receiver_mojo_to_media_adapter.cc
index 8c7cab3..ffcb22b 100644
--- a/services/video_capture/public/cpp/receiver_mojo_to_media_adapter.cc
+++ b/services/video_capture/public/cpp/receiver_mojo_to_media_adapter.cc
@@ -69,6 +69,10 @@
   video_frame_handler_->OnFrameWithEmptyRegionCapture();
 }
 
+void ReceiverMojoToMediaAdapter::OnNewCropVersion(uint32_t crop_version) {
+  video_frame_handler_->OnNewCropVersion(crop_version);
+}
+
 void ReceiverMojoToMediaAdapter::OnLog(const std::string& message) {
   video_frame_handler_->OnLog(message);
 }
diff --git a/services/video_capture/public/cpp/receiver_mojo_to_media_adapter.h b/services/video_capture/public/cpp/receiver_mojo_to_media_adapter.h
index 1b639d1..1851cf8c 100644
--- a/services/video_capture/public/cpp/receiver_mojo_to_media_adapter.h
+++ b/services/video_capture/public/cpp/receiver_mojo_to_media_adapter.h
@@ -31,6 +31,7 @@
   void OnBufferRetired(int buffer_id) override;
   void OnError(media::VideoCaptureError error) override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
   void OnFrameWithEmptyRegionCapture() override;
   void OnLog(const std::string& message) override;
   void OnStarted() override;
diff --git a/services/video_capture/public/mojom/video_frame_handler.mojom b/services/video_capture/public/mojom/video_frame_handler.mojom
index dea603f..96cb575 100644
--- a/services/video_capture/public/mojom/video_frame_handler.mojom
+++ b/services/video_capture/public/mojom/video_frame_handler.mojom
@@ -69,6 +69,15 @@
 
   OnFrameDropped(media.mojom.VideoCaptureFrameDropReason reason);
 
+  // Called to indicate that a new |crop_version| has been set, and that all
+  // frames which will subsequently be delivered using OnFrameCaptured(),
+  // will have a crop-version that is greater-than-or-equal-to this one.
+  // This allows the Promise which cropTo() returned to be resolved promptly,
+  // even if frames are not being produced over the track at the moment,
+  // which can happen if the track is cropped to an invisible target, or is
+  // paused, or is muted.
+  OnNewCropVersion(uint32 crop_version);
+
   // Called when a frame is *not* delivered because Region Capture was applied,
   // but the cropped-to region consists of zero pixels. This is needed because
   // the blue border that is normally drawn around the cropped-to region should
diff --git a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
index f66622d..0e5d7e0 100644
--- a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
+++ b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
@@ -61,6 +61,15 @@
                   pending_remote<FrameSinkVideoConsumerFrameCallbacks>
                       callbacks);
 
+  // Called to indicate that a new |crop_version| has been set, and that all
+  // frames which will subsequently be delivered using OnFrameCaptured(),
+  // will have a crop-version that is greater-than-or-equal-to this one.
+  // This allows the Promise which cropTo() returned to be resolved promptly,
+  // even if frames are not being produced over the track at the moment,
+  // which can happen if the track is cropped to an invisible target, or is
+  // paused, or is muted.
+  OnNewCropVersion(uint32 crop_version);
+
   // Called when a frame is *not* delivered because Region Capture was applied,
   // but the cropped-to region consists of zero pixels. This is needed because
   // the blue border that is normally drawn around the cropped-to region should
diff --git a/storage/browser/quota/quota_internals.mojom b/storage/browser/quota/quota_internals.mojom
index 5db2a56..01e76d6 100644
--- a/storage/browser/quota/quota_internals.mojom
+++ b/storage/browser/quota/quota_internals.mojom
@@ -49,10 +49,6 @@
     // Returns an array of Storage Bucket entries stored in the QuotaDatabase.
     RetrieveBucketsTable() => (array<BucketTableEntry> entries);
 
-    // Returns a host's usage for a given storage type.
-    GetHostUsageForInternals(string host, StorageType storage_type) =>
-        (int64 host_usage);
-
     // Returns the global usage and unlimited usage for a given storage type.
     GetGlobalUsageForInternals(StorageType storage_type) =>
         (int64 usage, int64 unlimited_usage);
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc
index f8e3798..40490a64 100644
--- a/storage/browser/quota/quota_manager_impl.cc
+++ b/storage/browser/quota/quota_manager_impl.cc
@@ -1739,22 +1739,6 @@
   usage_tracker->GetBucketUsageWithBreakdown(bucket, std::move(callback));
 }
 
-void QuotaManagerImpl::GetHostUsageForInternals(
-    const std::string& host,
-    storage::mojom::StorageType storage_type,
-    GetHostUsageForInternalsCallback callback) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  EnsureDatabaseOpened();
-
-  StorageType type = GetBlinkStorageType(storage_type);
-  UsageTracker* usage_tracker = GetUsageTracker(type);
-  DCHECK(usage_tracker);
-
-  usage_tracker->GetHostUsageWithBreakdown(
-      host, base::BindOnce(&QuotaManagerImpl::OnGetHostUsageForInternals,
-                           weak_factory_.GetWeakPtr(), std::move(callback)));
-}
-
 bool QuotaManagerImpl::IsSessionOnly(const StorageKey& storage_key,
                                      StorageType type) const {
   return type == StorageType::kTemporary && special_storage_policy_ &&
@@ -1986,16 +1970,6 @@
   return nullptr;
 }
 
-void QuotaManagerImpl::OnGetHostUsageForInternals(
-    GetHostUsageForInternalsCallback callback,
-    int64_t usage,
-    blink::mojom::UsageBreakdownPtr usage_breakdown) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_GE(usage, -1);
-
-  std::move(callback).Run(usage);
-}
-
 void QuotaManagerImpl::NotifyStorageAccessed(const StorageKey& storage_key,
                                              StorageType type,
                                              base::Time access_time) {
diff --git a/storage/browser/quota/quota_manager_impl.h b/storage/browser/quota/quota_manager_impl.h
index 19d3bf5..3535466 100644
--- a/storage/browser/quota/quota_manager_impl.h
+++ b/storage/browser/quota/quota_manager_impl.h
@@ -387,10 +387,6 @@
       GetDiskAvailabilityAndTempPoolSizeCallback callback) override;
   void GetStatistics(GetStatisticsCallback callback) override;
   void RetrieveBucketsTable(RetrieveBucketsTableCallback callback) override;
-  void GetHostUsageForInternals(
-      const std::string& host,
-      storage::mojom::StorageType storage_type,
-      GetHostUsageForInternalsCallback callback) override;
   void GetGlobalUsageForInternals(
       storage::mojom::StorageType storage_type,
       GetGlobalUsageForInternalsCallback callback) override;
@@ -584,10 +580,6 @@
   UsageTracker* GetUsageTracker(blink::mojom::StorageType type) const;
 
   void DumpBucketTable(DumpBucketTableCallback callback);
-  void OnGetHostUsageForInternals(
-      GetHostUsageForInternalsCallback callback,
-      int64_t usage,
-      blink::mojom::UsageBreakdownPtr usage_breakdown);
   void UpdateQuotaInternalsDiskAvailability(base::OnceClosure barrier_callback,
                                             AccumulateQuotaInternalsInfo* info,
                                             int64_t total_space,
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc
index f9579cf..d81f527 100644
--- a/storage/browser/quota/quota_manager_unittest.cc
+++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -2927,32 +2927,6 @@
              .usage);
 }
 
-TEST_F(QuotaManagerImplTest, GetHostUsageForInternals) {
-  static const ClientBucketData kData[] = {
-      {"http://example.com/", kDefaultBucketName, kTemp, 400},
-      {"http://example.com/", kDefaultBucketName, kPerm, 2},
-  };
-  MockQuotaClient* client =
-      CreateAndRegisterClient(QuotaClientType::kFileSystem, {kTemp, kPerm});
-  RegisterClientBucketData(client, kData);
-
-  base::test::TestFuture<int64_t> temp_future;
-  quota_manager_impl()->GetHostUsageForInternals(
-      "example.com", storage::mojom::StorageType::kTemporary,
-      temp_future.GetCallback());
-  int64_t temp_result = temp_future.Take();
-
-  EXPECT_EQ(400, temp_result);
-
-  base::test::TestFuture<int64_t> perm_future;
-  quota_manager_impl()->GetHostUsageForInternals(
-      "example.com", storage::mojom::StorageType::kPersistent,
-      perm_future.GetCallback());
-  int64_t perm_result = perm_future.Take();
-
-  EXPECT_EQ(2, perm_result);
-}
-
 TEST_F(QuotaManagerImplTest, GetDiskAvailabilityAndTempPoolSize) {
   const int kPoolSize = 1000;
   const int kPerHostQuota = kPoolSize / 5;
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 7eef3562..cb50bdc 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1800,7 +1800,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R105-14916.0.0",
+        "cros_img": "atlas-release/R105-14929.0.0",
         "name": "lacros_all_tast_tests ATLAS_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1864,7 +1864,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R105-14916.0.0",
+        "cros_img": "eve-release/R105-14929.0.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1880,7 +1880,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R104-14909.7.0",
+        "cros_img": "eve-release/R104-14909.11.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -1973,7 +1973,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R105-14916.0.0",
+        "cros_img": "hana-release/R105-14929.0.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1989,7 +1989,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14909.7.0",
+        "cros_img": "hana-release/R104-14909.11.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -2037,7 +2037,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R105-14916.0.0",
+        "cros_img": "jacuzzi-release/R105-14929.0.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -2053,7 +2053,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14909.7.0",
+        "cros_img": "jacuzzi-release/R104-14909.11.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -2087,7 +2087,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R105-14916.0.0",
+        "cros_img": "hana-release/R105-14929.0.0",
         "name": "ozone_unittests HANA_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2100,7 +2100,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14909.7.0",
+        "cros_img": "hana-release/R104-14909.11.0",
         "name": "ozone_unittests HANA_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2139,7 +2139,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R105-14916.0.0",
+        "cros_img": "jacuzzi-release/R105-14929.0.0",
         "name": "ozone_unittests JACUZZI_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2152,7 +2152,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14909.7.0",
+        "cros_img": "jacuzzi-release/R104-14909.11.0",
         "name": "ozone_unittests JACUZZI_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2178,7 +2178,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R105-14916.0.0",
+        "cros_img": "hana-release/R105-14929.0.0",
         "name": "viz_unittests HANA_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -2191,7 +2191,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14909.7.0",
+        "cros_img": "hana-release/R104-14909.11.0",
         "name": "viz_unittests HANA_RELEASE_DEV",
         "swarming": {},
         "test": "viz_unittests",
@@ -2230,7 +2230,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R105-14916.0.0",
+        "cros_img": "jacuzzi-release/R105-14929.0.0",
         "name": "viz_unittests JACUZZI_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -2243,7 +2243,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14909.7.0",
+        "cros_img": "jacuzzi-release/R104-14909.11.0",
         "name": "viz_unittests JACUZZI_RELEASE_DEV",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index f7ca736..1c2f835c 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -8327,15 +8327,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8361,7 +8361,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8446,7 +8446,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8837,15 +8837,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8871,7 +8871,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8956,7 +8956,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index af7b26f6..1b67d7c 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -5496,7 +5496,8 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
         },
         "test": "android_browsertests",
         "test_id_prefix": "ninja://chrome/test:android_browsertests/"
@@ -19556,8 +19557,7 @@
         "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android31.textpb",
-          "--gtest_filter=-org.chromium.android_webview.test.devui.HomeFragmentTest.testLongPressCopy*"
+          "--avd-config=../../tools/android/avd/proto/generic_android31.textpb"
         ],
         "merge": {
           "args": [
@@ -46457,15 +46457,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46491,7 +46491,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46576,7 +46576,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46967,15 +46967,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47001,7 +47001,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47086,7 +47086,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47481,15 +47481,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47515,7 +47515,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47600,7 +47600,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47991,15 +47991,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48025,7 +48025,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48110,7 +48110,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48573,15 +48573,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48607,7 +48607,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48692,7 +48692,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49083,15 +49083,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49117,7 +49117,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49202,7 +49202,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49665,15 +49665,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49699,7 +49699,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49784,7 +49784,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50175,15 +50175,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--implementation-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
+          "--webview-apk-path=apks/SystemWebView.apk",
+          "--implementation-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50209,7 +50209,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.61"
+              "revision": "version:103.0.5060.62"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50294,7 +50294,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.18"
+              "revision": "version:104.0.5112.23"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 71a1301..9212df9a 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -9073,9 +9073,6 @@
         "test_id_prefix": "ninja://ui/compositor:compositor_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -9126,24 +9123,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
@@ -10628,9 +10607,6 @@
         "test_id_prefix": "ninja://ui/compositor:compositor_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -10665,25 +10641,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-20.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
diff --git a/testing/buildbot/chromium.fuchsia.fyi.json b/testing/buildbot/chromium.fuchsia.fyi.json
index a89953d..9029b82 100644
--- a/testing/buildbot/chromium.fuchsia.fyi.json
+++ b/testing/buildbot/chromium.fuchsia.fyi.json
@@ -372,9 +372,6 @@
         "test_id_prefix": "ninja://ui/compositor:compositor_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -409,25 +406,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-20.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
@@ -1556,7 +1534,7 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter;../../testing/buildbot/filters/fuchsia.lsan.content_unittests.filter"
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.lsan.content_unittests.filter"
         ],
         "merge": {
           "args": [],
@@ -1608,24 +1586,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
@@ -2869,9 +2829,6 @@
         "test_id_prefix": "ninja://ui/compositor:compositor_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -2922,24 +2879,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
diff --git a/testing/buildbot/chromium.fuchsia.json b/testing/buildbot/chromium.fuchsia.json
index d1bec75..a9471c6 100644
--- a/testing/buildbot/chromium.fuchsia.json
+++ b/testing/buildbot/chromium.fuchsia.json
@@ -369,9 +369,6 @@
         "test_id_prefix": "ninja://ui/compositor:compositor_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -406,25 +403,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-20.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
@@ -1566,9 +1544,6 @@
         "test_id_prefix": "ninja://ui/compositor:compositor_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -1619,24 +1594,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index c6a443d..7400760 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -20001,7 +20001,6 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter",
           "--ram-size-mb=16384",
           "--code-coverage",
           "--code-coverage-dir=${ISOLATED_OUTDIR}",
@@ -20070,30 +20069,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "args": [
-          "--ram-size-mb=16384",
-          "--code-coverage",
-          "--code-coverage-dir=${ISOLATED_OUTDIR}",
-          "--test-launcher-jobs=2"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
@@ -21633,9 +21608,6 @@
         "test_id_prefix": "ninja://ui/compositor:compositor_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -21692,26 +21664,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-20.04",
-              "pool": "chromium.tests.fuchsia"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
@@ -23087,9 +23039,6 @@
         "test_id_prefix": "ninja://ui/compositor:compositor_unittests/"
       },
       {
-        "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
-        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -23140,24 +23089,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "cr_fuchsia_base_unittests",
-        "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "crypto_unittests",
         "test_id_prefix": "ninja://crypto:crypto_unittests/"
       },
@@ -24650,7 +24581,6 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter",
           "--gtest_also_run_disabled_tests",
           "--gtest_filter=*DISABLE*"
         ],
@@ -101211,25 +101141,6 @@
               "os": "Mac-10.15"
             }
           ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "browser_tests",
-        "test_id_prefix": "ninja://chrome/test:browser_tests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "cast_unittests",
@@ -102147,25 +102058,6 @@
               "os": "Mac-10.15"
             }
           ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "browser_tests",
-        "test_id_prefix": "ninja://chrome/test:browser_tests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "cast_unittests",
@@ -105456,9 +105348,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042"
-            },
-            {
+              "os": "Windows-10-19042",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -105481,9 +105371,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042"
-            },
-            {
+              "os": "Windows-10-19042",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -105505,9 +105393,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042"
-            },
-            {
+              "os": "Windows-10-19042",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -105529,9 +105415,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042"
-            },
-            {
+              "os": "Windows-10-19042",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -105553,9 +105437,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042"
-            },
-            {
+              "os": "Windows-10-19042",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -105577,9 +105459,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042"
-            },
-            {
+              "os": "Windows-10-19042",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -105609,9 +105489,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042"
-            },
-            {
+              "os": "Windows-10-19042",
               "pool": "chromium.tests.finch"
             }
           ],
@@ -105639,9 +105517,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-19042"
-            },
-            {
+              "os": "Windows-10-19042",
               "pool": "chromium.tests.finch"
             }
           ],
diff --git a/testing/buildbot/chromium.reclient.fyi.json b/testing/buildbot/chromium.reclient.fyi.json
index 742fafd2..b18e98a1 100644
--- a/testing/buildbot/chromium.reclient.fyi.json
+++ b/testing/buildbot/chromium.reclient.fyi.json
@@ -16,6 +16,16 @@
       "all"
     ]
   },
+  "Mac Builder reclient staging": {
+    "additional_compile_targets": [
+      "all"
+    ]
+  },
+  "Mac Builder reclient test": {
+    "additional_compile_targets": [
+      "all"
+    ]
+  },
   "Simple Chrome Builder reclient staging": {
     "additional_compile_targets": [
       "chromiumos_preflight"
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 0ca3b51..e93be27 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -158,7 +158,6 @@
   testonly = true
 
   data = [
-    "//testing/buildbot/filters/fuchsia.content_unittests.filter",
     "//testing/buildbot/filters/fuchsia.lsan.content_unittests.filter",
     "//testing/buildbot/filters/webrtc.content_unittests.filter",
   ]
diff --git a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter
index a9fee65..df454f4d 100644
--- a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter
+++ b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter
@@ -87,7 +87,9 @@
 -FingerprintSetupTest.*
 -ForceMaximizeOnFirstRunTest.*
 -ForceMaximizePolicyFalseTest.*
+-HIDDetectionDeviceOwnedTest.*
 -HIDDetectionScreenChromebookTest.*
+-HidDetectionSkipTestLegacy.*
 -HidDetectionSkipTest.*
 -HidDetectionTest.*
 -InitialEnrollmentTest.*
diff --git a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter
index 11a2358..cb090f6 100644
--- a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter
+++ b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter
@@ -87,7 +87,9 @@
 FingerprintSetupTest.*
 ForceMaximizeOnFirstRunTest.*
 ForceMaximizePolicyFalseTest.*
+HIDDetectionDeviceOwnedTest.*
 HIDDetectionScreenChromebookTest.*
+HidDetectionSkipTestLegacy.*
 HidDetectionSkipTest.*
 HidDetectionTest.*
 InitialEnrollmentTest.*
diff --git a/testing/buildbot/filters/fuchsia.content_unittests.filter b/testing/buildbot/filters/fuchsia.content_unittests.filter
deleted file mode 100644
index bacab34..0000000
--- a/testing/buildbot/filters/fuchsia.content_unittests.filter
+++ /dev/null
@@ -1,27 +0,0 @@
-# https://crbug.com/780317 - Flakily timeout under QEMU s/w emulation of ARM64.
--WebBluetoothDeviceIdTest.DefaultConstructor
-
-# These expect video capture: https://crbug.com/766356.
--MediaStreamManagerTest.MakeAndCancelMultipleRequests
--MediaStreamManagerTest.MakeMediaAccessRequest
--MediaStreamManagerTest.MakeMultipleRequests
-
-# Failing: https://crbug.com/771701.
--IndexedDBFactoryTest.DataFormatVersion
-
-# Flaky: https://crbug.com/776424.
--RenderWidgetHostViewAuraTest.CursorVisibilityChange
--RenderWidgetHostViewAuraTest.SetCanScrollForWebMouseWheelEvent
--RenderWidgetHostViewAuraTest.SyntheticFlingCancelAtTouchpadScrollBegin
--RenderWidgetHostViewAuraTest.TimerBasedWheelEventPhaseInfo
-
-# Flaky: https://crbug.com/777917.
--LevelDBTransactionRangeTests/LevelDBTransactionRangeTest.*
-
-# Flaky: https://crbug.com/780508.
--ServiceWorkerContainerHostTest.*
-
-# TODO(crbug.com/1231509): These tests require
-# OSExchangeDataProviderFactory::CreateProvider to be implemented.
--WebContentsViewAuraTest.DragDropFiles
--WebContentsViewAuraTest.DragDropFilesOriginateFromRenderer
diff --git a/testing/buildbot/filters/linux-lacros.browser_tests.filter b/testing/buildbot/filters/linux-lacros.browser_tests.filter
index fd74bbb0..63a59503 100644
--- a/testing/buildbot/filters/linux-lacros.browser_tests.filter
+++ b/testing/buildbot/filters/linux-lacros.browser_tests.filter
@@ -19,6 +19,7 @@
 -OmniboxPopupContentsViewTest.PopupMatchesLocationBarBackground
 -OutOfProcessPPAPITest.Printing
 -ProfileListDesktopBrowserTest.SwitchToProfile
+-SSLUITest.TestCloseTabWithUnsafePopup
 -TabHoverCardBubbleViewBrowserTest.WidgetNotVisibleOnMousePressAfterTabFocus
 -TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnKeyPressAfterTabFocus
 # crbug.com/1121486
@@ -27,6 +28,7 @@
 -All/HostedOrWebAppTest.CtrlClickLink/WebApp
 -AudioFocusWebContentsObserverBrowserTest.PlatformAppHasDifferentAudioFocus
 -ContentSettingsTest.AllowCookiesForASessionUsingExceptions
+-CustomTabBarViewBrowserTest.BackToAppButtonIsNotVisibleInOutOfScopePopups
 -DevToolsTest.TestDispatchKeyEventShowsAutoFill
 # #TODO (b/235882005): These tests fail due to a NOT_IMPLEMENTED_LOG_ONCE()
 # within the  wayland_surface.cc implementation. This implementation is
diff --git a/testing/buildbot/filters/ozone-linux.wayland_browser_tests.filter b/testing/buildbot/filters/ozone-linux.wayland_browser_tests.filter
index 9cc4d72..b0bb0b6 100644
--- a/testing/buildbot/filters/ozone-linux.wayland_browser_tests.filter
+++ b/testing/buildbot/filters/ozone-linux.wayland_browser_tests.filter
@@ -1,5 +1,7 @@
 # These tests cannot work on Wayland because the platform does not allow clients
 # to position top level windows, activate them, and set focus.
+-All/HostedOrWebAppTest.CtrlClickLink/HostedApp
+-All/HostedOrWebAppTest.CtrlClickLink/WebApp
 -All/PopupBrowserTest.MoveClampedToCurrentDisplay/0
 -All/PopupBrowserTest.MoveClampedToCurrentDisplay/1
 -AutomationManagerAuraBrowserTest.EventFromAction
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index e1ef5c44..6795021 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -718,10 +718,6 @@
     "label": "//courgette:courgette_unittests",
     "type": "console_test_launcher",
   },
-  "cr_fuchsia_base_unittests": {
-    "label": "//fuchsia/base:cr_fuchsia_base_unittests",
-    "type": "console_test_launcher",
-  },
   "crashpad_tests": {
     "label": "//third_party/crashpad/crashpad:crashpad_tests",
     "type": "console_test_launcher",
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 397a5a4..e14faaf 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1038,10 +1038,10 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R105-14916.0.0",
+        "cros_img": "octopus-release/R105-14929.0.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
-        "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")",
+        "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
         "test": "lacros_fyi_tast_tests",
         "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/",
         "timeout_sec": 10800,
@@ -1050,10 +1050,10 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R104-14909.7.0",
+        "cros_img": "octopus-release/R104-14909.11.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_DEV",
         "swarming": {},
-        "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")",
+        "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
         "test": "lacros_fyi_tast_tests",
         "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/",
         "timeout_sec": 10800,
@@ -1065,7 +1065,7 @@
         "cros_img": "octopus-release/R103-14816.64.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_BETA",
         "swarming": {},
-        "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")",
+        "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
         "test": "lacros_fyi_tast_tests",
         "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/",
         "timeout_sec": 10800,
@@ -1074,10 +1074,10 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R102-14695.85.0",
+        "cros_img": "octopus-release/R102-14695.107.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_STABLE",
         "swarming": {},
-        "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")",
+        "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
         "test": "lacros_fyi_tast_tests",
         "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/",
         "timeout_sec": 10800,
@@ -1086,7 +1086,55 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R105-14916.0.0",
+        "cros_img": "octopus-release/R105-14929.0.0",
+        "name": "lacros_variations_tast_tests OCTOPUS_RELEASE_LKGM",
+        "swarming": {},
+        "tast_expr": "(\"name:lacros.VariationSmoke\")",
+        "test": "lacros_variations_tast_tests",
+        "test_id_prefix": "ninja://chromeos/lacros:lacros_variations_tast_tests/",
+        "timeout_sec": 10800,
+        "variant_id": "OCTOPUS_RELEASE_LKGM"
+      },
+      {
+        "args": [],
+        "cros_board": "octopus",
+        "cros_img": "octopus-release/R104-14909.11.0",
+        "name": "lacros_variations_tast_tests OCTOPUS_RELEASE_DEV",
+        "swarming": {},
+        "tast_expr": "(\"name:lacros.VariationSmoke\")",
+        "test": "lacros_variations_tast_tests",
+        "test_id_prefix": "ninja://chromeos/lacros:lacros_variations_tast_tests/",
+        "timeout_sec": 10800,
+        "variant_id": "OCTOPUS_RELEASE_DEV"
+      },
+      {
+        "args": [],
+        "cros_board": "octopus",
+        "cros_img": "octopus-release/R103-14816.64.0",
+        "name": "lacros_variations_tast_tests OCTOPUS_RELEASE_BETA",
+        "swarming": {},
+        "tast_expr": "(\"name:lacros.VariationSmoke\")",
+        "test": "lacros_variations_tast_tests",
+        "test_id_prefix": "ninja://chromeos/lacros:lacros_variations_tast_tests/",
+        "timeout_sec": 10800,
+        "variant_id": "OCTOPUS_RELEASE_BETA"
+      },
+      {
+        "args": [],
+        "cros_board": "octopus",
+        "cros_img": "octopus-release/R102-14695.107.0",
+        "name": "lacros_variations_tast_tests OCTOPUS_RELEASE_STABLE",
+        "swarming": {},
+        "tast_expr": "(\"name:lacros.VariationSmoke\")",
+        "test": "lacros_variations_tast_tests",
+        "test_id_prefix": "ninja://chromeos/lacros:lacros_variations_tast_tests/",
+        "timeout_sec": 10800,
+        "variant_id": "OCTOPUS_RELEASE_STABLE"
+      },
+      {
+        "args": [],
+        "cros_board": "octopus",
+        "cros_img": "octopus-release/R105-14929.0.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1097,7 +1145,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R104-14909.7.0",
+        "cros_img": "octopus-release/R104-14909.11.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1119,7 +1167,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R102-14695.85.0",
+        "cros_img": "octopus-release/R102-14695.107.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_STABLE",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1138,7 +1186,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R105-14916.0.0",
+        "cros_img": "strongbad-release/R105-14929.0.0",
         "name": "lacros_all_tast_tests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1150,7 +1198,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14909.7.0",
+        "cros_img": "strongbad-release/R104-14909.11.0",
         "name": "lacros_all_tast_tests strongbad_RELEASE_DEV",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1186,7 +1234,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R105-14916.0.0",
+        "cros_img": "strongbad-release/R105-14929.0.0",
         "name": "ozone_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1197,7 +1245,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14909.7.0",
+        "cros_img": "strongbad-release/R104-14909.11.0",
         "name": "ozone_unittests strongbad_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1230,7 +1278,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R105-14916.0.0",
+        "cros_img": "strongbad-release/R105-14929.0.0",
         "name": "viz_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -1241,7 +1289,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14909.7.0",
+        "cros_img": "strongbad-release/R104-14909.11.0",
         "name": "viz_unittests strongbad_RELEASE_DEV",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 4459138..7607d11 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -435,11 +435,9 @@
   },
   'finch-chromium-swarming-pool': {
     'swarming': {
-      'dimension_sets': [
-        {
-          'pool': 'chromium.tests.finch',
-        },
-      ],
+      'dimensions': {
+        'pool': 'chromium.tests.finch',
+      },
     },
   },
   'flame': {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index de1dbbb..0cd177e 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -34,6 +34,11 @@
   },
   'android_browsertests': {
     'modifications': {
+      'Marshmallow Tablet Tester': {
+        'swarming': {
+          'shards': 2,
+        },
+      },
       'android-11-x86-rel': {
         'args': [
           # https://crbug.com/1289764
@@ -3528,12 +3533,6 @@
           '--gtest_filter=-org.chromium.net.NetworkChangeNotifierTest.testNetworkChangeNotifierJavaObservers',
         ],
       },
-      'android-12-x64-rel': {
-        'args': [
-          # crbug.com/1292197
-          '--gtest_filter=-org.chromium.android_webview.test.devui.HomeFragmentTest.testLongPressCopy*',
-        ],
-      },
       'android-marshmallow-x86-fyi-rel-reviver': {
         'swarming': {
           'shards': 9,
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 8cfa5eb..f397981 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -1813,11 +1813,7 @@
         },
       },
       'compositor_unittests': {},
-      'content_unittests': {
-        'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter',
-        ],
-      },
+      'content_unittests': {},
       'crypto_unittests': {},
       'events_unittests': {},
       'filesystem_service_unittests': {},
@@ -3948,7 +3944,11 @@
 
     'lacros_skylab_amd64_fyi': {
       'lacros_fyi_tast_tests': {
-        'tast_expr': '("group:mainline" && "dep:lacros" && !informational || "name:lacros.VariationSmoke")',
+        'tast_expr': '("group:mainline" && "dep:lacros" && !informational)',
+        'timeout_sec': 10800,
+      },
+      'lacros_variations_tast_tests': {
+        'tast_expr': '("name:lacros.VariationSmoke")',
         'timeout_sec': 10800,
       },
       'ozone_unittests': {
@@ -4435,6 +4435,9 @@
     'paeverywhere_common_tests': {
       # Run popular tests other than capture_unittests, crashpad_tests,
       # content_browsertests, and perfetto_unittests because they fail.
+      #
+      # browser_tests is said to be somewhat flaky for Mac
+      # (crbug.com/1201386), so we exclude that as well.
       'absl_hardening_tests': {},
       'angle_unittests': {
         'args': [
@@ -4452,11 +4455,6 @@
       'blink_unittests': {},
       'boringssl_crypto_tests': {},
       'boringssl_ssl_tests': {},
-      'browser_tests': {
-        'swarming': {
-          'shards': 10,
-        },
-      },
       'cast_unittests': {},
       'components_browsertests': {},
       'components_unittests': {
@@ -5146,7 +5144,6 @@
       'cast_runner_browsertests': {},
       'cast_runner_integration_tests_cfv1': {},
       'cast_runner_unittests': {},
-      'cr_fuchsia_base_unittests': {},
       'web_engine_browsertests': {},
       'web_engine_integration_tests': {
         'args': [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 258abb6..2454466d 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -510,23 +510,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.18'
+          'revision': 'version:104.0.5112.23'
         }
       ]
     }
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=103',
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
+      '--impl-version=103'
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -534,10 +534,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.61',
+          'revision': 'version:103.0.5060.62'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -654,23 +654,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.18'
+          'revision': 'version:104.0.5112.23'
         }
       ]
     }
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--implementation-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--impl-version=103',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--implementation-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
+      '--impl-version=103'
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -678,10 +678,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.61',
+          'revision': 'version:103.0.5060.62'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -798,23 +798,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.18'
+          'revision': 'version:104.0.5112.23'
         }
       ]
     }
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--client-version=103',
+      '--webview-apk-path=apks/SystemWebView.apk',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
+      '--client-version=103'
     ],
     'identifier': 'with_client_from_103',
     'swarming': {
@@ -822,10 +822,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.61',
+          'revision': 'version:103.0.5060.62'
         }
-      ],
-    },
+      ]
+    }
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -926,8 +926,8 @@
   'CROS_ATLAS_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '104.0.5107.2',
-      'cros_img': 'atlas-release/R105-14916.0.0',
+      'cros_chrome_version': '105.0.5125.0',
+      'cros_img': 'atlas-release/R105-14929.0.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_RELEASE_LKGM',
@@ -962,8 +962,8 @@
   'CROS_EVE_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '104.0.5107.2',
-      'cros_img': 'eve-release/R105-14916.0.0',
+      'cros_chrome_version': '105.0.5125.0',
+      'cros_img': 'eve-release/R105-14929.0.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_LKGM',
@@ -971,8 +971,8 @@
   'CROS_EVE_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '104.0.5112.6',
-      'cros_img': 'eve-release/R104-14909.7.0',
+      'cros_chrome_version': '104.0.5112.9',
+      'cros_img': 'eve-release/R104-14909.11.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_DEV',
@@ -1007,8 +1007,8 @@
   'CROS_HANA_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '104.0.5107.2',
-      'cros_img': 'hana-release/R105-14916.0.0',
+      'cros_chrome_version': '105.0.5125.0',
+      'cros_img': 'hana-release/R105-14929.0.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_LKGM',
@@ -1016,8 +1016,8 @@
   'CROS_HANA_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '104.0.5112.6',
-      'cros_img': 'hana-release/R104-14909.7.0',
+      'cros_chrome_version': '104.0.5112.9',
+      'cros_img': 'hana-release/R104-14909.11.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_DEV',
@@ -1043,8 +1043,8 @@
   'CROS_JACUZZI_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_chrome_version': '104.0.5107.2',
-      'cros_img': 'jacuzzi-release/R105-14916.0.0',
+      'cros_chrome_version': '105.0.5125.0',
+      'cros_img': 'jacuzzi-release/R105-14929.0.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_LKGM',
@@ -1052,8 +1052,8 @@
   'CROS_JACUZZI_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_chrome_version': '104.0.5112.6',
-      'cros_img': 'jacuzzi-release/R104-14909.7.0',
+      'cros_chrome_version': '104.0.5112.9',
+      'cros_img': 'jacuzzi-release/R104-14909.11.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_DEV',
@@ -1079,8 +1079,8 @@
   'CROS_OCTOPUS_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '104.0.5107.2',
-      'cros_img': 'octopus-release/R105-14916.0.0',
+      'cros_chrome_version': '105.0.5125.0',
+      'cros_img': 'octopus-release/R105-14929.0.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_LKGM',
@@ -1088,8 +1088,8 @@
   'CROS_OCTOPUS_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '104.0.5112.6',
-      'cros_img': 'octopus-release/R104-14909.7.0',
+      'cros_chrome_version': '104.0.5112.9',
+      'cros_img': 'octopus-release/R104-14909.11.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_DEV',
@@ -1106,8 +1106,8 @@
   'CROS_OCTOPUS_RELEASE_STABLE': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '102.0.5005.75',
-      'cros_img': 'octopus-release/R102-14695.85.0',
+      'cros_chrome_version': '102.0.5005.125',
+      'cros_img': 'octopus-release/R102-14695.107.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_STABLE',
@@ -1115,8 +1115,8 @@
   'CROS_STRONGBAD_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '104.0.5107.2',
-      'cros_img': 'strongbad-release/R105-14916.0.0',
+      'cros_chrome_version': '105.0.5125.0',
+      'cros_img': 'strongbad-release/R105-14929.0.0',
     },
     'enabled': True,
     'identifier': 'STRONGBAD_RELEASE_LKGM',
@@ -1124,8 +1124,8 @@
   'CROS_STRONGBAD_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '104.0.5112.6',
-      'cros_img': 'strongbad-release/R104-14909.7.0',
+      'cros_chrome_version': '104.0.5112.9',
+      'cros_img': 'strongbad-release/R104-14909.11.0',
     },
     'enabled': True,
     'identifier': 'strongbad_RELEASE_DEV',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 4b6b4386..3b82f6f 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -5337,6 +5337,16 @@
           'all'
         ],
       },
+      'Mac Builder reclient staging': {
+        'additional_compile_targets': [
+          'all',
+        ],
+      },
+      'Mac Builder reclient test': {
+        'additional_compile_targets': [
+          'all',
+        ],
+      },
       'Simple Chrome Builder reclient staging': {
         # Copied from
         # https://source.chromium.org/chromium/chromium/src/+/main:testing/buildbot/waterfalls.pyl;l=1567;drc=e8a03fce50115b247a6032f8ed922b6db62f11f6
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 58ab8287..2738c98 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -43,31 +43,6 @@
             ]
         }
     ],
-    "AddToHomescreenIPH": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "EnabledTextBubble_20210819",
-                    "params": {
-                        "availability": ">=0",
-                        "event_1": "name:add_to_homescreen_text_bubble_iph_trigger;comparator:==0;window:15;storage:90",
-                        "event_trigger": "name:add_to_homescreen_text_bubble_iph_trigger;comparator:<2;window:90;storage:90",
-                        "event_used": "name:add_to_homescreen_dialog_shown;comparator:==0;window:90;storage:90",
-                        "session_rate": "<1",
-                        "use_message": "false",
-                        "use_text_bubble": "true"
-                    },
-                    "enable_features": [
-                        "AddToHomescreenIPH",
-                        "IPH_AddToHomescreenTextBubble"
-                    ]
-                }
-            ]
-        }
-    ],
     "AlignWakeUps": [
         {
             "platforms": [
@@ -1059,6 +1034,48 @@
             ]
         }
     ],
+    "AutofillFillAndImportFromMoreFields": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "chromeos_lacros",
+                "ios",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "AutofillFillAndImportFromMoreFields"
+                    ]
+                }
+            ]
+        }
+    ],
+    "AutofillFillCreditCardAsPerFormatString": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "chromeos_lacros",
+                "ios",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "AutofillFillCreditCardAsPerFormatString"
+                    ]
+                }
+            ]
+        }
+    ],
     "AutofillFixServerQueriesIfPasswordManagerIsEnabled": [
         {
             "platforms": [
@@ -1217,6 +1234,49 @@
             ]
         }
     ],
+    "AutofillRationalizeStreetAddressAndAddressLine": [
+        {
+            "platforms": [
+                "android",
+                "android_webview",
+                "chromeos",
+                "chromeos_lacros",
+                "ios",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "AutofillRationalizeStreetAddressAndAddressLine"
+                    ]
+                }
+            ]
+        }
+    ],
+    "AutofillRefillModifiedCreditCardExpirationDates": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "chromeos_lacros",
+                "ios",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "AutofillRefillModifiedCreditCardExpirationDates"
+                    ]
+                }
+            ]
+        }
+    ],
     "AutofillRemoveInaccessibleProfileValues": [
         {
             "platforms": [
@@ -3689,8 +3749,9 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled_20220425",
+                    "name": "AsyncEarly_20220617",
                     "enable_features": [
+                        "EarlyEstablishGpuChannel",
                         "EstablishGpuChannelAsync"
                     ]
                 }
@@ -5109,21 +5170,6 @@
             ]
         }
     ],
-    "LacrosNonSyncingProfiles": [
-        {
-            "platforms": [
-                "chromeos_lacros"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "LacrosNonSyncingProfiles"
-                    ]
-                }
-            ]
-        }
-    ],
     "LanguagePacksSpanishHandwriting": [
         {
             "platforms": [
@@ -6860,7 +6906,7 @@
             ],
             "experiments": [
                 {
-                    "name": "EnabledWithContinueSection_20220615",
+                    "name": "EnabledWithContinueSection_20220621",
                     "params": {
                         "enable_continue": "true"
                     },
@@ -6872,7 +6918,7 @@
                     ]
                 },
                 {
-                    "name": "EnabledWithoutContinueSection_20220615",
+                    "name": "EnabledWithoutContinueSection_20220621",
                     "params": {
                         "enable_continue": "false"
                     },
@@ -6882,6 +6928,17 @@
                     "disable_features": [
                         "LauncherItemSuggest"
                     ]
+                },
+                {
+                    "name": "EnabledWithContinueAndMultipleQueries_20220621",
+                    "params": {
+                        "enable_continue": "true",
+                        "multiple_queries_per_session": "true"
+                    },
+                    "enable_features": [
+                        "LauncherItemSuggest",
+                        "ProductivityLauncher"
+                    ]
                 }
             ]
         }
@@ -9566,21 +9623,6 @@
             ]
         }
     ],
-    "WebViewNativeContextMenuPhase2": [
-        {
-            "platforms": [
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "WebViewNativeContextMenuPhase2"
-                    ]
-                }
-            ]
-        }
-    ],
     "WebViewNewInvalidateHeuristic": [
         {
             "platforms": [
diff --git a/third_party/blink/common/chrome_debug_urls.cc b/third_party/blink/common/chrome_debug_urls.cc
index ee996ef..c68329c 100644
--- a/third_party/blink/common/chrome_debug_urls.cc
+++ b/third_party/blink/common/chrome_debug_urls.cc
@@ -54,6 +54,7 @@
 #if BUILDFLAG(IS_WIN)
 const char kChromeUIBrowserHeapCorruptionURL[] =
     "chrome://inducebrowserheapcorruption/";
+const char kChromeUICfgViolationCrashURL[] = "chrome://crash/cfg";
 const char kChromeUIHeapCorruptionCrashURL[] = "chrome://heapcorruptioncrash/";
 #endif
 
@@ -102,6 +103,8 @@
 #endif
 
 #if BUILDFLAG(IS_WIN)
+  if (url == kChromeUICfgViolationCrashURL)
+    return true;
   if (url == kChromeUIHeapCorruptionCrashURL)
     return true;
 #endif
@@ -219,6 +222,11 @@
   }
 
 #if BUILDFLAG(IS_WIN)
+  if (url == kChromeUICfgViolationCrashURL) {
+    LOG(ERROR) << "Intentionally causing cfg crash because user navigated to "
+               << url.spec();
+    base::debug::win::TerminateWithControlFlowViolation();
+  }
   if (url == kChromeUIHeapCorruptionCrashURL) {
     LOG(ERROR)
         << "Intentionally causing heap corruption because user navigated to "
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 31bc729..54bb1dd 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -406,6 +406,12 @@
 const char kIntensiveWakeUpThrottling_GracePeriodSeconds_Name[] =
     "grace_period_seconds";
 
+// If enabled, the grace period of features::kIntensiveWakeUpThrottling will be
+// 10 seconds when a background page is loaded.
+const base::Feature kQuickIntensiveWakeUpThrottlingAfterLoading{
+    "QuickIntensiveWakeUpThrottlingAfterLoading",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Throttles Javascript timer wake ups on foreground pages.
 const base::Feature kThrottleForegroundTimers{
     "ThrottleForegroundTimers", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -1378,6 +1384,10 @@
 const base::Feature kBackForwardCacheAppBanner{
     "BackForwardCacheAppBanner", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kBackForwardCacheEnabledForNonPluginEmbed{
+    "BackForwardCacheEnabledForNonPluginEmbed",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Initialize CSSDefaultStyleSheets early in renderer startup.
 const base::Feature kDefaultStyleSheetsEarlyInit{
     "DefaultStyleSheetsEarlyInit", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/third_party/blink/common/interest_group/interest_group.cc b/third_party/blink/common/interest_group/interest_group.cc
index 89cd143a..63afaa1 100644
--- a/third_party/blink/common/interest_group/interest_group.cc
+++ b/third_party/blink/common/interest_group/interest_group.cc
@@ -13,7 +13,7 @@
 #include "base/time/time.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-forward.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 #include "url/url_constants.h"
@@ -64,13 +64,15 @@
   return render_url == other.render_url && metadata == other.metadata;
 }
 
-InterestGroup::InterestGroup() : priority(0.0) {}
+InterestGroup::InterestGroup()
+    : priority(0.0), execution_mode(ExecutionMode::kCompatibilityMode) {}
 
 InterestGroup::InterestGroup(
     base::Time expiry,
     url::Origin owner,
     std::string name,
     double priority,
+    blink::mojom::InterestGroup::ExecutionMode execution_mode,
     absl::optional<GURL> bidding_url,
     absl::optional<GURL> bidding_wasm_helper_url,
     absl::optional<GURL> daily_update_url,
@@ -83,6 +85,7 @@
       owner(std::move(owner)),
       name(std::move(name)),
       priority(priority),
+      execution_mode(execution_mode),
       bidding_url(std::move(bidding_url)),
       bidding_wasm_helper_url(std::move(bidding_wasm_helper_url)),
       daily_update_url(std::move(daily_update_url)),
@@ -104,6 +107,11 @@
   if (!priority || !std::isfinite(*priority))
     return false;
 
+  if (!execution_mode ||
+      *execution_mode !=
+          blink::mojom::InterestGroup::ExecutionMode::kCompatibilityMode)
+    return false;
+
   if (bidding_url && !IsUrlAllowed(*bidding_url, *this))
     return false;
 
@@ -147,8 +155,10 @@
   size += owner.Serialize().size();
   size += name.size();
 
-  // priority is not stored as nullable, so only count the value size.
+  // priority and execution_mode are not stored as nullable, so only count the
+  // value size.
   size += sizeof(decltype(priority)::value_type);
+  size += sizeof(decltype(execution_mode)::value_type);
 
   if (bidding_url)
     size += bidding_url->spec().length();
@@ -176,13 +186,14 @@
 }
 
 bool InterestGroup::IsEqualForTesting(const InterestGroup& other) const {
-  return std::tie(expiry, owner, name, priority, bidding_url,
+  return std::tie(expiry, owner, name, priority, execution_mode, bidding_url,
                   bidding_wasm_helper_url, daily_update_url,
                   trusted_bidding_signals_url, trusted_bidding_signals_keys,
                   user_bidding_signals, ads, ad_components) ==
          std::tie(other.expiry, other.owner, other.name, other.priority,
-                  other.bidding_url, other.bidding_wasm_helper_url,
-                  other.daily_update_url, other.trusted_bidding_signals_url,
+                  other.execution_mode, other.bidding_url,
+                  other.bidding_wasm_helper_url, other.daily_update_url,
+                  other.trusted_bidding_signals_url,
                   other.trusted_bidding_signals_keys,
                   other.user_bidding_signals, other.ads, other.ad_components);
 }
diff --git a/third_party/blink/common/interest_group/interest_group_mojom_traits.cc b/third_party/blink/common/interest_group/interest_group_mojom_traits.cc
index e851ee5..eef6088 100644
--- a/third_party/blink/common/interest_group/interest_group_mojom_traits.cc
+++ b/third_party/blink/common/interest_group/interest_group_mojom_traits.cc
@@ -23,6 +23,7 @@
 bool StructTraits<blink::mojom::InterestGroupDataView, blink::InterestGroup>::
     Read(blink::mojom::InterestGroupDataView data, blink::InterestGroup* out) {
   out->priority = data.priority();
+  out->execution_mode = data.execution_mode();
   if (!data.ReadExpiry(&out->expiry) || !data.ReadOwner(&out->owner) ||
       !data.ReadName(&out->name) || !data.ReadBiddingUrl(&out->bidding_url) ||
       !data.ReadBiddingWasmHelperUrl(&out->bidding_wasm_helper_url) ||
diff --git a/third_party/blink/common/manifest/manifest.cc b/third_party/blink/common/manifest/manifest.cc
index c25581a..efb8f72 100644
--- a/third_party/blink/common/manifest/manifest.cc
+++ b/third_party/blink/common/manifest/manifest.cc
@@ -93,4 +93,32 @@
   return AsTuple(*this) == AsTuple(other);
 }
 
+Manifest::HomeTabParams::HomeTabParams() = default;
+
+Manifest::HomeTabParams::~HomeTabParams() = default;
+
+bool Manifest::HomeTabParams::operator==(const HomeTabParams& other) const {
+  return icons == other.icons;
+}
+
+Manifest::NewTabButtonParams::NewTabButtonParams() = default;
+
+Manifest::NewTabButtonParams::~NewTabButtonParams() = default;
+
+bool Manifest::NewTabButtonParams::operator==(
+    const NewTabButtonParams& other) const {
+  return url == other.url;
+}
+
+Manifest::TabStrip::TabStrip() = default;
+
+Manifest::TabStrip::~TabStrip() = default;
+
+bool Manifest::TabStrip::operator==(const TabStrip& other) const {
+  auto AsTuple = [](const auto& item) {
+    return std::tie(item.home_tab, item.new_tab_button);
+  };
+  return AsTuple(*this) == AsTuple(other);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/common/manifest/manifest_mojom_traits.cc b/third_party/blink/common/manifest/manifest_mojom_traits.cc
index 5435a00..b90d81b 100644
--- a/third_party/blink/common/manifest/manifest_mojom_traits.cc
+++ b/third_party/blink/common/manifest/manifest_mojom_traits.cc
@@ -213,4 +213,73 @@
   return true;
 }
 
+bool StructTraits<blink::mojom::HomeTabParamsDataView,
+                  ::blink::Manifest::HomeTabParams>::
+    Read(blink::mojom::HomeTabParamsDataView data,
+         ::blink::Manifest::HomeTabParams* out) {
+  return data.ReadIcons(&out->icons);
+}
+
+bool StructTraits<blink::mojom::NewTabButtonParamsDataView,
+                  ::blink::Manifest::NewTabButtonParams>::
+    Read(blink::mojom::NewTabButtonParamsDataView data,
+         ::blink::Manifest::NewTabButtonParams* out) {
+  return data.ReadUrl(&out->url);
+}
+
+bool UnionTraits<blink::mojom::HomeTabUnionDataView,
+                 ::blink::Manifest::TabStrip::HomeTab>::
+    Read(blink::mojom::HomeTabUnionDataView data,
+         blink::Manifest::TabStrip::HomeTab* out) {
+  switch (data.tag()) {
+    case blink::mojom::HomeTabUnionDataView::Tag::kVisibility:
+      ::blink::mojom::TabStripMemberVisibility visibility;
+      if (!data.ReadVisibility(&visibility))
+        return false;
+      *out = visibility;
+      return true;
+    case blink::mojom::HomeTabUnionDataView::Tag::kParams:
+      ::blink::Manifest::HomeTabParams params;
+      if (!data.ReadParams(&params))
+        return false;
+      *out = params;
+      return true;
+  }
+  return false;
+}
+
+bool UnionTraits<blink::mojom::NewTabButtonUnionDataView,
+                 ::blink::Manifest::TabStrip::NewTabButton>::
+    Read(blink::mojom::NewTabButtonUnionDataView data,
+         ::blink::Manifest::TabStrip::NewTabButton* out) {
+  switch (data.tag()) {
+    case blink::mojom::NewTabButtonUnionDataView::Tag::kVisibility:
+      ::blink::mojom::TabStripMemberVisibility visibility;
+      if (!data.ReadVisibility(&visibility))
+        return false;
+      *out = visibility;
+      return true;
+    case blink::mojom::NewTabButtonUnionDataView::Tag::kParams:
+      ::blink::Manifest::NewTabButtonParams params;
+      if (!data.ReadParams(&params))
+        return false;
+      *out = params;
+      return true;
+  }
+  return false;
+}
+
+bool StructTraits<blink::mojom::ManifestTabStripDataView,
+                  ::blink::Manifest::TabStrip>::
+    Read(blink::mojom::ManifestTabStripDataView data,
+         ::blink::Manifest::TabStrip* out) {
+  if (!data.ReadHomeTab(&out->home_tab))
+    return false;
+
+  if (!data.ReadNewTabButton(&out->new_tab_button))
+    return false;
+
+  return true;
+}
+
 }  // namespace mojo
diff --git a/third_party/blink/common/mediastream/media_stream_mojom_traits.cc b/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
index 80fcf4af..27f3b64 100644
--- a/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
+++ b/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
@@ -68,6 +68,7 @@
 #endif
   out->hotword_enabled = input.hotword_enabled();
   out->disable_local_echo = input.disable_local_echo();
+  out->exclude_system_audio = input.exclude_system_audio();
   out->request_pan_tilt_zoom_permission =
       input.request_pan_tilt_zoom_permission();
   return true;
diff --git a/third_party/blink/public/common/chrome_debug_urls.h b/third_party/blink/public/common/chrome_debug_urls.h
index a23ef24..03fa165 100644
--- a/third_party/blink/public/common/chrome_debug_urls.h
+++ b/third_party/blink/public/common/chrome_debug_urls.h
@@ -45,6 +45,7 @@
 #endif
 #if BUILDFLAG(IS_WIN)
 BLINK_COMMON_EXPORT extern const char kChromeUIBrowserHeapCorruptionURL[];
+BLINK_COMMON_EXPORT extern const char kChromeUICfgViolationCrashURL[];
 BLINK_COMMON_EXPORT extern const char kChromeUIHeapCorruptionCrashURL[];
 #endif
 
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 29a6348..a17db30a3 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -172,6 +172,8 @@
 BLINK_COMMON_EXPORT extern const base::Feature kIntensiveWakeUpThrottling;
 BLINK_COMMON_EXPORT extern const char
     kIntensiveWakeUpThrottling_GracePeriodSeconds_Name[];
+BLINK_COMMON_EXPORT extern const base::Feature
+    kQuickIntensiveWakeUpThrottlingAfterLoading;
 BLINK_COMMON_EXPORT extern const base::Feature kThrottleForegroundTimers;
 
 #if BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
@@ -641,6 +643,11 @@
 // back/forward cache.
 BLINK_COMMON_EXPORT extern const base::Feature kBackForwardCacheAppBanner;
 
+// Enables back/forward cache for non-plugin embeds.
+// TODO(crbug.com/1325192): Remove once the bug is resolved.
+BLINK_COMMON_EXPORT
+extern const base::Feature kBackForwardCacheEnabledForNonPluginEmbed;
+
 BLINK_COMMON_EXPORT extern const base::Feature kDefaultStyleSheetsEarlyInit;
 
 BLINK_COMMON_EXPORT extern const base::Feature kSystemColorChooser;
diff --git a/third_party/blink/public/common/interest_group/interest_group.h b/third_party/blink/public/common/interest_group/interest_group.h
index 8ec1b87b..69857986 100644
--- a/third_party/blink/public/common/interest_group/interest_group.h
+++ b/third_party/blink/public/common/interest_group/interest_group.h
@@ -25,6 +25,7 @@
 //
 // https://github.com/WICG/turtledove/blob/main/FLEDGE.md#11-joining-interest-groups
 struct BLINK_COMMON_EXPORT InterestGroup {
+  using ExecutionMode = blink::mojom::InterestGroup_ExecutionMode;
   // An advertisement to display for an interest group. Typemapped to
   // blink::mojom::InterestGroupAd.
   // https://github.com/WICG/turtledove/blob/main/FLEDGE.md#12-interest-group-attributes
@@ -58,6 +59,7 @@
       url::Origin owner,
       std::string name,
       double priority,
+      ExecutionMode execution_mode,
       absl::optional<GURL> bidding_url,
       absl::optional<GURL> bidding_wasm_helper_url,
       absl::optional<GURL> daily_update_url,
@@ -83,6 +85,8 @@
   url::Origin owner;
   std::string name;
   absl::optional<double> priority;  // Needs to be optional for updates.
+  absl::optional<ExecutionMode>
+      execution_mode;  // Needs to be optional for updates.
   absl::optional<GURL> bidding_url;
   absl::optional<GURL> bidding_wasm_helper_url;
   absl::optional<GURL> daily_update_url;
@@ -91,7 +95,7 @@
   absl::optional<std::string> user_bidding_signals;
   absl::optional<std::vector<InterestGroup::Ad>> ads, ad_components;
 
-  static_assert(__LINE__ == 94, R"(
+  static_assert(__LINE__ == 98, R"(
 If modifying InterestGroup fields, make sure to also modify:
 
 * IsValid(), EstimateSize(), and IsEqualForTesting() in this class
diff --git a/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h b/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h
index 19ae4260..49c4fd0 100644
--- a/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h
+++ b/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h
@@ -12,7 +12,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/common_export.h"
 #include "third_party/blink/public/common/interest_group/interest_group.h"
-#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-forward.h"
+#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -54,6 +54,13 @@
     return interest_group.priority.value_or(0);
   }
 
+  static blink::InterestGroup::ExecutionMode execution_mode(
+      const blink::InterestGroup& interest_group) {
+    DCHECK(interest_group.execution_mode);
+    return interest_group.execution_mode.value_or(
+        blink::InterestGroup::ExecutionMode::kCompatibilityMode);
+  }
+
   static const absl::optional<GURL>& bidding_url(
       const blink::InterestGroup& interest_group) {
     return interest_group.bidding_url;
diff --git a/third_party/blink/public/common/manifest/manifest.h b/third_party/blink/public/common/manifest/manifest.h
index a978b0e80..5945aee 100644
--- a/third_party/blink/public/common/manifest/manifest.h
+++ b/third_party/blink/public/common/manifest/manifest.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/blink/public/common/common_export.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-shared.h"
 #include "ui/gfx/geometry/size.h"
@@ -153,6 +154,42 @@
     absl::optional<std::string> short_name;
     absl::optional<std::string> description;
   };
+
+  // Parameters for the home tab customisation to the tab strip.
+  struct BLINK_COMMON_EXPORT HomeTabParams {
+    HomeTabParams();
+    ~HomeTabParams();
+
+    bool operator==(const HomeTabParams& other) const;
+
+    std::vector<ImageResource> icons;
+  };
+
+  // Parameters for the new tab button customisation to the tab strip.
+  struct BLINK_COMMON_EXPORT NewTabButtonParams {
+    NewTabButtonParams();
+    ~NewTabButtonParams();
+
+    bool operator==(const NewTabButtonParams& other) const;
+
+    absl::optional<GURL> url;
+  };
+
+  // Structure containing customisations for the tab strip.
+  struct BLINK_COMMON_EXPORT TabStrip {
+    TabStrip();
+    ~TabStrip();
+
+    bool operator==(const TabStrip& other) const;
+
+    using Visibility = blink::mojom::TabStripMemberVisibility;
+    using HomeTab = absl::variant<Visibility, blink::Manifest::HomeTabParams>;
+    using NewTabButton =
+        absl::variant<Visibility, blink::Manifest::NewTabButtonParams>;
+
+    HomeTab home_tab;
+    NewTabButton new_tab_button;
+  };
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/common/manifest/manifest_mojom_traits.h b/third_party/blink/public/common/manifest/manifest_mojom_traits.h
index 2e634ef8..fd3016e4 100644
--- a/third_party/blink/public/common/manifest/manifest_mojom_traits.h
+++ b/third_party/blink/public/common/manifest/manifest_mojom_traits.h
@@ -12,6 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/blink/public/common/common_export.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
 
@@ -232,6 +233,103 @@
                    ::blink::Manifest::TranslationItem* out);
 };
 
+template <>
+struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::HomeTabParamsDataView,
+                                        ::blink::Manifest::HomeTabParams> {
+  static const std::vector<::blink::Manifest::ImageResource>& icons(
+      const ::blink::Manifest::HomeTabParams& params) {
+    return params.icons;
+  }
+
+  static bool Read(blink::mojom::HomeTabParamsDataView data,
+                   ::blink::Manifest::HomeTabParams* out);
+};
+
+template <>
+struct BLINK_COMMON_EXPORT
+    StructTraits<blink::mojom::NewTabButtonParamsDataView,
+                 ::blink::Manifest::NewTabButtonParams> {
+  static const absl::optional<GURL>& url(
+      const ::blink::Manifest::NewTabButtonParams& params) {
+    return params.url;
+  }
+
+  static bool Read(blink::mojom::NewTabButtonParamsDataView data,
+                   ::blink::Manifest::NewTabButtonParams* out);
+};
+
+template <>
+struct BLINK_COMMON_EXPORT UnionTraits<blink::mojom::HomeTabUnionDataView,
+                                       ::blink::Manifest::TabStrip::HomeTab> {
+  static blink::mojom::HomeTabUnionDataView::Tag GetTag(
+      const ::blink::Manifest::TabStrip::HomeTab& value) {
+    if (absl::holds_alternative<blink::mojom::TabStripMemberVisibility>(
+            value)) {
+      return blink::mojom::HomeTabUnion::Tag::kVisibility;
+    } else {
+      return blink::mojom::HomeTabUnion::Tag::kParams;
+    }
+  }
+
+  static ::blink::mojom::TabStripMemberVisibility visibility(
+      const ::blink::Manifest::TabStrip::HomeTab& value) {
+    return absl::get<blink::mojom::TabStripMemberVisibility>(value);
+  }
+
+  static const ::blink::Manifest::HomeTabParams& params(
+      const ::blink::Manifest::TabStrip::HomeTab& value) {
+    return absl::get<blink::Manifest::HomeTabParams>(value);
+  }
+
+  static bool Read(blink::mojom::HomeTabUnionDataView data,
+                   ::blink::Manifest::TabStrip::HomeTab* out);
+};
+
+template <>
+struct BLINK_COMMON_EXPORT
+    UnionTraits<blink::mojom::NewTabButtonUnionDataView,
+                ::blink::Manifest::TabStrip::NewTabButton> {
+  static blink::mojom::NewTabButtonUnionDataView::Tag GetTag(
+      const ::blink::Manifest::TabStrip::NewTabButton& value) {
+    if (absl::holds_alternative<blink::mojom::TabStripMemberVisibility>(
+            value)) {
+      return blink::mojom::NewTabButtonUnion::Tag::kVisibility;
+    } else {
+      return blink::mojom::NewTabButtonUnion::Tag::kParams;
+    }
+  }
+
+  static ::blink::mojom::TabStripMemberVisibility visibility(
+      const ::blink::Manifest::TabStrip::NewTabButton& value) {
+    return absl::get<blink::mojom::TabStripMemberVisibility>(value);
+  }
+
+  static const ::blink::Manifest::NewTabButtonParams& params(
+      const ::blink::Manifest::TabStrip::NewTabButton& value) {
+    return absl::get<blink::Manifest::NewTabButtonParams>(value);
+  }
+
+  static bool Read(blink::mojom::NewTabButtonUnionDataView data,
+                   ::blink::Manifest::TabStrip::NewTabButton* out);
+};
+
+template <>
+struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::ManifestTabStripDataView,
+                                        ::blink::Manifest::TabStrip> {
+  static const ::blink::Manifest::TabStrip::HomeTab& home_tab(
+      const ::blink::Manifest::TabStrip& tab_strip) {
+    return tab_strip.home_tab;
+  }
+
+  static const ::blink::Manifest::TabStrip::NewTabButton& new_tab_button(
+      const ::blink::Manifest::TabStrip& tab_strip) {
+    return tab_strip.new_tab_button;
+  }
+
+  static bool Read(blink::mojom::ManifestTabStripDataView data,
+                   ::blink::Manifest::TabStrip* out);
+};
+
 }  // namespace mojo
 
 #endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_MANIFEST_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/common/media/video_capture.h b/third_party/blink/public/common/media/video_capture.h
index 33f4f1f..6feaee3 100644
--- a/third_party/blink/public/common/media/video_capture.h
+++ b/third_party/blink/public/common/media/video_capture.h
@@ -49,6 +49,10 @@
 // Callback for delivering dropped frame notifications.
 using VideoCaptureNotifyFrameDroppedCB = base::RepeatingClosure;
 
+// Callback for informing when new crop-versions are applied.
+using VideoCaptureCropVersionCB =
+    base::RepeatingCallback<void(uint32_t crop_version)>;
+
 using VideoCaptureDeviceFormatsCB =
     base::OnceCallback<void(const media::VideoCaptureFormats&)>;
 
diff --git a/third_party/blink/public/common/mediastream/media_stream_controls.h b/third_party/blink/public/common/mediastream/media_stream_controls.h
index 33621374..06b6ffd 100644
--- a/third_party/blink/public/common/mediastream/media_stream_controls.h
+++ b/third_party/blink/public/common/mediastream/media_stream_controls.h
@@ -49,10 +49,12 @@
 
   TrackControls audio;
   TrackControls video;
+
   // Hotword functionality (chromeos only)
   // TODO(crbug.com/577627): this is now never set and needs to be removed.
   bool hotword_enabled = false;
   bool disable_local_echo = false;
+  bool exclude_system_audio = false;
   bool request_pan_tilt_zoom_permission = false;
 };
 
diff --git a/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h b/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h
index e8d2aa4..20932342 100644
--- a/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h
+++ b/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h
@@ -104,6 +104,10 @@
     return controls.disable_local_echo;
   }
 
+  static bool exclude_system_audio(const blink::StreamControls& controls) {
+    return controls.exclude_system_audio;
+  }
+
   static bool request_pan_tilt_zoom_permission(
       const blink::StreamControls& controls) {
     return controls.request_pan_tilt_zoom_permission;
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index a5031fa..2075e9e 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -650,6 +650,11 @@
           mojom = "blink.mojom.ManifestTranslationItem"
           cpp = "::blink::Manifest::TranslationItem"
         },
+
+        {
+          mojom = "blink.mojom.ManifestTabStrip"
+          cpp = "::blink::Manifest::TabStrip"
+        },
       ]
       traits_headers = [
         "//third_party/blink/public/common/common_export.h",
diff --git a/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom b/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
index 3f5d776..a523dff7 100644
--- a/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
+++ b/third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom
@@ -54,6 +54,11 @@
   VisibilityState visibility_state;
 };
 
+// Represents a screen display.
+struct CrosScreenInfo {
+  int32 width;
+};
+
 // Chrome OS Window Management API for System Extensions.
 // Called by System Extensions Renderers and implemented by Ash Chrome.
 interface CrosWindowManagement {
@@ -89,6 +94,9 @@
 
   // Closes the window identified by id if it exists, else do nothing.
   Close(mojo_base.mojom.UnguessableToken id) => (CrosWindowManagementStatus value);
+
+  // Returns all screens.
+  GetAllScreens() => (array<CrosScreenInfo> screens);
 };
 
 // Interface used by the browser to send the `start` event to Window Management
diff --git a/third_party/blink/public/mojom/conversions/attribution_data_host.mojom b/third_party/blink/public/mojom/conversions/attribution_data_host.mojom
index 76fd89b..c68b889 100644
--- a/third_party/blink/public/mojom/conversions/attribution_data_host.mojom
+++ b/third_party/blink/public/mojom/conversions/attribution_data_host.mojom
@@ -106,6 +106,10 @@
   // filter data matches.
   AttributionFilterData filters;
 
+  // If non-empty, this trigger will be ignored unless the attributed source's
+  // filter data does *NOT* match.
+  AttributionFilterData not_filters;
+
   // List of all aggregatable trigger data objects declared by the trigger
   // header.
   array<AttributionAggregatableTriggerData> aggregatable_trigger_data;
diff --git a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
index c7b61dc..8875278 100644
--- a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
+++ b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
@@ -10,6 +10,7 @@
 import "services/network/public/mojom/chunked_data_pipe_getter.mojom";
 import "services/network/public/mojom/fetch_api.mojom";
 import "services/network/public/mojom/request_priority.mojom";
+import "services/network/public/mojom/trust_tokens.mojom";
 import "services/network/public/mojom/url_request.mojom";
 import "third_party/blink/public/mojom/blob/serialized_blob.mojom";
 import "third_party/blink/public/mojom/loader/request_context_frame_type.mojom";
@@ -202,4 +203,7 @@
   // a process that later intercepts the request, e.g., in a service worker
   // fetch event handler.
   string? devtools_stack_id;
+
+  // Specifies a Trust Token protocol operation if the request has one.
+  network.mojom.TrustTokenParams? trust_token_params;
 };
diff --git a/third_party/blink/public/mojom/interest_group/interest_group_types.mojom b/third_party/blink/public/mojom/interest_group/interest_group_types.mojom
index caddd77..035ca88 100644
--- a/third_party/blink/public/mojom/interest_group/interest_group_types.mojom
+++ b/third_party/blink/public/mojom/interest_group/interest_group_types.mojom
@@ -28,12 +28,35 @@
 //
 // https://github.com/WICG/turtledove/blob/main/FLEDGE.md#11-joining-interest-groups
 struct InterestGroup {
+  enum ExecutionMode {
+    // kCompatibilityMode creates a new context for every execution. This is
+    // potentially slow as it is only able to reuse the compilation cache from
+    // other interest groups with the same bidding script.
+    kCompatibilityMode,
+    // kGroupedByOriginMode, mode uses the same JavaScript context for groups
+    // with the same joining origin. This can be much faster, but to mitigate
+    // any privacy leaks FLEDGE will clear all of the interest groups for a
+    // joining origin if another origin joins or leaves one of the interest
+    // groups.
+    kGroupedByOriginMode,
+    // kFrozenContext mode uses a "frozen" JavaScript context to execute the
+    // bidding scripts for all interest groups that share a common biddnig
+    // script. Before the script is loaded the global object is recursively
+    // frozen to prevent persisting state. After the script is loaded, the
+    // script context is also frozen and checked for any state that may persist
+    // between function execution. If any potentially persistent state is
+    // identified, execution abandoned.
+    kFrozenContext,
+  };
+
   mojo_base.mojom.Time expiry;
   // `owner` must match the current frame URL's origin.
   url.mojom.Origin owner;
   string name;
   // `priority` of the interest group.
   double priority = 0.0;
+  // `execution_mode` of the interest group.
+  ExecutionMode execution_mode = kCompatibilityMode;
   // `bidding_url` must match the current frame URL's origin.
   url.mojom.Url? bidding_url;
   // `bidding_wasm_helper_url` must match the current frame URL's origin.
diff --git a/third_party/blink/public/mojom/mediastream/media_stream.mojom b/third_party/blink/public/mojom/mediastream/media_stream.mojom
index 33cf4c3..41cac8f 100644
--- a/third_party/blink/public/mojom/mediastream/media_stream.mojom
+++ b/third_party/blink/public/mojom/mediastream/media_stream.mojom
@@ -118,6 +118,7 @@
   TrackControls video;
   bool hotword_enabled;
   bool disable_local_echo;
+  bool exclude_system_audio;
   bool request_pan_tilt_zoom_permission;
 };
 
diff --git a/third_party/blink/public/platform/media/multi_buffer.h b/third_party/blink/public/platform/media/multi_buffer.h
index 3f9bdc4..448c9b7e 100644
--- a/third_party/blink/public/platform/media/multi_buffer.h
+++ b/third_party/blink/public/platform/media/multi_buffer.h
@@ -266,7 +266,7 @@
       std::vector<scoped_refptr<media::DataBuffer>>* output);
 
   // Increment max cache size by |size| (counted in blocks).
-  void IncrementMaxSize(int32_t size);
+  void IncrementMaxSize(int64_t size);
 
   // Returns how many bytes have been received by the data providers at position
   // |block|, which have not yet been submitted to the multibuffer cache.
diff --git a/third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h b/third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h
index 75a28b3..98e64fc 100644
--- a/third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h
+++ b/third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h
@@ -70,6 +70,11 @@
   // |deliver_frame_cb| will be called on the IO thread when a video
   // frame is ready.
   //
+  // |crop_version_cb| will be called on the IO thread when a new crop
+  // version is successfully applied, and it is guaranteed that all
+  // subsequent frames delivered to |deliver_frame_cb|, will have this
+  // crop version or later.
+  //
   // Returns a callback that is used to stop capturing. Note that stopping
   // video capture is not synchronous. Client should handle the case where
   // callbacks are called after capturing is instructed to stop, typically
@@ -78,7 +83,8 @@
       const media::VideoCaptureSessionId& id,
       const media::VideoCaptureParams& params,
       const VideoCaptureStateUpdateCB& state_update_cb,
-      const VideoCaptureDeliverFrameCB& deliver_frame_cb);
+      const VideoCaptureDeliverFrameCB& deliver_frame_cb,
+      const VideoCaptureCropVersionCB& crop_version_cb);
 
   // Requests that the video capturer send a frame "soon" (e.g., to resolve
   // picture loss or quality issues).
diff --git a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
index 33f8619..e45c359 100644
--- a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
+++ b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
@@ -88,6 +88,7 @@
                 const VideoCaptureDeliverFrameCB& frame_callback,
                 const VideoCaptureNotifyFrameDroppedCB& dropped_callback,
                 const EncodedVideoFrameCB& encoded_frame_callback,
+                const VideoCaptureCropVersionCB& crop_version_callback,
                 const VideoTrackSettingsCallback& settings_callback,
                 const VideoTrackFormatCallback& format_callback,
                 ConstraintsOnceCallback callback);
@@ -207,6 +208,13 @@
   virtual absl::optional<uint32_t> GetNextCropVersion();
 #endif
 
+  // Returns the current crop version.
+  // For an explanation of what a |crop_version| is, see Crop().
+  // The initial crop version is zero. On platforms where cropping is not
+  // supported (Android), and for sources that don't support cropping (audio),
+  // the crop version never goes over 0.
+  virtual uint32_t GetCropVersion() const;
+
   // Notifies the source about that the number of encoded sinks have been
   // updated. Note: Can only be called if the number of encoded sinks have
   // actually changed!
@@ -241,11 +249,17 @@
 
   // An implementation must start capturing frames after this method is called.
   // When the source has started or failed to start OnStartDone must be called.
-  // An implementation must call |frame_callback| on the IO thread with the
-  // captured frames, and |encoded_frame_callback| with encoded frames if
-  // supported and enabled via OnEncodedSinkEnabled.
-  virtual void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback,
-                               EncodedVideoFrameCB encoded_frame_callback) = 0;
+  // An implementation must call the following callbacks on the IO thread:
+  // * |frame_callback| with the captured frames.
+  // * |encoded_frame_callback| with encoded frames if supported and enabled
+  //   via OnEncodedSinkEnabled.
+  // * |crop_version_callback| whenever it is guaranteed that all subsequent
+  //   frames that |frame_callback| will be called for, will have either
+  //   the given crop version or higher.
+  virtual void StartSourceImpl(
+      VideoCaptureDeliverFrameCB frame_callback,
+      EncodedVideoFrameCB encoded_frame_callback,
+      VideoCaptureCropVersionCB crop_version_callback) = 0;
   void OnStartDone(mojom::MediaStreamRequestResult result);
 
   // A subclass that supports restart must override this method such that it
@@ -362,6 +376,7 @@
     VideoCaptureDeliverFrameCB frame_callback;
     VideoCaptureNotifyFrameDroppedCB notify_frame_dropped_callback;
     EncodedVideoFrameCB encoded_frame_callback;
+    VideoCaptureCropVersionCB crop_version_callback;
     VideoTrackSettingsCallback settings_callback;
     VideoTrackFormatCallback format_callback;
     // TODO(guidou): Make |adapter_settings| a regular field instead of a
diff --git a/third_party/blink/renderer/bindings/OWNERS b/third_party/blink/renderer/bindings/OWNERS
index 1ac6e19..6c24e22 100644
--- a/third_party/blink/renderer/bindings/OWNERS
+++ b/third_party/blink/renderer/bindings/OWNERS
@@ -10,6 +10,8 @@
 yukishiino@chromium.org
 
 per-file generated_in_core.gni=*
+per-file generated_in_extensions_chromeos.gni=*
 per-file generated_in_modules.gni=*
 per-file idl_in_core.gni=*
+per-file idl_in_extensions_chromeos.gni=*
 per-file idl_in_modules.gni=*
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
index 5574ed1e..07f5b10 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -1077,7 +1077,10 @@
 BackgroundInlineScriptStreamer::BackgroundInlineScriptStreamer(
     const String& text,
     v8::ScriptCompiler::CompileOptions compile_options) {
-  auto stream = std::make_unique<InlineSourceStream>(text);
+  // TODO(crbug.com/1338413): This IsolatedCopy() call was added to keep TSan
+  // happy, but seems like it shouldn't be needed since WTF::String is now
+  // thread safe.
+  auto stream = std::make_unique<InlineSourceStream>(text.IsolatedCopy());
   source_ = std::make_unique<v8::ScriptCompiler::StreamedSource>(
       std::move(stream), text.Is8Bit()
                              ? v8::ScriptCompiler::StreamedSource::ONE_BYTE
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
index e79c5fad..10224c82 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
@@ -34,6 +34,7 @@
 #include <memory>
 
 #include "base/numerics/checked_math.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/sys_byteorder.h"
 #include "third_party/blink/public/web/web_serialized_script_value_version.h"
 #include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
@@ -58,7 +59,6 @@
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -299,7 +299,7 @@
   // This requires direct use of uninitialized strings, though.
   UChar* destination;
   wtf_size_t string_size_bytes =
-      SafeCast<wtf_size_t>((data_buffer_size_ + 1) & ~1);
+      base::checked_cast<wtf_size_t>((data_buffer_size_ + 1) & ~1);
   String wire_string =
       String::CreateUninitialized(string_size_bytes / 2, destination);
   memcpy(destination, data_buffer_.get(), data_buffer_size_);
diff --git a/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h b/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h
index aed4de9..fb45c9c 100644
--- a/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h
+++ b/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_TO_V8_TRAITS_H_
 #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_TO_V8_TRAITS_H_
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
 #include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
@@ -388,7 +389,7 @@
   v8::Local<v8::Array> array;
   {
     v8::Context::Scope context_scope(script_state->GetContext());
-    array = v8::Array::New(isolate, SafeCast<int>(vector.size()));
+    array = v8::Array::New(isolate, base::checked_cast<int>(vector.size()));
   }
   v8::Local<v8::Context> context = script_state->GetContext();
   uint32_t index = 0;
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
index b4664d06..7f6b447 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
@@ -7,6 +7,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/time/time.h"
 #include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
 #include "third_party/blink/public/platform/platform.h"
@@ -130,12 +131,12 @@
     // The resources needed for caching may have been GC'ed, but we should still
     // save the compiled module. Use the platform API directly.
     Vector<uint8_t> serialized_data = CachedMetadata::GetSerializedDataHeader(
-        kWasmModuleTag,
-        kWireBytesDigestSize + SafeCast<wtf_size_t>(serialized_module.size));
+        kWasmModuleTag, kWireBytesDigestSize + base::checked_cast<wtf_size_t>(
+                                                   serialized_module.size));
     serialized_data.Append(wire_bytes_digest.data(), kWireBytesDigestSize);
     serialized_data.Append(
         reinterpret_cast<const uint8_t*>(serialized_module.buffer.get()),
-        SafeCast<wtf_size_t>(serialized_module.size));
+        base::checked_cast<wtf_size_t>(serialized_module.size));
 
     // Make sure the data could be copied.
     if (serialized_data.size() < serialized_module.size)
diff --git a/third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni b/third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni
index a028f2d..96396e0 100644
--- a/third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni
+++ b/third_party/blink/renderer/bindings/generated_in_extensions_chromeos.gni
@@ -16,6 +16,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_cros_window_management.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_cros_accelerator_event.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_cros_accelerator_event.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_cros_screen.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_cros_screen.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_cros_window.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_cros_window.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/extensions_chromeos/v8/v8_cros_hid.h",
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index adb6b091..cad46f2 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -1414,6 +1414,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_webgl_power_preference.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_well_known_directory.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_well_known_directory.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_worklet_execution_mode.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_worklet_execution_mode.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_write_command_type.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_write_command_type.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_depth_data_format.cc",
@@ -2303,6 +2305,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sync_event.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sync_manager.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sync_manager.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_system_audio_preference_enum.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_system_audio_preference_enum.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_task_controller.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_task_controller.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_task_priority_change_event.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_extensions_chromeos.gni b/third_party/blink/renderer/bindings/idl_in_extensions_chromeos.gni
index fab1b32..b8394d4 100644
--- a/third_party/blink/renderer/bindings/idl_in_extensions_chromeos.gni
+++ b/third_party/blink/renderer/bindings/idl_in_extensions_chromeos.gni
@@ -13,6 +13,7 @@
           "//third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.idl",
           "//third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_accelerator_event.idl",
           "//third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_accelerator_event_init.idl",
+          "//third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.idl",
           "//third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.idl",
           "//third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.idl",
         ],
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
index 8feec90..96f9bff 100644
--- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
+++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
@@ -606,7 +606,7 @@
 
   auto& handle_internals = attachments[index];
   return MakeGarbageCollected<MediaSourceHandleImpl>(
-      std::move(handle_internals.attachment),
+      std::move(handle_internals.attachment_provider),
       std::move(handle_internals.internal_blob_url));
 }
 
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
index cc225c4..9549748 100644
--- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
+++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
@@ -589,20 +589,21 @@
   auto* attachment = GetSerializedScriptValue()
                          ->GetOrCreateAttachment<MediaSourceHandleAttachment>();
 
-  // The collection of underlying scoped_refptr<MediaSourceAttachment>
-  // involved in serialization. Each is the internal state of a
-  // MediaSourceHandleImpl. Add the internal state of |handle| to it and
-  // serialize it using the index of that state in the vector.
+  // The collection of underlying scoped_refptr<MediaSourceAttachmentProvider>
+  // and internal object URLs involved in serialization. Each is the internal
+  // state of a MediaSourceHandleImpl. Add the internal state of |handle| to it
+  // and serialize it using the index of that state in the vector.
   auto& attachments = attachment->Attachments();
 
-  scoped_refptr<MediaSourceAttachment> media_source_attachment =
-      handle->TakeAttachment();
+  scoped_refptr<HandleAttachmentProvider> media_source_attachment_provider =
+      handle->TakeAttachmentProvider();
   // The two handle checks, above, (!is_serialized() and !is_used()) should
-  // prevent us from ever having a missing |media_source_attachment| here.
-  DCHECK(media_source_attachment);
+  // prevent us from ever having a missing |media_source_attachment_provider|
+  // here.
+  DCHECK(media_source_attachment_provider);
 
   attachments.push_back(MediaSourceHandleAttachment::HandleInternals{
-      .attachment = std::move(media_source_attachment),
+      .attachment_provider = std::move(media_source_attachment_provider),
       .internal_blob_url = handle->GetInternalBlobURL()});
   handle->mark_serialized();
   const uint32_t index = static_cast<uint32_t>(attachments.size() - 1);
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index e4562ca..5f3a8d7 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -30,6 +30,7 @@
 import("//third_party/blink/renderer/core/editing/build.gni")
 import("//third_party/blink/renderer/core/events/build.gni")
 import("//third_party/blink/renderer/core/execution_context/build.gni")
+import("//third_party/blink/renderer/core/exported/build.gni")
 import("//third_party/blink/renderer/core/fetch/build.gni")
 import("//third_party/blink/renderer/core/fileapi/build.gni")
 import("//third_party/blink/renderer/core/fragment_directive/build.gni")
@@ -55,6 +56,7 @@
 import("//third_party/blink/renderer/core/paint/build.gni")
 import("//third_party/blink/renderer/core/permissions_policy/build.gni")
 import("//third_party/blink/renderer/core/resize_observer/build.gni")
+import("//third_party/blink/renderer/core/scheduler_integration_tests/build.gni")
 import("//third_party/blink/renderer/core/script/build.gni")
 import("//third_party/blink/renderer/core/scroll/build.gni")
 import("//third_party/blink/renderer/core/speculation_rules/build.gni")
@@ -1253,35 +1255,11 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "exported/web_document_subresource_filter_test.cc",
-    "exported/web_document_test.cc",
-    "exported/web_drag_data_test.cc",
-    "exported/web_element_test.cc",
-    "exported/web_frame_serializer_sanitization_test.cc",
-    "exported/web_frame_serializer_test.cc",
-    "exported/web_frame_serializer_test_helper.cc",
-    "exported/web_frame_serializer_test_helper.h",
-    "exported/web_image_test.cc",
-    "exported/web_meaningful_layouts_test.cc",
-    "exported/web_node_test.cc",
-    "exported/web_plugin_container_test.cc",
-    "exported/web_range_test.cc",
-    "exported/web_scoped_window_focus_allowed_indicator_test.cc",
-    "exported/web_searchable_form_data_test.cc",
-    "exported/web_selector_test.cc",
-    "exported/web_view_test.cc",
-    "scheduler_integration_tests/frame_scheduler_test.cc",
-    "scheduler_integration_tests/frame_throttling_test.cc",
-    "scheduler_integration_tests/scheduler_affecting_features_test.cc",
-    "scheduler_integration_tests/throttling_test.cc",
-    "scheduler_integration_tests/virtual_time_test.cc",
-  ]
 
   # If you create a new subdirectory 'foo' that contains unit tests, list them in
   # 'foo/build.gni' to define blink_core_tests_foo, and add any dependencies in
   # the deps section below.
-  sources += rebase_path(blink_core_tests_accessibility, "", "accessibility")
+  sources = rebase_path(blink_core_tests_accessibility, "", "accessibility")
   sources += rebase_path(blink_core_tests_animation, "", "animation")
   sources += rebase_path(blink_core_tests_annotation, "", "annotation")
   sources += rebase_path(blink_core_tests_clipboard, "", "clipboard")
@@ -1297,6 +1275,7 @@
   sources += rebase_path(blink_core_tests_events, "", "events")
   sources +=
       rebase_path(blink_core_tests_execution_context, "", "execution_context")
+  sources += rebase_path(blink_core_tests_exported, "", "exported")
   sources += rebase_path(blink_core_tests_fetch, "", "fetch")
   sources += rebase_path(blink_core_tests_fileapi, "", "fileapi")
   sources +=
@@ -1323,6 +1302,9 @@
       rebase_path(blink_core_tests_permissions_policy, "", "permissions_policy")
   sources +=
       rebase_path(blink_core_tests_resize_observer, "", "resize_observer")
+  sources += rebase_path(blink_core_tests_scheduler_integration_tests,
+                         "",
+                         "scheduler_integration_tests")
   sources += rebase_path(blink_core_tests_script, "", "script")
   sources += rebase_path(blink_core_tests_scroll, "", "scroll")
   sources +=
diff --git a/third_party/blink/renderer/core/css/css_selector.cc b/third_party/blink/renderer/core/css/css_selector.cc
index e7eeef2..f8ed7f0 100644
--- a/third_party/blink/renderer/core/css/css_selector.cc
+++ b/third_party/blink/renderer/core/css/css_selector.cc
@@ -996,7 +996,7 @@
     if (simple_selector->SelectorList()) {
       builder.Append('(');
       const CSSSelector* first_sub_selector =
-          simple_selector->SelectorList()->FirstForCSSOM();
+          simple_selector->SelectorList()->First();
       for (const CSSSelector* sub_selector = first_sub_selector; sub_selector;
            sub_selector = CSSSelectorList::Next(*sub_selector)) {
         if (sub_selector != first_sub_selector)
diff --git a/third_party/blink/renderer/core/css/css_selector.h b/third_party/blink/renderer/core/css/css_selector.h
index ccfa832..148ac714d 100644
--- a/third_party/blink/renderer/core/css/css_selector.h
+++ b/third_party/blink/renderer/core/css/css_selector.h
@@ -412,11 +412,6 @@
     is_last_in_selector_list_ = is_last;
   }
 
-  bool IsLastInOriginalList() const { return is_last_in_original_list_; }
-  void SetLastInOriginalList(bool is_last) {
-    is_last_in_original_list_ = is_last;
-  }
-
   bool IsLastInTagHistory() const { return is_last_in_tag_history_; }
   void SetLastInTagHistory(bool is_last) { is_last_in_tag_history_ = is_last; }
 
@@ -456,7 +451,6 @@
   unsigned has_rare_data_ : 1;
   unsigned is_for_page_ : 1;
   unsigned tag_is_implicit_ : 1;
-  unsigned is_last_in_original_list_ : 1;
 
   void SetPseudoType(PseudoType pseudo_type) {
     pseudo_type_ = pseudo_type;
@@ -600,7 +594,6 @@
       has_rare_data_(false),
       is_for_page_(false),
       tag_is_implicit_(false),
-      is_last_in_original_list_(false),
       data_(DataUnion::kConstructEmptyValue) {}
 
 inline CSSSelector::CSSSelector(const QualifiedName& tag_q_name,
@@ -613,7 +606,6 @@
       has_rare_data_(false),
       is_for_page_(false),
       tag_is_implicit_(tag_is_implicit),
-      is_last_in_original_list_(false),
       data_(tag_q_name) {}
 
 inline CSSSelector::CSSSelector(const CSSSelector& o)
@@ -625,7 +617,6 @@
       has_rare_data_(o.has_rare_data_),
       is_for_page_(o.is_for_page_),
       tag_is_implicit_(o.tag_is_implicit_),
-      is_last_in_original_list_(o.is_last_in_original_list_),
       data_(DataUnion::kConstructUninitialized) {
   if (o.match_ == kTag) {
     new (&data_.tag_q_name_) QualifiedName(o.data_.tag_q_name_);
diff --git a/third_party/blink/renderer/core/css/css_selector_list.cc b/third_party/blink/renderer/core/css/css_selector_list.cc
index 2ef1309..237ec4e 100644
--- a/third_party/blink/renderer/core/css/css_selector_list.cc
+++ b/third_party/blink/renderer/core/css/css_selector_list.cc
@@ -84,23 +84,11 @@
   }
   DCHECK_EQ(flattened_size, array_index);
   list.selector_array_[array_index - 1].SetLastInSelectorList(true);
-  list.selector_array_[array_index - 1].SetLastInOriginalList(true);
   selector_vector.clear();
 
   return list;
 }
 
-const CSSSelector* CSSSelectorList::FirstForCSSOM() const {
-  const CSSSelector* s = First();
-  if (!s)
-    return nullptr;
-  while (Next(*s))
-    s = Next(*s);
-  if (NextInFullList(*s))
-    return NextInFullList(*s);
-  return First();
-}
-
 unsigned CSSSelectorList::ComputeLength() const {
   if (!selector_array_)
     return 0;
@@ -122,8 +110,8 @@
 String CSSSelectorList::SelectorsText() const {
   StringBuilder result;
 
-  for (const CSSSelector* s = FirstForCSSOM(); s; s = Next(*s)) {
-    if (s != FirstForCSSOM())
+  for (const CSSSelector* s = First(); s; s = Next(*s)) {
+    if (s != First())
       result.Append(", ");
     result.Append(s->SelectorText());
   }
diff --git a/third_party/blink/renderer/core/css/css_selector_list.h b/third_party/blink/renderer/core/css/css_selector_list.h
index 1553a05..486fcae8 100644
--- a/third_party/blink/renderer/core/css/css_selector_list.h
+++ b/third_party/blink/renderer/core/css/css_selector_list.h
@@ -84,9 +84,7 @@
 
   bool IsValid() const { return !!selector_array_; }
   const CSSSelector* First() const { return selector_array_.get(); }
-  const CSSSelector* FirstForCSSOM() const;
   static const CSSSelector* Next(const CSSSelector&);
-  static const CSSSelector* NextInFullList(const CSSSelector&);
 
   // The CSS selector represents a single sequence of simple selectors.
   bool HasOneSelector() const { return selector_array_ && !Next(*First()); }
@@ -132,15 +130,6 @@
   const CSSSelector* last = &current;
   while (!last->IsLastInTagHistory())
     last++;
-  return last->IsLastInOriginalList() ? nullptr : last + 1;
-}
-
-inline const CSSSelector* CSSSelectorList::NextInFullList(
-    const CSSSelector& current) {
-  // Skip subparts of compound selectors.
-  const CSSSelector* last = &current;
-  while (!last->IsLastInTagHistory())
-    last++;
   return last->IsLastInSelectorList() ? nullptr : last + 1;
 }
 
diff --git a/third_party/blink/renderer/core/css/css_selector_test.cc b/third_party/blink/renderer/core/css/css_selector_test.cc
index 16f79d0..851e901 100644
--- a/third_party/blink/renderer/core/css/css_selector_test.cc
+++ b/third_party/blink/renderer/core/css/css_selector_test.cc
@@ -232,7 +232,6 @@
   CSSSelectorList list;
   EXPECT_FALSE(list.IsValid());
   EXPECT_FALSE(list.First());
-  EXPECT_FALSE(list.FirstForCSSOM());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_selector_watch.cc b/third_party/blink/renderer/core/css/css_selector_watch.cc
index 995b489..205b0ab 100644
--- a/third_party/blink/renderer/core/css/css_selector_watch.cc
+++ b/third_party/blink/renderer/core/css/css_selector_watch.cc
@@ -139,7 +139,7 @@
 }
 
 static bool AllCompound(const CSSSelectorList& selector_list) {
-  for (const CSSSelector* selector = selector_list.FirstForCSSOM(); selector;
+  for (const CSSSelector* selector = selector_list.First(); selector;
        selector = selector_list.Next(*selector)) {
     if (!selector->IsCompound())
       return false;
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
index 92028d9..4cfb06ac 100644
--- a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
@@ -1463,7 +1463,7 @@
   if (context_->Mode() == kUASheetMode)
     return;
 
-  for (const CSSSelector* selector = selector_list.FirstForCSSOM(); selector;
+  for (const CSSSelector* selector = selector_list.First(); selector;
        selector = CSSSelectorList::Next(*selector)) {
     for (const CSSSelector* current = selector; current;
          current = current->TagHistory()) {
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
index 7d6018ce..dc35a5f5 100644
--- a/third_party/blink/renderer/core/css/style_engine.cc
+++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -2698,6 +2698,7 @@
   if (cq_data->SkippedStyleRecalc()) {
     DecrementSkippedContainerRecalc();
     AllowMarkForReattachFromRebuildLayoutTreeScope allow_reattach(*this);
+    base::AutoReset<bool> cq_recalc(&in_container_query_style_recalc_, true);
     RecalcStyleForContainer(container, {});
   }
 }
diff --git a/third_party/blink/renderer/core/document_transition/document_transition.cc b/third_party/blink/renderer/core/document_transition/document_transition.cc
index c879b29..ff25122 100644
--- a/third_party/blink/renderer/core/document_transition/document_transition.cc
+++ b/third_party/blink/renderer/core/document_transition/document_transition.cc
@@ -311,10 +311,14 @@
   return std::move(pending_request_);
 }
 
-bool DocumentTransition::IsTransitionParticipant(
+bool DocumentTransition::NeedsSharedElementEffectNode(
     const LayoutObject& object) const {
+  // Layout view always needs an effect node, even if root itself is not
+  // transitioning. The reason for this is that we want the root to have an
+  // effect which can be hoisted up be the sibling of the layout view. This
+  // simplifies calling code to have a consistent stacking context structure.
   if (auto* layout_view = DynamicTo<LayoutView>(object))
-    return style_tracker_ && style_tracker_->IsRootTransitioning();
+    return state_ != State::kIdle;
 
   // Otherwise check if the layout object has an active shared element.
   auto* element = DynamicTo<Element>(object.GetNode());
@@ -326,7 +330,7 @@
     const EffectPaintPropertyNodeOrAlias& current_effect,
     const ClipPaintPropertyNodeOrAlias* current_clip,
     const TransformPaintPropertyNodeOrAlias* current_transform) {
-  DCHECK(IsTransitionParticipant(object));
+  DCHECK(NeedsSharedElementEffectNode(object));
   DCHECK(current_transform);
   DCHECK(current_clip);
 
@@ -348,7 +352,8 @@
     style_tracker_->UpdateRootIndexAndSnapshotId(
         state.document_transition_shared_element_id,
         state.shared_element_resource_id);
-    DCHECK(state.document_transition_shared_element_id.valid());
+    DCHECK(state.document_transition_shared_element_id.valid() ||
+           !style_tracker_->IsRootTransitioning());
     return style_tracker_->UpdateRootEffect(std::move(state), current_effect);
   }
 
@@ -361,7 +366,7 @@
 
 EffectPaintPropertyNode* DocumentTransition::GetEffect(
     const LayoutObject& object) const {
-  DCHECK(IsTransitionParticipant(object));
+  DCHECK(NeedsSharedElementEffectNode(object));
 
   auto* element = DynamicTo<Element>(object.GetNode());
   if (!element)
diff --git a/third_party/blink/renderer/core/document_transition/document_transition.h b/third_party/blink/renderer/core/document_transition/document_transition.h
index ab4dd2d..2c449bc8 100644
--- a/third_party/blink/renderer/core/document_transition/document_transition.h
+++ b/third_party/blink/renderer/core/document_transition/document_transition.h
@@ -69,9 +69,9 @@
   // This uses std::move semantics to take the request from this object.
   std::unique_ptr<DocumentTransitionRequest> TakePendingRequest();
 
-  // Returns true if this object participates in an active transition (if there
-  // is one).
-  bool IsTransitionParticipant(const LayoutObject& object) const;
+  // Returns true if this object needs to create an EffectNode for the shared
+  // element transition.
+  bool NeedsSharedElementEffectNode(const LayoutObject& object) const;
 
   // Updates an effect node. This effect populates the shared element id and the
   // shared element resource id. The return value is a result of updating the
diff --git a/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc b/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc
index 613b91a9..0ca7872 100644
--- a/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc
+++ b/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.cc
@@ -572,6 +572,9 @@
 void DocumentTransitionStyleTracker::UpdateRootIndexAndSnapshotId(
     DocumentTransitionSharedElementId& index,
     viz::SharedElementResourceId& resource_id) const {
+  if (!IsRootTransitioning())
+    return;
+
   index.AddIndex(0);
   const auto& root_data = GetCurrentRootData();
   DCHECK(root_data);
@@ -626,6 +629,7 @@
           MakeGarbageCollected<DocumentTransitionContentElement>(
               parent, pseudo_id, document_transition_tag, snapshot_id,
               /*is_live_content_element=*/false);
+      fprintf(stderr, "0setting intrinsic size %s\n", size.ToString().Utf8().c_str());
       pseudo_element->SetIntrinsicSize(size);
       return pseudo_element;
     }
@@ -647,6 +651,7 @@
           MakeGarbageCollected<DocumentTransitionContentElement>(
               parent, pseudo_id, document_transition_tag, snapshot_id,
               /*is_live_content_element=*/true);
+      fprintf(stderr, "1setting intrinsic size %s\n", size.ToString().Utf8().c_str());
       pseudo_element->SetIntrinsicSize(size);
       return pseudo_element;
     }
@@ -732,6 +737,7 @@
       // DocumentTransitionContentElement.
       bool use_cached_data = false;
       LayoutSize size = element_data->GetIntrinsicSize(use_cached_data);
+      fprintf(stderr, "2setting intrinsic size %s\n", size.ToString().Utf8().c_str());
       static_cast<DocumentTransitionContentElement*>(pseudo_element)
           ->SetIntrinsicSize(size);
     }
diff --git a/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.h b/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.h
index 22f7392..0fc5fc3d 100644
--- a/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.h
+++ b/third_party/blink/renderer/core/document_transition/document_transition_style_tracker.h
@@ -112,6 +112,10 @@
   int CapturedTagCount() const { return captured_tag_count_; }
 
   bool IsSharedElement(Element* element) const;
+
+  // This function represents whether root itself is participating in the
+  // transition (i.e. it has a tag in the current phase). Note that we create an
+  // EffectNode for the root whether or not it's transitioning.
   bool IsRootTransitioning() const;
 
   std::vector<viz::SharedElementResourceId> TakeCaptureResourceIds() {
diff --git a/third_party/blink/renderer/core/document_transition/document_transition_test.cc b/third_party/blink/renderer/core/document_transition/document_transition_test.cc
index 5445c1a..41844fc 100644
--- a/third_party/blink/renderer/core/document_transition/document_transition_test.cc
+++ b/third_party/blink/renderer/core/document_transition/document_transition_test.cc
@@ -130,7 +130,7 @@
     auto* transition =
         DocumentTransitionSupplement::EnsureDocumentTransition(GetDocument());
     return layout_object && transition &&
-           transition->IsTransitionParticipant(*layout_object);
+           transition->NeedsSharedElementEffectNode(*layout_object);
   }
 
   void ValidatePseudoElementTree(
diff --git a/third_party/blink/renderer/core/dom/document_parser.h b/third_party/blink/renderer/core/dom/document_parser.h
index 37f97bd3..67ec38df 100644
--- a/third_party/blink/renderer/core/dom/document_parser.h
+++ b/third_party/blink/renderer/core/dom/document_parser.h
@@ -105,6 +105,10 @@
   // be parsed.
   virtual void CommitPreloadedData() {}
 
+  // Notifies the parser that this is a good time to send requests for any
+  // preloads that may be pending.
+  virtual void FlushPendingPreloads() {}
+
   void SetDocumentWasLoadedAsPartOfNavigation() {
     document_was_loaded_as_part_of_navigation_ = true;
   }
diff --git a/third_party/blink/renderer/core/dom/element_data.h b/third_party/blink/renderer/core/dom/element_data.h
index bfae665..937c4fa 100644
--- a/third_party/blink/renderer/core/dom/element_data.h
+++ b/third_party/blink/renderer/core/dom/element_data.h
@@ -138,7 +138,6 @@
  private:
   friend class Element;
   friend class HTMLImageElement;
-  friend class HTMLQuoteElement;
   friend class ShareableElementData;
   friend class UniqueElementData;
   friend class SVGElement;
diff --git a/third_party/blink/renderer/core/dom/layout_tree_builder.cc b/third_party/blink/renderer/core/dom/layout_tree_builder.cc
index 1e0b2940..da62005 100644
--- a/third_party/blink/renderer/core/dom/layout_tree_builder.cc
+++ b/third_party/blink/renderer/core/dom/layout_tree_builder.cc
@@ -75,6 +75,16 @@
     return;
   if (!parent_layout_object->CanHaveChildren())
     return;
+
+  // If we are in the top layer and the parent layout object without top layer
+  // adjustment can't have children, then don't render.
+  // https://github.com/w3c/csswg-drafts/issues/6939#issuecomment-1016671534
+  if (node_->IsInTopLayer() && context_.parent &&
+      !context_.parent->CanHaveChildren() &&
+      node_->GetPseudoId() != kPseudoIdBackdrop) {
+    return;
+  }
+
   if (node_->IsPseudoElement() &&
       !CanHaveGeneratedChildren(*parent_layout_object))
     return;
diff --git a/third_party/blink/renderer/core/editing/ime/ime_text_span_vector_builder.cc b/third_party/blink/renderer/core/editing/ime/ime_text_span_vector_builder.cc
index 102e0162..07f9a12 100644
--- a/third_party/blink/renderer/core/editing/ime/ime_text_span_vector_builder.cc
+++ b/third_party/blink/renderer/core/editing/ime/ime_text_span_vector_builder.cc
@@ -30,12 +30,14 @@
 
 #include "third_party/blink/renderer/core/editing/ime/ime_text_span_vector_builder.h"
 
+#include "base/numerics/safe_conversions.h"
+
 namespace blink {
 
 Vector<ImeTextSpan> ImeTextSpanVectorBuilder::Build(
     const WebVector<ui::ImeTextSpan>& ime_text_spans) {
   Vector<ImeTextSpan> result;
-  wtf_size_t size = SafeCast<wtf_size_t>(ime_text_spans.size());
+  wtf_size_t size = base::checked_cast<wtf_size_t>(ime_text_spans.size());
   result.ReserveCapacity(size);
   for (wtf_size_t i = 0; i < size; ++i)
     result.push_back(ime_text_spans[i]);
diff --git a/third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.cc b/third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.cc
index 948bf22..1155309 100644
--- a/third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.cc
+++ b/third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h"
 
 namespace blink {
@@ -31,7 +32,7 @@
   if (pos != list->begin())
     DCHECK_GE(marker->StartOffset(), (*std::prev(pos))->EndOffset());
 
-  list->insert(SafeCast<wtf_size_t>(pos - list->begin()), marker);
+  list->insert(base::checked_cast<wtf_size_t>(pos - list->begin()), marker);
 }
 
 bool SortedDocumentMarkerListEditor::MoveMarkers(MarkerList* src_list,
@@ -56,7 +57,7 @@
   }
 
   // Remove the range of markers that were moved to dstNode
-  src_list->EraseAt(0, SafeCast<wtf_size_t>(it - src_list->begin()));
+  src_list->EraseAt(0, base::checked_cast<wtf_size_t>(it - src_list->begin()));
 
   return didMoveMarker;
 }
@@ -77,8 +78,8 @@
         return marker->StartOffset() < end_offset;
       });
 
-  list->EraseAt(SafeCast<wtf_size_t>(start_pos - list->begin()),
-                SafeCast<wtf_size_t>(end_pos - start_pos));
+  list->EraseAt(base::checked_cast<wtf_size_t>(start_pos - list->begin()),
+                base::checked_cast<wtf_size_t>(end_pos - start_pos));
   return start_pos != end_pos;
 }
 
@@ -118,8 +119,9 @@
   // Note: shift_range_begin could point at a marker being shifted instead of
   // deleted, but if this is the case, we don't need to delete any markers, and
   // EraseAt() will get 0 for the length param
-  list->EraseAt(SafeCast<wtf_size_t>(shift_range_begin - list->begin()),
-                SafeCast<wtf_size_t>(erase_range_end - shift_range_begin));
+  list->EraseAt(
+      base::checked_cast<wtf_size_t>(shift_range_begin - list->begin()),
+      base::checked_cast<wtf_size_t>(erase_range_end - shift_range_begin));
   return did_shift_marker;
 }
 
@@ -162,8 +164,9 @@
     }
   }
 
-  list->EraseAt(SafeCast<wtf_size_t>(erase_range_begin - list->begin()),
-                SafeCast<wtf_size_t>(erase_range_end - erase_range_begin));
+  list->EraseAt(
+      base::checked_cast<wtf_size_t>(erase_range_begin - list->begin()),
+      base::checked_cast<wtf_size_t>(erase_range_end - erase_range_begin));
   return did_shift_marker;
 }
 
diff --git a/third_party/blink/renderer/core/exported/BUILD.gn b/third_party/blink/renderer/core/exported/BUILD.gn
index fc55b0d..5ab81e7 100644
--- a/third_party/blink/renderer/core/exported/BUILD.gn
+++ b/third_party/blink/renderer/core/exported/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 import("//build/config/dcheck_always_on.gni")
 import("//third_party/blink/renderer/core/core.gni")
+import("//third_party/blink/renderer/core/exported/build.gni")
 
 static_library("test_support") {
   testonly = true
@@ -19,74 +20,7 @@
 }
 
 blink_core_sources("exported") {
-  sources = [
-    "web_array_buffer.cc",
-    "web_array_buffer_converter.cc",
-    "web_blob.cc",
-    "web_console_message.cc",
-    "web_content_holder.cc",
-    "web_custom_element.cc",
-    "web_dev_tools_agent_impl.cc",
-    "web_dev_tools_agent_impl.h",
-    "web_document.cc",
-    "web_dom_activity_logger.cc",
-    "web_dom_event.cc",
-    "web_dom_message_event.cc",
-    "web_element.cc",
-    "web_element_collection.cc",
-    "web_form_control_element.cc",
-    "web_form_element.cc",
-    "web_form_element_observer_impl.cc",
-    "web_form_element_observer_impl.h",
-    "web_frame_content_dumper.cc",
-    "web_frame_serializer.cc",
-    "web_heap.cc",
-    "web_history_entry.cc",
-    "web_history_item.cc",
-    "web_hit_test_result.cc",
-    "web_image.cc",
-    "web_image_cache.cc",
-    "web_input_element.cc",
-    "web_input_method_controller_impl.cc",
-    "web_input_method_controller_impl.h",
-    "web_isolated_world_info.cc",
-    "web_label_element.cc",
-    "web_language_detection_details.cc",
-    "web_memory_statistics.cc",
-    "web_message_port_converter.cc",
-    "web_meta_element.cc",
-    "web_navigation_params.cc",
-    "web_node.cc",
-    "web_option_element.cc",
-    "web_page_popup_impl.cc",
-    "web_page_popup_impl.h",
-    "web_performance.cc",
-    "web_plugin_container_impl.cc",
-    "web_plugin_container_impl.h",
-    "web_plugin_document.cc",
-    "web_plugin_script_forbidden_scope.cc",
-    "web_range.cc",
-    "web_render_theme.cc",
-    "web_savable_resources_test_support.cc",
-    "web_scoped_page_pauser.cc",
-    "web_scoped_window_focus_allowed_indicator.cc",
-    "web_script_controller.cc",
-    "web_searchable_form_data.cc",
-    "web_security_policy.cc",
-    "web_select_element.cc",
-    "web_selector.cc",
-    "web_serialized_script_value.cc",
-    "web_settings_impl.cc",
-    "web_settings_impl.h",
-    "web_shared_worker_impl.cc",
-    "web_shared_worker_impl.h",
-    "web_text_checking_result.cc",
-    "web_v8_context_snapshot.cc",
-    "web_v8_features.cc",
-    "web_view_impl.cc",
-    "web_view_impl.h",
-    "web_view_observer.cc",
-  ]
+  sources = blink_core_sources_exported
 
   if (is_debug || dcheck_always_on) {
     sources += [ "web_disallow_transition_scope.cc" ]
diff --git a/third_party/blink/renderer/core/exported/build.gni b/third_party/blink/renderer/core/exported/build.gni
new file mode 100644
index 0000000..dbce0cb0
--- /dev/null
+++ b/third_party/blink/renderer/core/exported/build.gni
@@ -0,0 +1,92 @@
+# 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.
+
+blink_core_sources_exported = [
+  "web_array_buffer.cc",
+  "web_array_buffer_converter.cc",
+  "web_blob.cc",
+  "web_console_message.cc",
+  "web_content_holder.cc",
+  "web_custom_element.cc",
+  "web_dev_tools_agent_impl.cc",
+  "web_dev_tools_agent_impl.h",
+  "web_document.cc",
+  "web_dom_activity_logger.cc",
+  "web_dom_event.cc",
+  "web_dom_message_event.cc",
+  "web_element.cc",
+  "web_element_collection.cc",
+  "web_form_control_element.cc",
+  "web_form_element.cc",
+  "web_form_element_observer_impl.cc",
+  "web_form_element_observer_impl.h",
+  "web_frame_content_dumper.cc",
+  "web_frame_serializer.cc",
+  "web_heap.cc",
+  "web_history_entry.cc",
+  "web_history_item.cc",
+  "web_hit_test_result.cc",
+  "web_image.cc",
+  "web_image_cache.cc",
+  "web_input_element.cc",
+  "web_input_method_controller_impl.cc",
+  "web_input_method_controller_impl.h",
+  "web_isolated_world_info.cc",
+  "web_label_element.cc",
+  "web_language_detection_details.cc",
+  "web_memory_statistics.cc",
+  "web_message_port_converter.cc",
+  "web_meta_element.cc",
+  "web_navigation_params.cc",
+  "web_node.cc",
+  "web_option_element.cc",
+  "web_page_popup_impl.cc",
+  "web_page_popup_impl.h",
+  "web_performance.cc",
+  "web_plugin_container_impl.cc",
+  "web_plugin_container_impl.h",
+  "web_plugin_document.cc",
+  "web_plugin_script_forbidden_scope.cc",
+  "web_range.cc",
+  "web_render_theme.cc",
+  "web_savable_resources_test_support.cc",
+  "web_scoped_page_pauser.cc",
+  "web_scoped_window_focus_allowed_indicator.cc",
+  "web_script_controller.cc",
+  "web_searchable_form_data.cc",
+  "web_security_policy.cc",
+  "web_select_element.cc",
+  "web_selector.cc",
+  "web_serialized_script_value.cc",
+  "web_settings_impl.cc",
+  "web_settings_impl.h",
+  "web_shared_worker_impl.cc",
+  "web_shared_worker_impl.h",
+  "web_text_checking_result.cc",
+  "web_v8_context_snapshot.cc",
+  "web_v8_features.cc",
+  "web_view_impl.cc",
+  "web_view_impl.h",
+  "web_view_observer.cc",
+]
+
+blink_core_tests_exported = [
+  "web_document_subresource_filter_test.cc",
+  "web_document_test.cc",
+  "web_drag_data_test.cc",
+  "web_element_test.cc",
+  "web_frame_serializer_sanitization_test.cc",
+  "web_frame_serializer_test.cc",
+  "web_frame_serializer_test_helper.cc",
+  "web_frame_serializer_test_helper.h",
+  "web_image_test.cc",
+  "web_meaningful_layouts_test.cc",
+  "web_node_test.cc",
+  "web_plugin_container_test.cc",
+  "web_range_test.cc",
+  "web_scoped_window_focus_allowed_indicator_test.cc",
+  "web_searchable_form_data_test.cc",
+  "web_selector_test.cc",
+  "web_view_test.cc",
+]
diff --git a/third_party/blink/renderer/core/exported/web_document.cc b/third_party/blink/renderer/core/exported/web_document.cc
index 86389b2..12669ac 100644
--- a/third_party/blink/renderer/core/exported/web_document.cc
+++ b/third_party/blink/renderer/core/exported/web_document.cc
@@ -205,12 +205,7 @@
   Vector<WebFormElement> form_elements;
   form_elements.ReserveCapacity(forms->length());
   for (Element* element : *forms) {
-    auto* html_form_element = blink::DynamicTo<HTMLFormElement>(element);
-    // TODO(https://crbug.com/1293602): Make this a To<> instead of a CHECK.
-    CHECK(html_form_element)
-        << "Document::forms() returned a non-form element! " << element;
-    if (html_form_element)
-      form_elements.emplace_back(html_form_element);
+    form_elements.emplace_back(blink::To<HTMLFormElement>(element));
   }
   return form_elements;
 }
diff --git a/third_party/blink/renderer/core/exported/web_selector.cc b/third_party/blink/renderer/core/exported/web_selector.cc
index f781f6d..06ed4d8d 100644
--- a/third_party/blink/renderer/core/exported/web_selector.cc
+++ b/third_party/blink/renderer/core/exported/web_selector.cc
@@ -47,7 +47,7 @@
       web_selector);
 
   if (restriction == kWebSelectorTypeCompound) {
-    for (const CSSSelector* selector = selector_list.FirstForCSSOM(); selector;
+    for (const CSSSelector* selector = selector_list.First(); selector;
          selector = selector_list.Next(*selector)) {
       if (!selector->IsCompound())
         return WebString();
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer.cc b/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
index 6d31c207..80a42d7 100644
--- a/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
+++ b/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
@@ -5,7 +5,9 @@
 #include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
 
 #include <memory>
+
 #include "base/auto_reset.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/fetch/body.h"
 #include "third_party/blink/renderer/core/fetch/bytes_consumer_tee.h"
@@ -24,7 +26,6 @@
 #include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h"
 #include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -459,7 +460,7 @@
     if (result == BytesConsumer::Result::kOk) {
       array = DOMUint8Array::CreateOrNull(
           reinterpret_cast<const unsigned char*>(buffer),
-          SafeCast<uint32_t>(available));
+          base::checked_cast<uint32_t>(available));
       result = consumer_->EndRead(available);
       if (!array) {
         RaiseOOMError();
diff --git a/third_party/blink/renderer/core/fetch/bytes_consumer_tee.cc b/third_party/blink/renderer/core/fetch/bytes_consumer_tee.cc
index fbda4f4a..beb02d4 100644
--- a/third_party/blink/renderer/core/fetch/bytes_consumer_tee.cc
+++ b/third_party/blink/renderer/core/fetch/bytes_consumer_tee.cc
@@ -5,8 +5,11 @@
 #include "third_party/blink/renderer/core/fetch/bytes_consumer_tee.h"
 
 #include <string.h>
+
 #include <algorithm>
+
 #include "base/memory/scoped_refptr.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/fetch/blob_bytes_consumer.h"
@@ -16,7 +19,6 @@
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "v8/include/v8.h"
 
 namespace blink {
@@ -63,8 +65,8 @@
       }
       Chunk* chunk = nullptr;
       if (result == Result::kOk) {
-        chunk = MakeGarbageCollected<Chunk>(buffer,
-                                            SafeCast<wtf_size_t>(available));
+        chunk = MakeGarbageCollected<Chunk>(
+            buffer, base::checked_cast<wtf_size_t>(available));
         result = src_->EndRead(available);
       }
       switch (result) {
diff --git a/third_party/blink/renderer/core/fetch/fetch_data_loader.cc b/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
index d03eacf..5c50754 100644
--- a/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
@@ -23,7 +24,6 @@
 #include "third_party/blink/renderer/platform/network/parsed_content_disposition.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -159,7 +159,7 @@
         return;
       if (result == BytesConsumer::Result::kOk) {
         if (available > 0) {
-          bool ok = Append(buffer, SafeCast<wtf_size_t>(available));
+          bool ok = Append(buffer, base::checked_cast<wtf_size_t>(available));
           if (!ok) {
             [[maybe_unused]] auto unused = consumer_->EndRead(0);
             consumer_->Cancel();
@@ -215,7 +215,7 @@
   // Builds a DOMArrayBuffer from the received bytes.
   DOMArrayBuffer* BuildArrayBuffer() {
     DOMArrayBuffer* result = DOMArrayBuffer::CreateUninitializedOrNull(
-        SafeCast<unsigned>(buffer_->size()), 1);
+        base::checked_cast<unsigned>(buffer_->size()), 1);
     // Handle a failed allocation.
     if (!result) {
       return result;
@@ -623,7 +623,7 @@
         if (available == 0) {
           result = consumer_->EndRead(0);
         } else {
-          uint32_t num_bytes = SafeCast<uint32_t>(available);
+          uint32_t num_bytes = base::checked_cast<uint32_t>(available);
           MojoResult mojo_result = out_data_pipe_->WriteData(
               buffer, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE);
           if (mojo_result == MOJO_RESULT_OK) {
diff --git a/third_party/blink/renderer/core/fetch/fetch_manager.cc b/third_party/blink/renderer/core/fetch/fetch_manager.cc
index 3e76fb8..2e6581e 100644
--- a/third_party/blink/renderer/core/fetch/fetch_manager.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -9,6 +9,7 @@
 #include "base/check.h"
 #include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/strcat.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/unguessable_token.h"
@@ -79,7 +80,6 @@
 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 #include "v8/include/v8.h"
@@ -192,7 +192,7 @@
         size_t available;
         result = body_->BeginRead(&buffer, &available);
         if (result == Result::kOk) {
-          buffer_.Append(buffer, SafeCast<wtf_size_t>(available));
+          buffer_.Append(buffer, base::checked_cast<wtf_size_t>(available));
           result = body_->EndRead(available);
         }
         if (result == Result::kShouldWait)
diff --git a/third_party/blink/renderer/core/fetch/fetch_request_data.cc b/third_party/blink/renderer/core/fetch/fetch_request_data.cc
index 464f0319..224b01f8 100644
--- a/third_party/blink/renderer/core/fetch/fetch_request_data.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_request_data.cc
@@ -189,6 +189,17 @@
   if (fetch_api_request->fetch_window_id)
     request->SetWindowId(fetch_api_request->fetch_window_id.value());
 
+  if (fetch_api_request->trust_token_params) {
+    if (script_state) {
+      // script state might be null for some tests
+      DCHECK(RuntimeEnabledFeatures::TrustTokensEnabled(
+          ExecutionContext::From(script_state)));
+    }
+    absl::optional<network::mojom::blink::TrustTokenParams> trust_token_params =
+        std::move(*(fetch_api_request->trust_token_params->Clone().get()));
+    request->SetTrustTokenParams(trust_token_params);
+  }
+
   return request;
 }
 
diff --git a/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc b/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
index 30972bf4..c3073ac 100644
--- a/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
@@ -45,4 +45,34 @@
   EXPECT_TRUE(request_data->HeaderList()->Has("sec-fetch-yy"));
 }
 
+TEST(FetchRequestDataTest, CheckTrustTokenParamsAreCopiedWithCreate) {
+  // create a fetch API request instance
+  auto request = mojom::blink::FetchAPIRequest::New();
+  // create a TrustTokenParams instance
+  WTF::Vector<::scoped_refptr<const ::blink::SecurityOrigin>> issuers;
+  issuers.push_back(
+      ::blink::SecurityOrigin::CreateFromString("https://aaa.example"));
+  issuers.push_back(
+      ::blink::SecurityOrigin::CreateFromString("https://bbb.example"));
+  WTF::Vector<WTF::String> additional_signed_headers = {"aaa", "bbb"};
+  auto trust_token_params = network::mojom::blink::TrustTokenParams::New(
+      network::mojom::TrustTokenOperationType::kRedemption,
+      network::mojom::TrustTokenRefreshPolicy::kUseCached,
+      network::mojom::TrustTokenSignRequestData::kInclude,
+      /* include_timestamp_header=*/true, issuers, additional_signed_headers,
+      /* possibly_unsafe_additional_signing_data=*/"ccc");
+  // get a copy of of TrustTokenParams instance created, will be used in testing
+  // later
+  auto trust_token_params_copy = trust_token_params->Clone();
+  // set trust token params in request
+  request->trust_token_params = std::move(trust_token_params);
+  // create a FetchRequestData instance from request
+  FetchRequestData* request_data = FetchRequestData::Create(
+      /*script_state=*/nullptr, std::move(request),
+      FetchRequestData::ForServiceWorkerFetchEvent::kTrue);
+  // compare trust token params of request_data to trust_token_params_copy.
+  EXPECT_TRUE(request_data->TrustTokenParams());
+  EXPECT_EQ(*(request_data->TrustTokenParams()), *(trust_token_params_copy));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/fetch_response_data.cc b/third_party/blink/renderer/core/fetch/fetch_response_data.cc
index 8ef917ab..cad55569 100644
--- a/third_party/blink/renderer/core/fetch/fetch_response_data.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_response_data.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "storage/common/quota/padding_key.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
 #include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
@@ -15,7 +16,6 @@
 #include "third_party/blink/renderer/platform/network/http_names.h"
 #include "third_party/blink/renderer/platform/network/http_parsers.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 using Type = network::mojom::FetchResponseType;
 using ResponseSource = network::mojom::FetchResponseSource;
@@ -26,7 +26,7 @@
 
 Vector<String> HeaderSetToVector(const HTTPHeaderSet& headers) {
   Vector<String> result;
-  result.ReserveInitialCapacity(SafeCast<wtf_size_t>(headers.size()));
+  result.ReserveInitialCapacity(base::checked_cast<wtf_size_t>(headers.size()));
   // HTTPHeaderSet stores headers using Latin1 encoding.
   for (const auto& header : headers)
     result.push_back(String(header.data(), header.size()));
diff --git a/third_party/blink/renderer/core/fetch/multipart_parser_test.cc b/third_party/blink/renderer/core/fetch/multipart_parser_test.cc
index 4678839..80e9cb0 100644
--- a/third_party/blink/renderer/core/fetch/multipart_parser_test.cc
+++ b/third_party/blink/renderer/core/fetch/multipart_parser_test.cc
@@ -4,12 +4,13 @@
 
 #include "third_party/blink/renderer/core/fetch/multipart_parser.h"
 
+#include <string.h>
+
+#include <algorithm>
+
+#include "base/numerics/safe_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/network/http_names.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-
-#include <string.h>
-#include <algorithm>
 
 namespace blink {
 
@@ -38,7 +39,7 @@
     parts_.push_back(header_fields);
   }
   void PartDataInMultipartReceived(const char* bytes, size_t size) override {
-    parts_.back().data.Append(bytes, SafeCast<wtf_size_t>(size));
+    parts_.back().data.Append(bytes, base::checked_cast<wtf_size_t>(size));
   }
   void PartDataInMultipartFullyReceived() override {
     parts_.back().data_fully_received = true;
diff --git a/third_party/blink/renderer/core/fileapi/file_reader_loader.cc b/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
index dfa291d..f8d1bf94 100644
--- a/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
+++ b/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
@@ -35,6 +35,7 @@
 #include <utility>
 
 #include "base/memory/scoped_refptr.h"
+#include "base/numerics/safe_conversions.h"
 #include "mojo/public/cpp/system/wait.h"
 #include "third_party/blink/public/common/blob/blob_utils.h"
 #include "third_party/blink/public/platform/web_url_request.h"
@@ -52,7 +53,6 @@
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
 #include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/base64.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -135,7 +135,7 @@
 
   if (!finished_loading_) {
     return DOMArrayBuffer::Create(raw_data_.Data(),
-                                  SafeCast<size_t>(bytes_loaded_));
+                                  base::checked_cast<size_t>(bytes_loaded_));
   }
 
   array_buffer_result_ = DOMArrayBuffer::Create(std::move(raw_data_));
@@ -429,7 +429,7 @@
 
   Vector<char> out;
   Base64Encode(base::make_span(static_cast<const uint8_t*>(raw_data_.Data()),
-                               SafeCast<unsigned>(bytes_loaded_)),
+                               base::checked_cast<unsigned>(bytes_loaded_)),
                out);
   builder.Append(out.data(), out.size());
 
diff --git a/third_party/blink/renderer/core/frame/attribution_response_parsing.cc b/third_party/blink/renderer/core/frame/attribution_response_parsing.cc
index e2f28c9..5520c4a 100644
--- a/third_party/blink/renderer/core/frame/attribution_response_parsing.cc
+++ b/third_party/blink/renderer/core/frame/attribution_response_parsing.cc
@@ -492,6 +492,13 @@
     return false;
   }
 
+  trigger_data.not_filters = mojom::blink::AttributionFilterData::New();
+
+  if (!ParseAttributionFilterData(object->Get("not_filters"),
+                                  *trigger_data.not_filters)) {
+    return false;
+  }
+
   if (!ParseAttributionAggregatableTriggerData(
           object->Get("aggregatable_trigger_data"),
           trigger_data.aggregatable_trigger_data)) {
diff --git a/third_party/blink/renderer/core/frame/attribution_src/attribution_trigger_registration_corpus/all_params.textproto b/third_party/blink/renderer/core/frame/attribution_src/attribution_trigger_registration_corpus/all_params.textproto
index c5c8b4df..91f8aeb9 100644
--- a/third_party/blink/renderer/core/frame/attribution_src/attribution_trigger_registration_corpus/all_params.textproto
+++ b/third_party/blink/renderer/core/frame/attribution_src/attribution_trigger_registration_corpus/all_params.textproto
@@ -258,4 +258,23 @@
       }
     }
   }
+  field {
+    name: "not_filters"
+    value {
+      object_value {
+        field {
+          name: "q"
+          value {
+            array_value {
+              value {
+                string_value {
+                  value: "r"
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
 }
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.h b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
index c8086b7a..76a3772 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.h
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
@@ -391,18 +391,6 @@
 
   bool HasPolicyFromSource(network::mojom::ContentSecurityPolicySource) const;
 
-  static bool IsScriptDirective(CSPDirectiveName directive_type) {
-    return (directive_type == CSPDirectiveName::ScriptSrc ||
-            directive_type == CSPDirectiveName::ScriptSrcAttr ||
-            directive_type == CSPDirectiveName::ScriptSrcElem);
-  }
-
-  static bool IsStyleDirective(CSPDirectiveName directive_type) {
-    return (directive_type == CSPDirectiveName::StyleSrc ||
-            directive_type == CSPDirectiveName::StyleSrcAttr ||
-            directive_type == CSPDirectiveName::StyleSrcElem);
-  }
-
   void Count(WebFeature feature) const;
 
  private:
diff --git a/third_party/blink/renderer/core/frame/csp/source_list_directive.cc b/third_party/blink/renderer/core/frame/csp/source_list_directive.cc
index 9d900bac..c5211af 100644
--- a/third_party/blink/renderer/core/frame/csp/source_list_directive.cc
+++ b/third_party/blink/renderer/core/frame/csp/source_list_directive.cc
@@ -36,6 +36,20 @@
   return false;
 }
 
+bool IsScriptDirective(CSPDirectiveName directive_type) {
+  return (directive_type == CSPDirectiveName::ScriptSrc ||
+          directive_type == CSPDirectiveName::ScriptSrcAttr ||
+          directive_type == CSPDirectiveName::ScriptSrcElem ||
+          directive_type == CSPDirectiveName::DefaultSrc);
+}
+
+bool IsStyleDirective(CSPDirectiveName directive_type) {
+  return (directive_type == CSPDirectiveName::StyleSrc ||
+          directive_type == CSPDirectiveName::StyleSrcAttr ||
+          directive_type == CSPDirectiveName::StyleSrcElem ||
+          directive_type == CSPDirectiveName::DefaultSrc);
+}
+
 }  // namespace
 
 bool CSPSourceListAllows(
@@ -120,15 +134,14 @@
 bool CSPSourceListAllowAllInline(
     CSPDirectiveName directive_type,
     const network::mojom::blink::CSPSourceList& source_list) {
-  if (directive_type != CSPDirectiveName::DefaultSrc &&
-      !ContentSecurityPolicy::IsScriptDirective(directive_type) &&
-      !ContentSecurityPolicy::IsStyleDirective(directive_type)) {
+  if (!IsScriptDirective(directive_type) &&
+      !IsStyleDirective(directive_type)) {
     return false;
   }
 
   return source_list.allow_inline &&
          !CSPSourceListIsHashOrNoncePresent(source_list) &&
-         (!ContentSecurityPolicy::IsScriptDirective(directive_type) ||
+         (!IsScriptDirective(directive_type) ||
           !source_list.allow_dynamic);
 }
 
diff --git a/third_party/blink/renderer/core/frame/find_in_page.cc b/third_party/blink/renderer/core/frame/find_in_page.cc
index 11bc63d..6b824bd 100644
--- a/third_party/blink/renderer/core/frame/find_in_page.cc
+++ b/third_party/blink/renderer/core/frame/find_in_page.cc
@@ -32,6 +32,7 @@
 
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/public/web/web_plugin.h"
@@ -273,7 +274,8 @@
 
 void FindInPage::SetTickmarks(const WebElement& target,
                               const WebVector<gfx::Rect>& tickmarks) {
-  Vector<gfx::Rect> tickmarks_converted(SafeCast<wtf_size_t>(tickmarks.size()));
+  Vector<gfx::Rect> tickmarks_converted(
+      base::checked_cast<wtf_size_t>(tickmarks.size()));
   for (wtf_size_t i = 0; i < tickmarks.size(); ++i)
     tickmarks_converted[i] = tickmarks[i];
 
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
index 86f90ef6a..e3a7e41 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame_mojo_handler.h"
 
 #include "base/metrics/histogram_functions.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/power_scheduler/power_mode.h"
@@ -136,7 +137,8 @@
       std::move(callback).Run(nullptr);
       return;
     }
-    const auto& resource = resources_.at(SafeCast<WTF::wtf_size_t>(index));
+    const auto& resource =
+        resources_.at(base::checked_cast<WTF::wtf_size_t>(index));
     auto info = data_decoder::mojom::blink::SerializedResourceInfo::New();
     info->url = resource.url;
     info->mime_type = resource.mime_type;
@@ -149,7 +151,8 @@
       std::move(callback).Run(absl::nullopt);
       return;
     }
-    const auto& resource = resources_.at(SafeCast<WTF::wtf_size_t>(index));
+    const auto& resource =
+        resources_.at(base::checked_cast<WTF::wtf_size_t>(index));
     if (!resource.data) {
       std::move(callback).Run(absl::nullopt);
       return;
diff --git a/third_party/blink/renderer/core/frame/pausable_script_executor.cc b/third_party/blink/renderer/core/frame/pausable_script_executor.cc
index 0e10a85..50802cd9d 100644
--- a/third_party/blink/renderer/core/frame/pausable_script_executor.cc
+++ b/third_party/blink/renderer/core/frame/pausable_script_executor.cc
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/check.h"
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_vector.h"
@@ -209,7 +210,7 @@
                                        int argc,
                                        v8::Local<v8::Value> argv[])
     : function_(isolate, function), receiver_(isolate, receiver) {
-  args_.ReserveCapacity(SafeCast<wtf_size_t>(argc));
+  args_.ReserveCapacity(base::checked_cast<wtf_size_t>(argc));
   for (int i = 0; i < argc; ++i)
     args_.push_back(TraceWrapperV8Reference<v8::Value>(isolate, argv[i]));
 }
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 840b54f..e97009a1d 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1332,7 +1332,8 @@
 void WebLocalFrameImpl::RemoveSpellingMarkersUnderWords(
     const WebVector<WebString>& words) {
   Vector<String> converted_words;
-  converted_words.Append(words.data(), SafeCast<wtf_size_t>(words.size()));
+  converted_words.Append(words.data(),
+                         base::checked_cast<wtf_size_t>(words.size()));
   GetFrame()->RemoveSpellingMarkersUnderWords(converted_words);
 }
 
@@ -2680,33 +2681,13 @@
   params.selection_rect =
       LocalRootFrameWidget()->BlinkSpaceToEnclosedDIPs(data.selection_rect);
 
-#if BUILDFLAG(IS_ANDROID)
-  // The Samsung Email app relies on the context menu being shown after the
-  // javascript onselectionchanged is triggered.
-  // See crbug.com/729488
-  GetFrame()
-      ->GetTaskRunner(TaskType::kInternalDefault)
-      ->PostTask(
-          FROM_HERE,
-          WTF::Bind(&WebLocalFrameImpl::ShowDeferredContextMenu,
-                    WrapWeakPersistent(this), std::move(client), params));
-#else
-  ShowDeferredContextMenu(std::move(client), params);
-#endif
-
-  if (Client())
-    Client()->UpdateContextMenuDataForTesting(data, host_context_menu_location);
-}
-
-void WebLocalFrameImpl::ShowDeferredContextMenu(
-    mojo::PendingAssociatedRemote<mojom::blink::ContextMenuClient> client,
-    const UntrustworthyContextMenuParams& params) {
-  // The local frame may become detached before the object is GC'ed. So, this
-  // method needs to check if GetFrame() returns a nullptr.
   if (!GetFrame())
     return;
   GetFrame()->GetLocalFrameHostRemote().ShowContextMenu(std::move(client),
                                                         params);
+
+  if (Client())
+    Client()->UpdateContextMenuDataForTesting(data, host_context_menu_location);
 }
 
 bool WebLocalFrameImpl::IsAllowedToDownload() const {
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index ef15a355..6a7c6b7 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -576,10 +576,6 @@
       network::mojom::blink::WebSandboxFlags sandbox_flags =
           network::mojom::blink::WebSandboxFlags::kNone);
 
-  void ShowDeferredContextMenu(
-      mojo::PendingAssociatedRemote<mojom::blink::ContextMenuClient> client,
-      const UntrustworthyContextMenuParams& params);
-
   WebLocalFrameClient* client_;
 
   // TODO(dcheng): Inline this field directly rather than going through Member.
diff --git a/third_party/blink/renderer/core/html/forms/external_popup_menu.cc b/third_party/blink/renderer/core/html/forms/external_popup_menu.cc
index 05a3adf4..9cc05b12 100644
--- a/third_party/blink/renderer/core/html/forms/external_popup_menu.cc
+++ b/third_party/blink/renderer/core/html/forms/external_popup_menu.cc
@@ -30,6 +30,7 @@
 
 #include "third_party/blink/renderer/core/html/forms/external_popup_menu.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
@@ -245,7 +246,7 @@
         ToPopupMenuItemIndex(indices[indices.size() - 1], *owner_element));
   } else {
     Vector<int> list_indices;
-    wtf_size_t list_count = SafeCast<wtf_size_t>(indices.size());
+    wtf_size_t list_count = base::checked_cast<wtf_size_t>(indices.size());
     list_indices.ReserveCapacity(list_count);
     for (wtf_size_t i = 0; i < list_count; ++i)
       list_indices.push_back(ToPopupMenuItemIndex(indices[i], *owner_element));
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index e56d613c..ccfd16d 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -69,7 +69,6 @@
 #include "third_party/blink/renderer/core/html/html_dimension.h"
 #include "third_party/blink/renderer/core/html/html_document.h"
 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
-#include "third_party/blink/renderer/core/html/html_quote_element.h"
 #include "third_party/blink/renderer/core/html/html_slot_element.h"
 #include "third_party/blink/renderer/core/html/html_template_element.h"
 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
@@ -254,12 +253,6 @@
 void HTMLElement::MapLanguageAttributeToLocale(
     const AtomicString& value,
     MutableCSSPropertyValueSet* style) {
-  // HTMLQuoteElement should ignore own lang attribute and use lang of parent.
-  // This is handled in CollectExtraStyleForPresentationAttribute().
-  // https://github.com/w3c/csswg-drafts/issues/5478
-  if (IsA<HTMLQuoteElement>(this)) {
-    return;
-  }
   if (!value.IsEmpty()) {
     // Have to quote so the locale id is treated as a string instead of as a CSS
     // keyword.
diff --git a/third_party/blink/renderer/core/html/html_link_element.cc b/third_party/blink/renderer/core/html/html_link_element.cc
index e7320b96..48fdc89 100644
--- a/third_party/blink/renderer/core/html/html_link_element.cc
+++ b/third_party/blink/renderer/core/html/html_link_element.cc
@@ -27,6 +27,7 @@
 
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_icon_sizes_parser.h"
 #include "third_party/blink/public/platform/web_prescient_networking.h"
@@ -110,7 +111,7 @@
     sizes_->DidUpdateAttributeValue(params.old_value, value);
     WebVector<gfx::Size> web_icon_sizes =
         WebIconSizesParser::ParseIconSizes(value);
-    icon_sizes_.resize(SafeCast<wtf_size_t>(web_icon_sizes.size()));
+    icon_sizes_.resize(base::checked_cast<wtf_size_t>(web_icon_sizes.size()));
     for (wtf_size_t i = 0; i < icon_sizes_.size(); ++i)
       icon_sizes_[i] = web_icon_sizes[i];
     Process();
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc
index b8e49b6..223da88 100644
--- a/third_party/blink/renderer/core/html/html_plugin_element.cc
+++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -22,6 +22,8 @@
 
 #include "third_party/blink/renderer/core/html/html_plugin_element.h"
 
+#include "base/feature_list.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
 #include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
@@ -126,10 +128,13 @@
       // simpler to make both classes share the same codepath in this class.
       needs_plugin_update_(!flags.IsCreatedByParser()) {
   SetHasCustomStyleCallbacks();
-  if (auto* context = doc.GetExecutionContext()) {
-    context->GetScheduler()->RegisterStickyFeature(
-        SchedulingPolicy::Feature::kContainsPlugins,
-        {SchedulingPolicy::DisableBackForwardCache()});
+  if (!base::FeatureList::IsEnabled(
+          features::kBackForwardCacheEnabledForNonPluginEmbed)) {
+    if (auto* context = doc.GetExecutionContext()) {
+      context->GetScheduler()->RegisterStickyFeature(
+          SchedulingPolicy::Feature::kContainsPlugins,
+          {SchedulingPolicy::DisableBackForwardCache()});
+    }
   }
 }
 
@@ -695,6 +700,17 @@
     layout_object->GetFrameView()->AddPlugin(plugin);
   }
 
+  if (base::FeatureList::IsEnabled(
+          features::kBackForwardCacheEnabledForNonPluginEmbed)) {
+    // Disable back/forward cache when a document uses a plugin. This is not
+    // done in the constructor since |HTMLPlugInElement| is a base class for
+    // HTMLObjectElement and HTMLEmbedElement which can host child browsing
+    // contexts instead.
+    GetExecutionContext()->GetScheduler()->RegisterStickyFeature(
+        SchedulingPolicy::Feature::kContainsPlugins,
+        {SchedulingPolicy::DisableBackForwardCache()});
+  }
+
   GetDocument().SetContainsPlugins();
   // TODO(esprehn): WebPluginContainerImpl::SetCcLayer() also schedules a
   // compositing update, do we need both?
diff --git a/third_party/blink/renderer/core/html/html_quote_element.cc b/third_party/blink/renderer/core/html/html_quote_element.cc
index 41913ab..e85d6a1 100644
--- a/third_party/blink/renderer/core/html/html_quote_element.cc
+++ b/third_party/blink/renderer/core/html/html_quote_element.cc
@@ -22,8 +22,6 @@
 
 #include "third_party/blink/renderer/core/html/html_quote_element.h"
 
-#include "third_party/blink/renderer/core/css/css_markup.h"
-#include "third_party/blink/renderer/core/css/css_property_names.h"
 #include "third_party/blink/renderer/core/css/style_engine.h"
 #include "third_party/blink/renderer/core/html_names.h"
 
@@ -34,7 +32,6 @@
     : HTMLElement(tag_name, document) {
   DCHECK(HasTagName(html_names::kQTag) ||
          HasTagName(html_names::kBlockquoteTag));
-  SetHasCustomStyleCallbacks();
 }
 
 bool HTMLQuoteElement::IsURLAttribute(const Attribute& attribute) const {
@@ -51,27 +48,4 @@
   return html_names::kCiteAttr;
 }
 
-void HTMLQuoteElement::WillRecalcStyle(const StyleRecalcChange change) {
-  EnsureUniqueElementData().SetPresentationAttributeStyleIsDirty(true);
-}
-
-void HTMLQuoteElement::CollectExtraStyleForPresentationAttribute(
-    MutableCSSPropertyValueSet* style) {
-  HTMLElement::CollectExtraStyleForPresentationAttribute(style);
-
-  // <q> should ignore its own lang attribute and use lang of parent.
-  // https://github.com/w3c/csswg-drafts/issues/5478
-  Element* parent = parentElement();
-  if (parent) {
-    if (const AtomicString lang = parent->ComputeInheritedLanguage()) {
-      AddPropertyToPresentationAttributeStyle(
-          style, CSSPropertyID::kWebkitLocale, SerializeString(lang));
-      return;
-    }
-  }
-  // The empty string means the language is explicitly unknown.
-  AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kWebkitLocale,
-                                          CSSValueID::kAuto);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_quote_element.h b/third_party/blink/renderer/core/html/html_quote_element.h
index bfaf467..aa6585f 100644
--- a/third_party/blink/renderer/core/html/html_quote_element.h
+++ b/third_party/blink/renderer/core/html/html_quote_element.h
@@ -39,9 +39,6 @@
   bool IsURLAttribute(const Attribute&) const override;
   bool HasLegalLinkAttribute(const QualifiedName&) const override;
   const QualifiedName& SubResourceAttributeName() const override;
-  void WillRecalcStyle(const StyleRecalcChange) override;
-  void CollectExtraStyleForPresentationAttribute(
-      MutableCSSPropertyValueSet*) override;
 };
 
 inline bool IsHTMLQuoteElement(const HTMLElement& element) {
diff --git a/third_party/blink/renderer/core/html/html_slot_element.h b/third_party/blink/renderer/core/html/html_slot_element.h
index d430f67..7b6b0fc 100644
--- a/third_party/blink/renderer/core/html/html_slot_element.h
+++ b/third_party/blink/renderer/core/html/html_slot_element.h
@@ -32,6 +32,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_SLOT_ELEMENT_H_
 
 #include "base/check_op.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_element_text.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
@@ -181,8 +182,8 @@
       const Container& seq2,
       LCSTable& lcs_table,
       BacktrackTable& backtrack_table) {
-    const wtf_size_t rows = SafeCast<wtf_size_t>(seq1.size());
-    const wtf_size_t columns = SafeCast<wtf_size_t>(seq2.size());
+    const wtf_size_t rows = base::checked_cast<wtf_size_t>(seq1.size());
+    const wtf_size_t columns = base::checked_cast<wtf_size_t>(seq2.size());
 
     DCHECK_GT(lcs_table.size(), rows);
     DCHECK_GT(lcs_table[0].size(), columns);
diff --git a/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc b/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc
index e65327b6..4241925e 100644
--- a/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc
+++ b/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc
@@ -159,7 +159,7 @@
 
   // Picture-in-Picture can be disabled by the website when the API is enabled.
   bool picture_in_picture_allowed =
-      !RuntimeEnabledFeatures::PictureInPictureEnabled() &&
+      !RuntimeEnabledFeatures::PictureInPictureEnabled() ||
       !VideoElement().FastHasAttribute(
           html_names::kDisablepictureinpictureAttr);
 
diff --git a/third_party/blink/renderer/core/html/parser/background_html_scanner_test.cc b/third_party/blink/renderer/core/html/parser/background_html_scanner_test.cc
index 99c7909..ceba40c 100644
--- a/third_party/blink/renderer/core/html/parser/background_html_scanner_test.cc
+++ b/third_party/blink/renderer/core/html/parser/background_html_scanner_test.cc
@@ -82,7 +82,7 @@
           parser, task_runner_));
   preload_scanner.ScanInBackground(
       "<script>foo</script>", GetDocument().ValidBaseElementURL(),
-      CrossThreadBindOnce([](std::unique_ptr<PendingPreloadData>) {}));
+      CrossThreadBindRepeating([](std::unique_ptr<PendingPreloadData>) {}));
   FlushTaskRunner();
   EXPECT_NE(parser->TakeInlineScriptStreamer("foo"), nullptr);
 }
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index 22d678e..63b0d439 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -1511,7 +1511,7 @@
     background_scanner_.AsyncCall(&HTMLPreloadScanner::ScanInBackground)
         .WithArgs(
             source, GetDocument()->ValidBaseElementURL(),
-            CrossThreadBindOnce(
+            CrossThreadBindRepeating(
                 &HTMLDocumentParser::AddPreloadDataOnBackgroundThread,
                 WrapCrossThreadPersistent(this),
                 GetDocument()->GetTaskRunner(TaskType::kInternalLoading)));
@@ -1533,30 +1533,43 @@
 void HTMLDocumentParser::AddPreloadDataOnBackgroundThread(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     std::unique_ptr<PendingPreloadData> preload_data) {
+  DCHECK(!IsMainThread());
+  bool should_post_task = false;
   {
     base::AutoLock lock(pending_preload_lock_);
+    // Only post a task if the preload data is empty. Otherwise, a task has
+    // already been posted and will consume the new data.
+    should_post_task = pending_preload_data_.IsEmpty();
     pending_preload_data_.push_back(std::move(preload_data));
   }
 
-  PostCrossThreadTask(
-      *task_runner, FROM_HERE,
-      CrossThreadBindOnce(&HTMLDocumentParser::FlushPendingPreloads,
-                          WrapCrossThreadPersistent(this)));
+  if (should_post_task) {
+    PostCrossThreadTask(
+        *task_runner, FROM_HERE,
+        CrossThreadBindOnce(&HTMLDocumentParser::FlushPendingPreloads,
+                            WrapCrossThreadPersistent(this)));
+  }
 }
 
 void HTMLDocumentParser::FlushPendingPreloads() {
-  DCHECK(ThreadedPreloadScannerEnabled());
+  DCHECK(IsMainThread());
+  if (!ThreadedPreloadScannerEnabled())
+    return;
+
   if (IsDetached() || !preloader_)
     return;
 
-  Vector<std::unique_ptr<PendingPreloadData>> preload_data;
-  {
-    base::AutoLock lock(pending_preload_lock_);
-    preload_data = std::move(pending_preload_data_);
-  }
+  // Do this in a loop in case more preloads are added in the background.
+  while (HasPendingPreloads()) {
+    Vector<std::unique_ptr<PendingPreloadData>> preload_data;
+    {
+      base::AutoLock lock(pending_preload_lock_);
+      preload_data = std::move(pending_preload_data_);
+    }
 
-  for (auto& preload : preload_data)
-    ProcessPreloadData(std::move(preload));
+    for (auto& preload : preload_data)
+      ProcessPreloadData(std::move(preload));
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.h b/third_party/blink/renderer/core/html/parser/html_document_parser.h
index 6cc1606..01e4cc50 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.h
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.h
@@ -148,6 +148,7 @@
   void CheckIfBlockingStylesheetAdded();
   void DocumentElementAvailable() override;
   void CommitPreloadedData() override;
+  void FlushPendingPreloads() override;
 
   // HTMLParserScriptRunnerHost
   void NotifyScriptLoaded() final;
@@ -200,9 +201,6 @@
       scoped_refptr<base::SequencedTaskRunner> task_runner,
       std::unique_ptr<PendingPreloadData> preload_data);
 
-  // Processes preload data on the main thread from |background_scanner_|.
-  void FlushPendingPreloads();
-
   bool HasPendingPreloads() {
     base::AutoLock lock(pending_preload_lock_);
     return !pending_preload_data_.IsEmpty();
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
index eb4a761..77543b11 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -1093,7 +1093,8 @@
 }
 
 std::unique_ptr<PendingPreloadData> HTMLPreloadScanner::Scan(
-    const KURL& starting_base_element_url) {
+    const KURL& starting_base_element_url,
+    const TakePreloadFn& take_preload) {
   auto pending_data = std::make_unique<PendingPreloadData>();
 
   TRACE_EVENT1("blink", "HTMLPreloadScanner::scan", "source_length",
@@ -1132,15 +1133,20 @@
       tokenizer_->Reset();
       return pending_data;
     }
+    // Incrementally add preloads when scanning in the background.
+    if (take_preload && !pending_data->requests.IsEmpty()) {
+      take_preload.Run(std::move(pending_data));
+      pending_data = std::make_unique<PendingPreloadData>();
+    }
   }
   return pending_data;
 }
 
 void HTMLPreloadScanner::ScanInBackground(const String& source,
                                           const KURL& document_base_element_url,
-                                          TakePreloadFn take_preload) {
+                                          const TakePreloadFn& take_preload) {
   source_.Append(source);
-  std::move(take_preload).Run(Scan(document_base_element_url));
+  take_preload.Run(Scan(document_base_element_url, take_preload));
 }
 
 CachedDocumentParameters::CachedDocumentParameters(Document* document) {
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
index f7cc08b..3665782 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
@@ -193,15 +193,17 @@
   ~HTMLPreloadScanner();
 
   void AppendToEnd(const SegmentedString&);
+
+  using TakePreloadFn = WTF::CrossThreadRepeatingFunction<void(
+      std::unique_ptr<PendingPreloadData>)>;
   std::unique_ptr<PendingPreloadData> Scan(
-      const KURL& document_base_element_url);
+      const KURL& document_base_element_url,
+      const TakePreloadFn& take_preload = TakePreloadFn());
 
   // Scans |source| and calls |take_preload| with the generated preload data.
-  using TakePreloadFn =
-      CrossThreadOnceFunction<void(std::unique_ptr<PendingPreloadData>)>;
   void ScanInBackground(const String& source,
                         const KURL& document_base_element_url,
-                        TakePreloadFn take_preload);
+                        const TakePreloadFn& take_preload);
 
  private:
   TokenPreloadScanner scanner_;
diff --git a/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc b/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
index cfc09d1..8ca105d 100644
--- a/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
+++ b/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
@@ -22,6 +22,7 @@
 
 #include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/core/dom/dom_implementation.h"
 #include "third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h"
 #include "third_party/blink/renderer/platform/text/text_encoding_detector.h"
@@ -392,7 +393,7 @@
 }
 
 String TextResourceDecoder::Decode(const char* data, size_t data_len) {
-  wtf_size_t len = SafeCast<wtf_size_t>(data_len);
+  wtf_size_t len = base::checked_cast<wtf_size_t>(data_len);
   // If we have previously buffered data, then add the new data to the buffer
   // and use the buffered content. Any case that depends on buffering (== return
   // the empty string) should call AddToBufferIfEmpty() if it needs more data to
diff --git a/third_party/blink/renderer/core/html/resources/html.css b/third_party/blink/renderer/core/html/resources/html.css
index f16e3128..cc3c359 100644
--- a/third_party/blink/renderer/core/html/resources/html.css
+++ b/third_party/blink/renderer/core/html/resources/html.css
@@ -25,7 +25,7 @@
 
 html {
     display: block;
-    page-transition-tag: root !important;
+    page-transition-tag: root;
 }
 
 /* generic block-level elements */
diff --git a/third_party/blink/renderer/core/html/time_ranges.cc b/third_party/blink/renderer/core/html/time_ranges.cc
index ee2ea40..08ad418 100644
--- a/third_party/blink/renderer/core/html/time_ranges.cc
+++ b/third_party/blink/renderer/core/html/time_ranges.cc
@@ -25,6 +25,7 @@
 
 #include "third_party/blink/renderer/core/html/time_ranges.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -36,7 +37,7 @@
 }
 
 TimeRanges::TimeRanges(const blink::WebTimeRanges& web_ranges) {
-  wtf_size_t size = SafeCast<wtf_size_t>(web_ranges.size());
+  wtf_size_t size = base::checked_cast<wtf_size_t>(web_ranges.size());
   for (wtf_size_t i = 0; i < size; ++i)
     Add(web_ranges[i].start, web_ranges[i].end);
 }
diff --git a/third_party/blink/renderer/core/html/track/text_track_cue_list.cc b/third_party/blink/renderer/core/html/track/text_track_cue_list.cc
index 30b9b17..ac66627c 100644
--- a/third_party/blink/renderer/core/html/track/text_track_cue_list.cc
+++ b/third_party/blink/renderer/core/html/track/text_track_cue_list.cc
@@ -26,7 +26,8 @@
 #include "third_party/blink/renderer/core/html/track/text_track_cue_list.h"
 
 #include <algorithm>
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+
+#include "base/numerics/safe_conversions.h"
 
 namespace blink {
 
@@ -84,7 +85,7 @@
     const TextTrackCue* cue_to_insert) const {
   auto* it =
       std::upper_bound(list_.begin(), list_.end(), cue_to_insert, CueIsBefore);
-  wtf_size_t index = SafeCast<wtf_size_t>(it - list_.begin());
+  wtf_size_t index = base::checked_cast<wtf_size_t>(it - list_.begin());
   SECURITY_DCHECK(index <= list_.size());
   return index;
 }
diff --git a/third_party/blink/renderer/core/input/pointer_event_manager.cc b/third_party/blink/renderer/core/input/pointer_event_manager.cc
index 91135bad..1f6e5e9 100644
--- a/third_party/blink/renderer/core/input/pointer_event_manager.cc
+++ b/third_party/blink/renderer/core/input/pointer_event_manager.cc
@@ -368,7 +368,8 @@
          WebPointerProperties::PointerType::kTouch);
 
   LayoutSize hit_rect_size = GetHitTestRectForAdjustment(
-      *frame_, LayoutSize(pointer_event.width, pointer_event.height));
+      *frame_, LayoutSize(LayoutUnit(pointer_event.width),
+                          LayoutUnit(pointer_event.height)));
 
   if (hit_rect_size.IsEmpty())
     return;
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc b/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc
index 144bf92..a61695a8 100644
--- a/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/inspector/inspector_audits_agent.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-blink.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
 #include "third_party/blink/public/platform/web_data.h"
@@ -52,7 +53,7 @@
                         kUnpremul_SkAlphaType);
   uint32_t row_bytes = static_cast<uint32_t>(info.minRowBytes());
   Vector<unsigned char> pixel_storage(
-      SafeCast<wtf_size_t>(info.computeByteSize(row_bytes)));
+      base::checked_cast<wtf_size_t>(info.computeByteSize(row_bytes)));
   SkPixmap pixmap(info, pixel_storage.data(), row_bytes);
   sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
 
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
index c8c395d3..54f0b146 100644
--- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -724,6 +724,8 @@
   HashSet<String> unique_names;
   *class_names = std::make_unique<protocol::Array<String>>();
   Node* parent_node = NodeForId(node_id);
+  if (!parent_node)
+    return Response::ServerError("No suitable node with given id found");
   auto* parent_element = DynamicTo<Element>(parent_node);
   if (!parent_element && !parent_node->IsDocumentNode() &&
       !parent_node->IsDocumentFragment())
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index c56bf94..3c6c51f 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -35,6 +35,7 @@
 
 #include "base/containers/span.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
 #include "net/base/ip_address.h"
 #include "net/base/ip_endpoint.h"
@@ -1782,9 +1783,9 @@
     size += span.size();
   }
   Vector<char> flatten;
-  flatten.ReserveCapacity(SafeCast<wtf_size_t>(size));
+  flatten.ReserveCapacity(base::checked_cast<wtf_size_t>(size));
   for (const auto& span : data) {
-    flatten.Append(span.data(), SafeCast<wtf_size_t>(span.size()));
+    flatten.Append(span.data(), base::checked_cast<wtf_size_t>(span.size()));
   }
   GetFrontend()->webSocketFrameReceived(
       IdentifiersFactory::SubresourceRequestId(identifier),
diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
index bcf5639..3e9dab2 100644
--- a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
@@ -34,6 +34,7 @@
 #include <utility>
 
 #include "base/containers/span.h"
+#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/frame/frame_ad_evidence.h"
@@ -318,9 +319,10 @@
   }
 
   const SharedBuffer::DeprecatedFlatData flat_buffer(std::move(buffer));
-  return MaybeEncodeTextContent(text_content, flat_buffer.Data(),
-                                SafeCast<wtf_size_t>(flat_buffer.size()),
-                                result, base64_encoded);
+  return MaybeEncodeTextContent(
+      text_content, flat_buffer.Data(),
+      base::checked_cast<wtf_size_t>(flat_buffer.size()), result,
+      base64_encoded);
 }
 
 // static
@@ -350,13 +352,13 @@
     text_content = decoder->Decode(flat_buffer.Data(), flat_buffer.size());
     text_content = text_content + decoder->Flush();
   } else if (encoding.IsValid()) {
-    text_content = encoding.Decode(flat_buffer.Data(),
-                                   SafeCast<wtf_size_t>(flat_buffer.size()));
+    text_content = encoding.Decode(
+        flat_buffer.Data(), base::checked_cast<wtf_size_t>(flat_buffer.size()));
   }
 
   MaybeEncodeTextContent(text_content, flat_buffer.Data(),
-                         SafeCast<wtf_size_t>(flat_buffer.size()), result,
-                         base64_encoded);
+                         base::checked_cast<wtf_size_t>(flat_buffer.size()),
+                         result, base64_encoded);
   return true;
 }
 
diff --git a/third_party/blink/renderer/core/inspector/network_resources_data.cc b/third_party/blink/renderer/core/inspector/network_resources_data.cc
index 25d18925..9f7d205 100644
--- a/third_party/blink/renderer/core/inspector/network_resources_data.cc
+++ b/third_party/blink/renderer/core/inspector/network_resources_data.cc
@@ -29,6 +29,8 @@
 #include "third_party/blink/renderer/core/inspector/network_resources_data.h"
 
 #include <memory>
+
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/core/dom/dom_implementation.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
@@ -303,7 +305,7 @@
                                                 uint64_t data_length) {
   if (ResourceData* resource_data =
           PrepareToAddResourceData(request_id, data_length)) {
-    resource_data->AppendData(data, SafeCast<size_t>(data_length));
+    resource_data->AppendData(data, base::checked_cast<size_t>(data_length));
   }
 }
 
diff --git a/third_party/blink/renderer/core/inspector/v8_inspector_string.cc b/third_party/blink/renderer/core/inspector/v8_inspector_string.cc
index 490c9c5..dc617f0d 100644
--- a/third_party/blink/renderer/core/inspector/v8_inspector_string.cc
+++ b/third_party/blink/renderer/core/inspector/v8_inspector_string.cc
@@ -5,6 +5,8 @@
 #include "third_party/blink/renderer/core/inspector/v8_inspector_string.h"
 
 #include <utility>
+
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/core/inspector/protocol/protocol.h"
 #include "third_party/blink/renderer/platform/wtf/text/base64.h"
 #include "third_party/inspector_protocol/crdtp/cbor.h"
@@ -31,10 +33,10 @@
 String ToCoreString(const v8_inspector::StringView& string) {
   if (string.is8Bit()) {
     return String(reinterpret_cast<const LChar*>(string.characters8()),
-                  SafeCast<wtf_size_t>(string.length()));
+                  base::checked_cast<wtf_size_t>(string.length()));
   }
   return String(reinterpret_cast<const UChar*>(string.characters16()),
-                SafeCast<wtf_size_t>(string.length()));
+                base::checked_cast<wtf_size_t>(string.length()));
 }
 
 String ToCoreString(std::unique_ptr<v8_inspector::StringBuffer> buffer) {
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_offset.h b/third_party/blink/renderer/core/layout/geometry/logical_offset.h
index dd494af..f56a332 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_offset.h
@@ -26,9 +26,10 @@
   constexpr LogicalOffset(LayoutUnit inline_offset, LayoutUnit block_offset)
       : inline_offset(inline_offset), block_offset(block_offset) {}
 
-  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
-  // or int. Use explicit LayoutUnit constructor for each parameter instead.
-  LogicalOffset(float, float) = delete;
+  // This is deleted to avoid unwanted lossy conversion from float or double to
+  // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter
+  // instead.
+  LogicalOffset(double, double) = delete;
 
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
   // 'constexpr' is to let compiler detect incorrect usages in production code.
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_rect.h b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
index fe1c94b..f6c95d07 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_rect.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_rect.h
@@ -28,9 +28,10 @@
                         LayoutUnit block_size)
       : offset(inline_offset, block_offset), size(inline_size, block_size) {}
 
-  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
-  // or int. Use explicit LayoutUnit constructor for each parameter instead.
-  LogicalRect(float, float, float, float) = delete;
+  // This is deleted to avoid unwanted lossy conversion from float or double to
+  // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter
+  // instead.
+  LogicalRect(double, double, double, double) = delete;
 
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
   // 'constexpr' is to let compiler detect usage from production code.
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_size.h b/third_party/blink/renderer/core/layout/geometry/logical_size.h
index e952b385..54f7481 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_size.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_size.h
@@ -24,9 +24,10 @@
   constexpr LogicalSize(LayoutUnit inline_size, LayoutUnit block_size)
       : inline_size(inline_size), block_size(block_size) {}
 
-  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
-  // or int. Use explicit LayoutUnit constructor for each parameter instead.
-  LogicalSize(float, float) = delete;
+  // This is deleted to avoid unwanted lossy conversion from float or double to
+  // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter
+  // instead.
+  LogicalSize(double, double) = delete;
 
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
   // 'constexpr' is to let compiler detect usage from production code.
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_offset.h b/third_party/blink/renderer/core/layout/geometry/physical_offset.h
index 2ffc06a..d0564a1 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_offset.h
@@ -31,10 +31,10 @@
   constexpr PhysicalOffset(LayoutUnit left, LayoutUnit top)
       : left(left), top(top) {}
 
-  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
-  // or int. Use explicit LayoutUnit constructor for each parameter, or use
-  // FromPointFFloor etc. instead.
-  PhysicalOffset(float, float) = delete;
+  // This is deleted to avoid unwanted lossy conversion from float or double to
+  // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter,
+  // or use FromPointF*() instead.
+  PhysicalOffset(double, double) = delete;
 
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
   // 'constexpr' is to let compiler detect usage from production code.
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_rect.h b/third_party/blink/renderer/core/layout/geometry/physical_rect.h
index 6c1c426..e716c6c 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_rect.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_rect.h
@@ -41,10 +41,10 @@
                          LayoutUnit height)
       : offset(left, top), size(width, height) {}
 
-  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
-  // or int. Use explicit LayoutUnit constructor for each parameter, or use
-  // EnclosingRect() or FastAndLossyFromRectF() instead.
-  PhysicalRect(float, float, float, float) = delete;
+  // This is deleted to avoid unwanted lossy conversion from float or double to
+  // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter,
+  // or use EnclosingRect() or FastAndLossyFromRectF() instead.
+  PhysicalRect(double, double, double, double) = delete;
 
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
   // 'constexpr' is to let compiler detect usage from production code.
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_size.h b/third_party/blink/renderer/core/layout/geometry/physical_size.h
index e50df6b..63ebf1f 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_size.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_size.h
@@ -29,10 +29,10 @@
   constexpr PhysicalSize(LayoutUnit width, LayoutUnit height)
       : width(width), height(height) {}
 
-  // This is deleted to avoid unwanted lossy conversion from float to LayoutUnit
-  // or int. Use explicit LayoutUnit constructor for each parameter, or use
-  // FromSizeF*() instead.
-  PhysicalSize(float, float) = delete;
+  // This is deleted to avoid unwanted lossy conversion from float or double to
+  // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter,
+  // or use FromSizeF*() instead.
+  PhysicalSize(double, double) = delete;
 
   // For testing only. It's defined in core/testing/core_unit_test_helper.h.
   // 'constexpr' is to let compiler detect usage from production code.
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc
index dace2e3..b7cca51 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -67,6 +67,7 @@
 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
 #include "third_party/blink/renderer/core/page/named_pages_mapper.h"
 #include "third_party/blink/renderer/core/paint/block_flow_paint_invalidator.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -4439,7 +4440,8 @@
     for (const NGPhysicalBoxFragment& fragment : PhysicalFragments()) {
       if (const NGFragmentItems* items = fragment.Items()) {
         NGInlineCursor cursor(fragment, *items);
-        NGFragmentItem::RecalcInkOverflowForCursor(&cursor);
+        NGInlinePaintContext inline_context;
+        NGFragmentItem::RecalcInkOverflowForCursor(&cursor, &inline_context);
       }
       // Even if this turned out to be an inline formatting context with
       // fragment items (handled above), we need to handle floating descendants.
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
index 2d14a8d..f9d4c6e6 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -45,6 +45,7 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section_interface.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.h"
 #include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
@@ -581,8 +582,12 @@
   if (IsInline() && IsInLayoutNGInlineFormattingContext()) {
     DCHECK(HasSelfPaintingLayer());
     NGInlineCursor cursor;
-    for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject())
-      cursor.Current().RecalcInkOverflow(cursor);
+    NGInlinePaintContext inline_context;
+    for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject()) {
+      NGInlinePaintContext::ScopedInlineBoxAncestors scoped_items(
+          cursor, &inline_context);
+      cursor.Current().RecalcInkOverflow(cursor, &inline_context);
+    }
     return;
   }
 
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
index 590da75..2891f12 100644
--- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -839,8 +839,7 @@
   LayoutUnit border_and_padding;
   if (ar_type == EAspectRatioType::kRatio ||
       (ar_type == EAspectRatioType::kAutoAndRatio && aspect_ratio.IsEmpty())) {
-    gfx::SizeF int_ratio = child.StyleRef().AspectRatio().GetRatio();
-    aspect_ratio = LayoutSize{int_ratio.width(), int_ratio.height()};
+    aspect_ratio = LayoutSize(child.StyleRef().AspectRatio().GetRatio());
     if (child.StyleRef().BoxSizingForAspectRatio() == EBoxSizing::kContentBox) {
       cross_size -= cross_axis_border_and_padding;
       border_and_padding = main_axis_border_and_padding;
diff --git a/third_party/blink/renderer/core/layout/layout_html_canvas.cc b/third_party/blink/renderer/core/layout/layout_html_canvas.cc
index 537f17b..097f167 100644
--- a/third_party/blink/renderer/core/layout/layout_html_canvas.cc
+++ b/third_party/blink/renderer/core/layout/layout_html_canvas.cc
@@ -49,8 +49,7 @@
 void LayoutHTMLCanvas::CanvasSizeChanged() {
   NOT_DESTROYED();
   gfx::Size canvas_size = To<HTMLCanvasElement>(GetNode())->Size();
-  LayoutSize zoomed_size(canvas_size.width() * StyleRef().EffectiveZoom(),
-                         canvas_size.height() * StyleRef().EffectiveZoom());
+  LayoutSize zoomed_size = LayoutSize(canvas_size) * StyleRef().EffectiveZoom();
 
   if (zoomed_size == IntrinsicSize())
     return;
diff --git a/third_party/blink/renderer/core/layout/layout_object_factory.cc b/third_party/blink/renderer/core/layout/layout_object_factory.cc
index 91f016e..a55024f 100644
--- a/third_party/blink/renderer/core/layout/layout_object_factory.cc
+++ b/third_party/blink/renderer/core/layout/layout_object_factory.cc
@@ -187,6 +187,17 @@
                                                     LegacyLayout legacy) {
   const Node* parent = node.parentNode();
   const ComputedStyle* parent_style = parent->GetComputedStyle();
+
+  if (legacy == LegacyLayout::kForce) {
+    // A table inside an inline element with specified columns may end up
+    // marking a list-item ancestor with a size container-type for forced legacy
+    // without re-attaching it during interleaved style recalc. Enforce
+    // legacy/ng consistency between list-item and marker.
+    DCHECK(!RuntimeEnabledFeatures::LayoutNGTableFragmentationEnabled());
+    DCHECK(parent->GetLayoutObject());
+    if (parent->GetLayoutObject()->IsLayoutNGObject())
+      legacy = LegacyLayout::kAuto;
+  }
   bool is_inside =
       parent_style->ListStylePosition() == EListStylePosition::kInside ||
       (IsA<HTMLLIElement>(parent) && !parent_style->IsInsideListElement());
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index ac91dda8..5c33864 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -25,6 +25,8 @@
 #include "third_party/blink/renderer/core/layout/layout_text.h"
 
 #include <algorithm>
+
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
@@ -2904,8 +2906,10 @@
                                 size_t size) {
   NOT_DESTROYED();
 #if DCHECK_IS_ON()
-  for (size_t i = begin; i < begin + size; i++)
-    DCHECK_EQ(data->items[SafeCast<wtf_size_t>(i)].GetLayoutObject(), this);
+  for (size_t i = begin; i < begin + size; i++) {
+    DCHECK_EQ(data->items[base::checked_cast<wtf_size_t>(i)].GetLayoutObject(),
+              this);
+  }
 #endif
   auto* items = GetNGInlineItems();
   if (!items)
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.cc b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.cc
index db9040a..3a3102db 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.h"
 #include "third_party/blink/renderer/platform/fonts/font.h"
 #include "third_party/blink/renderer/platform/fonts/font_description.h"
 #include "third_party/blink/renderer/platform/transforms/affine_transform.h"
@@ -228,9 +229,11 @@
   LayoutRect ink_overflow = text_rect.ToLayoutRect();
 
   if (!style.AppliedTextDecorations().IsEmpty()) {
+    // |LayoutNGTextCombine| does not support decorating box, as it is not
+    // supported in vertical flow and text-combine is only for vertical flow.
     const LayoutRect decoration_rect =
-        NGInkOverflow::ComputeTextDecorationOverflow(style, style.GetFont(),
-                                                     ink_overflow);
+        NGInkOverflow::ComputeTextDecorationOverflow(
+            style, style.GetFont(), ink_overflow, /* inline_context */ nullptr);
     ink_overflow.Unite(decoration_rect);
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
index a9e0b92..e445fcb 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.h"
 #include "third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h"
 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
 
@@ -805,7 +806,8 @@
 }
 
 PhysicalRect NGFragmentItem::RecalcInkOverflowForCursor(
-    NGInlineCursor* cursor) {
+    NGInlineCursor* cursor,
+    NGInlinePaintContext* inline_context) {
   DCHECK(cursor);
   DCHECK(!cursor->Current() || cursor->IsAtFirst());
   PhysicalRect contents_ink_overflow;
@@ -822,7 +824,8 @@
       continue;
 
     PhysicalRect child_rect;
-    item->GetMutableForPainting().RecalcInkOverflow(*cursor, &child_rect);
+    item->GetMutableForPainting().RecalcInkOverflow(*cursor, inline_context,
+                                                    &child_rect);
     if (!child_rect.IsEmpty()) {
       child_rect.offset += item->OffsetInContainerFragment();
       contents_ink_overflow.Unite(child_rect);
@@ -833,6 +836,7 @@
 
 void NGFragmentItem::RecalcInkOverflow(
     const NGInlineCursor& cursor,
+    NGInlinePaintContext* inline_context,
     PhysicalRect* self_and_contents_rect_out) {
   DCHECK_EQ(this, cursor.CurrentItem());
 
@@ -863,8 +867,12 @@
             BuildSvgTransformForBoundingBox(), self_and_contents_rect_out);
         return;
       }
+      // Create |ScopedInlineItem| here because the decoration box is not
+      // supported for SVG.
+      NGInlinePaintContext::ScopedInlineItem scoped_inline_item(*this,
+                                                                inline_context);
       ink_overflow_type_ = ink_overflow_.SetTextInkOverflow(
-          InkOverflowType(), paint_info, Style(), Size(),
+          InkOverflowType(), paint_info, Style(), Size(), inline_context,
           self_and_contents_rect_out);
       return;
     }
@@ -874,10 +882,11 @@
     return;
   }
 
-  const NGPhysicalBoxFragment* box_fragment = BoxFragment();
-  if (box_fragment) {
-    box_fragment = box_fragment->PostLayout();
-    if (box_fragment && !box_fragment->IsInlineBox()) {
+  if (Type() == kBox) {
+    const NGPhysicalBoxFragment* box_fragment = PostLayoutBoxFragment();
+    if (UNLIKELY(!box_fragment))
+      return;
+    if (!box_fragment->IsInlineBox()) {
       DCHECK(!HasChildren());
       if (box_fragment->CanUseFragmentsForInkOverflow()) {
         box_fragment->GetMutableForPainting().RecalcInkOverflow();
@@ -890,17 +899,23 @@
       *self_and_contents_rect_out = owner_box->PhysicalVisualOverflowRect();
       return;
     }
+
+    DCHECK(box_fragment->IsInlineBox());
+    NGInlinePaintContext::ScopedInlineItem scoped_inline_item(*this,
+                                                              inline_context);
+    const PhysicalRect contents_rect =
+        RecalcInkOverflowForDescendantsOf(cursor, inline_context);
+    DCHECK(box_fragment->Children().empty());
+    DCHECK_EQ(box_fragment->Size(), Size());
+    box_fragment->GetMutableForPainting().RecalcInkOverflow(contents_rect);
+    *self_and_contents_rect_out = box_fragment->InkOverflow();
+    return;
   }
 
-  // Re-compute descendants, then compute the contents ink overflow from them.
-  NGInlineCursor descendants_cursor = cursor.CursorForDescendants();
-  PhysicalRect contents_rect = RecalcInkOverflowForCursor(&descendants_cursor);
-
-  // |contents_rect| is relative to the inline formatting context. Make it
-  // relative to |this|.
-  contents_rect.offset -= OffsetInContainerFragment();
-
   if (Type() == kLine) {
+    NGInlinePaintContext::ScopedLineBox scoped_line_box(cursor, inline_context);
+    PhysicalRect contents_rect =
+        RecalcInkOverflowForDescendantsOf(cursor, inline_context);
     const auto* const text_combine =
         DynamicTo<LayoutNGTextCombine>(GetLayoutObject());
     if (UNLIKELY(text_combine))
@@ -912,18 +927,23 @@
     return;
   }
 
-  if (box_fragment) {
-    DCHECK(box_fragment->IsInlineBox());
-    DCHECK(box_fragment->Children().empty());
-    DCHECK_EQ(box_fragment->Size(), Size());
-    box_fragment->GetMutableForPainting().RecalcInkOverflow(contents_rect);
-    *self_and_contents_rect_out = box_fragment->InkOverflow();
-    return;
-  }
-
   NOTREACHED();
 }
 
+PhysicalRect NGFragmentItem::RecalcInkOverflowForDescendantsOf(
+    const NGInlineCursor& cursor,
+    NGInlinePaintContext* inline_context) const {
+  // Re-compute descendants, then compute the contents ink overflow from them.
+  NGInlineCursor descendants_cursor = cursor.CursorForDescendants();
+  PhysicalRect contents_rect =
+      RecalcInkOverflowForCursor(&descendants_cursor, inline_context);
+
+  // |contents_rect| is relative to the inline formatting context. Make it
+  // relative to |this|.
+  contents_rect.offset -= OffsetInContainerFragment();
+  return contents_rect;
+}
+
 void NGFragmentItem::SetDeltaToNextForSameLayoutObject(wtf_size_t delta) const {
   DCHECK_NE(Type(), kLine);
   delta_to_next_for_same_layout_object_ = delta;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
index dd7d0d3..67d6fb4 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
@@ -25,6 +25,7 @@
 
 class NGFragmentItems;
 class NGInlineBreakToken;
+class NGInlinePaintContext;
 struct NGTextFragmentPaintInfo;
 struct NGLogicalLineItem;
 
@@ -306,7 +307,9 @@
   static PhysicalRect LocalVisualRectFor(const LayoutObject& layout_object);
 
   // Re-compute the ink overflow for the |cursor| until its end.
-  static PhysicalRect RecalcInkOverflowForCursor(NGInlineCursor* cursor);
+  static PhysicalRect RecalcInkOverflowForCursor(
+      NGInlineCursor* cursor,
+      NGInlinePaintContext* inline_context);
 
   // Painters can use const methods only, except for these explicitly declared
   // methods.
@@ -316,8 +319,10 @@
    public:
     void InvalidateInkOverflow() { return item_.InvalidateInkOverflow(); }
     void RecalcInkOverflow(const NGInlineCursor& cursor,
+                           NGInlinePaintContext* inline_context,
                            PhysicalRect* self_and_contents_rect_out) {
-      return item_.RecalcInkOverflow(cursor, self_and_contents_rect_out);
+      return item_.RecalcInkOverflow(cursor, inline_context,
+                                     self_and_contents_rect_out);
     }
 
    private:
@@ -560,7 +565,11 @@
 
   // Re-compute the ink overflow for this item. |cursor| should be at |this|.
   void RecalcInkOverflow(const NGInlineCursor& cursor,
+                         NGInlinePaintContext* inline_context,
                          PhysicalRect* self_and_contents_rect_out);
+  PhysicalRect RecalcInkOverflowForDescendantsOf(
+      const NGInlineCursor& cursor,
+      NGInlinePaintContext* inline_context) const;
 
   // Compute the inline position from text offset, in logical coordinate
   // relative to this fragment.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
index b3e05dc52..0f0f989 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.h"
 
 namespace blink {
 class HTMLBRElement;
@@ -460,11 +461,12 @@
 }
 
 void NGInlineCursorPosition::RecalcInkOverflow(
-    const NGInlineCursor& cursor) const {
+    const NGInlineCursor& cursor,
+    NGInlinePaintContext* inline_context) const {
   DCHECK(item_);
   DCHECK_EQ(item_, cursor.Current().Item());
   PhysicalRect self_and_contents_rect;
-  item_->GetMutableForPainting().RecalcInkOverflow(cursor,
+  item_->GetMutableForPainting().RecalcInkOverflow(cursor, inline_context,
                                                    &self_and_contents_rect);
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
index a79650c..a4e7beb 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
@@ -31,6 +31,7 @@
 class NGInlineBackwardCursor;
 class NGInlineBreakToken;
 class NGInlineCursor;
+class NGInlinePaintContext;
 class NGPhysicalBoxFragment;
 class Node;
 class ShapeResultView;
@@ -156,7 +157,8 @@
     return item_->SelfInkOverflow();
   }
 
-  void RecalcInkOverflow(const NGInlineCursor& cursor) const;
+  void RecalcInkOverflow(const NGInlineCursor& cursor,
+                         NGInlinePaintContext* inline_context) const;
 
   // Returns start/end of offset in text content of current text fragment.
   // It is error when this cursor doesn't point to text fragment.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
index 3fb98a7..fd1b806 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
@@ -344,11 +344,12 @@
     const NGTextFragmentPaintInfo& text_info,
     const ComputedStyle& style,
     const PhysicalSize& size,
+    const NGInlinePaintContext* inline_context,
     PhysicalRect* ink_overflow_out) {
   CheckType(type);
   DCHECK(type == kNotSet || type == kInvalidated);
-  absl::optional<PhysicalRect> ink_overflow =
-      ComputeTextInkOverflow(text_info, style, style.GetFont(), size);
+  absl::optional<PhysicalRect> ink_overflow = ComputeTextInkOverflow(
+      text_info, style, style.GetFont(), size, inline_context);
   if (!ink_overflow) {
     *ink_overflow_out = {PhysicalOffset(), size};
     return Reset(type);
@@ -378,8 +379,9 @@
                          LayoutUnit(rect.height()))
           : PhysicalSize(LayoutUnit(rect.width()),
                          LayoutUnit(rect.height() / length_adjust_scale));
-  absl::optional<PhysicalRect> ink_overflow =
-      ComputeTextInkOverflow(text_info, style, scaled_font, item_size);
+  // No |inline_context| because the decoration box is not supported for SVG.
+  absl::optional<PhysicalRect> ink_overflow = ComputeTextInkOverflow(
+      text_info, style, scaled_font, item_size, /* inline_context */ nullptr);
   const bool needs_transform =
       scaling_factor != 1.0f || !transform.IsIdentity();
   PhysicalSize unscaled_size = PhysicalSize::FromSizeFRound(rect.size());
@@ -427,7 +429,8 @@
     const NGTextFragmentPaintInfo& text_info,
     const ComputedStyle& style,
     const Font& scaled_font,
-    const PhysicalSize& size) {
+    const PhysicalSize& size,
+    const NGInlinePaintContext* inline_context) {
   // Glyph bounds is in logical coordinate, origin at the alphabetic baseline.
   const gfx::RectF text_ink_bounds = scaled_font.TextInkBounds(text_info);
   LayoutRect ink_overflow = EnclosingLayoutRect(text_ink_bounds);
@@ -446,8 +449,8 @@
   // Following effects, such as shadows, operate on the text decorations,
   // so compute text decoration overflow first.
   if (!style.AppliedTextDecorations().IsEmpty() && scaled_font.PrimaryFont()) {
-    LayoutRect decoration_rect =
-        ComputeTextDecorationOverflow(style, scaled_font, ink_overflow);
+    LayoutRect decoration_rect = ComputeTextDecorationOverflow(
+        style, scaled_font, ink_overflow, inline_context);
     ink_overflow.Unite(decoration_rect);
   }
 
@@ -506,7 +509,8 @@
 LayoutRect NGInkOverflow::ComputeTextDecorationOverflow(
     const ComputedStyle& style,
     const Font& scaled_font,
-    const LayoutRect& ink_overflow) {
+    const LayoutRect& ink_overflow,
+    const NGInlinePaintContext* inline_context) {
   DCHECK(!style.AppliedTextDecorations().IsEmpty());
   // Use a zero offset because all offsets
   // are applied to the ink overflow after it has been computed.
@@ -518,8 +522,7 @@
   // because it just makes the resultant ink overflow slightly larger.
   const MinimumThickness1 kMinimumThicknessIsOne(true);
   TextDecorationInfo decoration_info(
-      offset, ink_overflow.Width(), style,
-      /* inline_context */ nullptr,
+      offset, ink_overflow.Width(), style, inline_context,
       /* selection_text_decoration */ absl::nullopt, &scaled_font,
       kMinimumThicknessIsOne);
   NGTextDecorationOffset decoration_offset(decoration_info.TargetStyle(),
diff --git a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
index 7c936fd..ee86ae1 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
@@ -17,6 +17,7 @@
 class AffineTransform;
 class ComputedStyle;
 class Font;
+class NGInlinePaintContext;
 struct NGTextFragmentPaintInfo;
 
 // Represents an ink-overflow rectangle. Used for:
@@ -117,6 +118,7 @@
                           const NGTextFragmentPaintInfo& text_info,
                           const ComputedStyle& style,
                           const PhysicalSize& size,
+                          const NGInlinePaintContext* inline_context,
                           PhysicalRect* ink_overflow_out);
 
   // Compute and set ink overflow for SVG text.
@@ -136,7 +138,8 @@
       const NGTextFragmentPaintInfo& text_info,
       const ComputedStyle& style,
       const Font& scaled_font,
-      const PhysicalSize& size);
+      const PhysicalSize& size,
+      const NGInlinePaintContext* inline_context);
 
   // Returns ink-overflow with emphasis mark overflow in logical direction.
   // |size| is a size of text item, e.g. |NGFragmentItem::Size()|.
@@ -152,7 +155,8 @@
   static LayoutRect ComputeTextDecorationOverflow(
       const ComputedStyle& style,
       const Font& scaled_font,
-      const LayoutRect& ink_overflow);
+      const LayoutRect& ink_overflow,
+      const NGInlinePaintContext* inline_context);
 
 #if DCHECK_IS_ON()
   struct ReadUnsetAsNoneScope {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index c8358bc..1358152e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -28,6 +28,7 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_outline_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_cell.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.h"
 #include "third_party/blink/renderer/core/paint/outline_painter.h"
 #include "third_party/blink/renderer/platform/geometry/layout_rect_outsets.h"
 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
@@ -1157,7 +1158,9 @@
   PhysicalRect contents_rect;
   if (const NGFragmentItems* items = Items()) {
     NGInlineCursor cursor(*this, *items);
-    contents_rect = NGFragmentItem::RecalcInkOverflowForCursor(&cursor);
+    NGInlinePaintContext child_inline_context;
+    contents_rect = NGFragmentItem::RecalcInkOverflowForCursor(
+        &cursor, &child_inline_context);
 
     // Add text decorations and emphasis mark ink over flow for combined
     // text.
diff --git a/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc b/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc
index 18650dd8..82f8541 100644
--- a/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc
+++ b/third_party/blink/renderer/core/layout/ng/svg/layout_ng_svg_text.cc
@@ -225,8 +225,10 @@
   // If our bounds changed, notify the parents.
   if (UpdateTransformAfterLayout(bounds_changed) || bounds_changed)
     SetNeedsBoundariesUpdate();
-  if (bounds_changed)
-    SetSize(LayoutSize(boundaries.right(), boundaries.bottom()));
+  if (bounds_changed) {
+    SetSize(LayoutSize(LayoutUnit(boundaries.right()),
+                       LayoutUnit(boundaries.bottom())));
+  }
 
   UpdateTransformAffectsVectorEffect();
 }
diff --git a/third_party/blink/renderer/core/layout/shapes/ellipse_shape.cc b/third_party/blink/renderer/core/layout/shapes/ellipse_shape.cc
index 755f1b55..2bbc3d8 100644
--- a/third_party/blink/renderer/core/layout/shapes/ellipse_shape.cc
+++ b/third_party/blink/renderer/core/layout/shapes/ellipse_shape.cc
@@ -40,9 +40,10 @@
   DCHECK_GE(ShapeMargin(), 0);
   float margin_radius_x = radius_x_ + ShapeMargin();
   float margin_radius_y = radius_y_ + ShapeMargin();
-  return LayoutRect(center_.x() - margin_radius_x,
-                    center_.y() - margin_radius_y, margin_radius_x * 2,
-                    margin_radius_y * 2);
+  return LayoutRect(LayoutUnit(center_.x() - margin_radius_x),
+                    LayoutUnit(center_.y() - margin_radius_y),
+                    LayoutUnit(margin_radius_x * 2),
+                    LayoutUnit(margin_radius_y * 2));
 }
 
 LineSegment EllipseShape::GetExcludedInterval(LayoutUnit logical_top,
diff --git a/third_party/blink/renderer/core/layout/shapes/ellipse_shape_test.cc b/third_party/blink/renderer/core/layout/shapes/ellipse_shape_test.cc
index b43b880..1daed8c 100644
--- a/third_party/blink/renderer/core/layout/shapes/ellipse_shape_test.cc
+++ b/third_party/blink/renderer/core/layout/shapes/ellipse_shape_test.cc
@@ -105,4 +105,15 @@
   EXPECT_INVALID_EXCLUDED_INTERVAL(shape, 100, 1);
 }
 
+TEST(EllipseShapeTest, ShapeMarginLogicalBoundingBoxWithFloatValues) {
+  EXPECT_EQ(LayoutRect(LayoutUnit(-2.25f), LayoutUnit(-2.125f), LayoutUnit(7),
+                       LayoutUnit(9.75f)),
+            EllipseShape(gfx::PointF(1.25f, 2.75f), 3.5f, 4.875f)
+                .ShapeMarginLogicalBoundingBox());
+  EXPECT_EQ(LayoutRect(LayoutUnit::Min(), LayoutUnit(), LayoutUnit::Max(),
+                       LayoutUnit()),
+            EllipseShape(gfx::PointF(), 1e20f, 1e-20f)
+                .ShapeMarginLogicalBoundingBox());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
index 606e0d7c..47d4cf4 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -62,8 +62,9 @@
   auto* svg = To<SVGSVGElement>(node);
   DCHECK(svg);
 
-  SetIntrinsicSize(LayoutSize(svg->IntrinsicWidth().value_or(kDefaultWidth),
-                              svg->IntrinsicHeight().value_or(kDefaultHeight)));
+  SetIntrinsicSize(
+      LayoutSize(LayoutUnit(svg->IntrinsicWidth().value_or(kDefaultWidth)),
+                 LayoutUnit(svg->IntrinsicHeight().value_or(kDefaultHeight))));
 }
 
 LayoutSVGRoot::~LayoutSVGRoot() = default;
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index b6d5ee3f..275d80c 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -38,6 +38,7 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/stl_util.h"
 #include "base/time/default_tick_clock.h"
 #include "build/chromeos_buildflags.h"
@@ -184,7 +185,7 @@
     const WebVector<WebString>& force_enabled_origin_trials) {
   Vector<String> result;
   result.ReserveInitialCapacity(
-      SafeCast<wtf_size_t>(force_enabled_origin_trials.size()));
+      base::checked_cast<wtf_size_t>(force_enabled_origin_trials.size()));
   for (const auto& trial : force_enabled_origin_trials)
     result.push_back(trial);
   return result;
@@ -2650,6 +2651,9 @@
   document->MaybeHandleHttpRefresh(
       response_.HttpHeaderField(http_names::kRefresh),
       Document::kHttpRefreshFromHeader);
+
+  // The parser may have collected preloads in the background, flush them now.
+  parser_->FlushPendingPreloads();
 }
 
 const AtomicString& DocumentLoader::MimeType() const {
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource.cc b/third_party/blink/renderer/core/loader/resource/image_resource.cc
index c162723..954140fc 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource.cc
@@ -303,7 +303,7 @@
 void ImageResource::AppendData(const char* data, size_t length) {
   v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(length);
   if (multipart_parser_) {
-    multipart_parser_->AppendData(data, SafeCast<wtf_size_t>(length));
+    multipart_parser_->AppendData(data, base::checked_cast<wtf_size_t>(length));
   } else {
     Resource::AppendData(data, length);
 
diff --git a/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc b/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc
index f8422c0..3f9fa4a 100644
--- a/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc
+++ b/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc
@@ -8,9 +8,9 @@
 #include <stdint.h>
 #include <string.h>
 
+#include "base/numerics/safe_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 namespace multipart_image_resource_parser_test {
@@ -29,7 +29,7 @@
     data_.push_back(Vector<char>());
   }
   void MultipartDataReceived(const char* bytes, size_t size) override {
-    data_.back().Append(bytes, SafeCast<wtf_size_t>(size));
+    data_.back().Append(bytes, base::checked_cast<wtf_size_t>(size));
   }
 
   Vector<ResourceResponse> responses_;
diff --git a/third_party/blink/renderer/core/loader/threadable_loader.cc b/third_party/blink/renderer/core/loader/threadable_loader.cc
index 324ede5..f3bae64 100644
--- a/third_party/blink/renderer/core/loader/threadable_loader.cc
+++ b/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -33,6 +33,7 @@
 
 #include <memory>
 
+#include "base/numerics/safe_conversions.h"
 #include "services/network/public/cpp/cors/cors_error_status.h"
 #include "services/network/public/mojom/cors.mojom-blink.h"
 #include "services/network/public/mojom/fetch_api.mojom-blink.h"
@@ -323,7 +324,7 @@
 
   // TODO(junov): Fix the ThreadableLoader ecosystem to use size_t. Until then,
   // we use safeCast to trap potential overflows.
-  client_->DidReceiveData(data, SafeCast<unsigned>(data_length));
+  client_->DidReceiveData(data, base::checked_cast<unsigned>(data_length));
 }
 
 void ThreadableLoader::NotifyFinished(Resource* resource) {
diff --git a/third_party/blink/renderer/core/messaging/message_port.cc b/third_party/blink/renderer/core/messaging/message_port.cc
index b72ede668..747ce956 100644
--- a/third_party/blink/renderer/core/messaging/message_port.cc
+++ b/third_party/blink/renderer/core/messaging/message_port.cc
@@ -28,6 +28,7 @@
 
 #include <memory>
 
+#include "base/numerics/safe_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
 #include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
@@ -265,7 +266,7 @@
     WebVector<MessagePortChannel> channels) {
   // https://html.spec.whatwg.org/C/#message-ports
   // |ports| should be an empty array, not null even when there is no ports.
-  wtf_size_t count = SafeCast<wtf_size_t>(channels.size());
+  wtf_size_t count = base::checked_cast<wtf_size_t>(channels.size());
   MessagePortArray* port_array = MakeGarbageCollected<MessagePortArray>(count);
   for (wtf_size_t i = 0; i < count; ++i) {
     auto* port = MakeGarbageCollected<MessagePort>(context);
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc
index 568beb3..c526aab 100644
--- a/third_party/blink/renderer/core/page/create_window.cc
+++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -26,6 +26,7 @@
 
 #include "third_party/blink/renderer/core/page/create_window.h"
 
+#include "base/check_op.h"
 #include "base/feature_list.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
@@ -83,8 +84,8 @@
   unsigned key_begin, key_end;
   unsigned value_begin, value_end;
 
-  String buffer = feature_string.LowerASCII();
-  unsigned length = buffer.length();
+  const String buffer = feature_string.LowerASCII();
+  const unsigned length = buffer.length();
   for (unsigned i = 0; i < length;) {
     // skip to first non-separator (start of key name), but don't skip
     // past the end of the string
@@ -201,10 +202,19 @@
       window_features.persistent = true;
     } else if (attribution_reporting_enabled &&
                key_string == "attributionsrc") {
+      // attributionsrc values are URLs, and as such their original case needs
+      // to be retained for correctness. Positions in both `feature_string` and
+      // `buffer` correspond because ASCII-lowercasing doesn't add, remove, or
+      // swap character positions; it only does in-place transformations of
+      // capital ASCII characters. See crbug.com/1338698 for details.
+      DCHECK_EQ(feature_string.length(), buffer.length());
+      const StringView original_case_value_string(feature_string, value_begin,
+                                                  value_end - value_begin);
+
       // attributionsrc values are encoded in order to support embedded special
       // characters, such as '='.
-      const String decoded = DecodeURLEscapeSequences(value_string.ToString(),
-                                                      DecodeURLMode::kUTF8);
+      const String decoded = DecodeURLEscapeSequences(
+          original_case_value_string.ToString(), DecodeURLMode::kUTF8);
 
       if (!decoded.IsEmpty()) {
         window_features.impression =
diff --git a/third_party/blink/renderer/core/page/touch_adjustment.cc b/third_party/blink/renderer/core/page/touch_adjustment.cc
index cec737b..00968c6 100644
--- a/third_party/blink/renderer/core/page/touch_adjustment.cc
+++ b/third_party/blink/renderer/core/page/touch_adjustment.cc
@@ -51,8 +51,8 @@
 const float kZeroTolerance = 1e-6f;
 // The touch adjustment range (diameters) in dip, using same as the value in
 // gesture_configuration_android.cc
-constexpr float kMaxAdjustmentSizeDip = 32.f;
-constexpr float kMinAdjustmentSizeDip = 20.f;
+constexpr LayoutUnit kMaxAdjustmentSizeDip(32);
+constexpr LayoutUnit kMinAdjustmentSizeDip(20);
 
 // Class for remembering absolute quads of a target node and what node they
 // represent.
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
index 6e239d7b..36a530e6 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -259,10 +259,10 @@
 
   if (auto* supplement =
           DocumentTransitionSupplement::FromIfExists(object.GetDocument())) {
-    // Note that `IsTransitionParticipant returns true for values that are in
-    // the non-transition-pseudo tree DOM. That is, things like layout view or
-    // the shared elements that we are transitioning.
-    if (supplement->GetTransition()->IsTransitionParticipant(object))
+    // Note that `NeedsSharedElementEffectNode` returns true for values that are
+    // in the non-transition-pseudo tree DOM. That is, things like layout view
+    // or the shared elements that we are transitioning.
+    if (supplement->GetTransition()->NeedsSharedElementEffectNode(object))
       reasons |= CompositingReason::kDocumentTransitionSharedElement;
   }
 
diff --git a/third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.cc b/third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.cc
index 751c2eec..9df5860a 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_inline_paint_context.cc
@@ -167,8 +167,16 @@
         // All non-culled inline boxes should have called |SyncDecoratingBox|,
         // so the loop should have stopped before seeing non-culled inline
         // boxes.
-        if (!IsA<LayoutText>(layout_object)) {
-          if (const auto* layout_inline = DynamicTo<LayoutInline>(parent)) {
+        if (const auto* layout_inline = DynamicTo<LayoutInline>(parent)) {
+          // Except when |AppliedTextDecorations| is duplicated instead of
+          // shared, see above.
+          if (!(parent_decorations.size() == parent->Parent()
+                                                 ->StyleRef()
+                                                 .AppliedTextDecorations()
+                                                 .size() &&
+                parent_style.GetTextDecorationLine() ==
+                    TextDecorationLine::kNone) &&
+              !IsA<LayoutText>(layout_object)) {
             DCHECK(!layout_inline->ShouldCreateBoxFragment());
             DCHECK(!layout_inline->HasInlineFragments());
           }
diff --git a/third_party/blink/renderer/core/paint/ng/ng_inline_paint_context_test.cc b/third_party/blink/renderer/core/paint/ng/ng_inline_paint_context_test.cc
index 1b39065..1529932 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_inline_paint_context_test.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_inline_paint_context_test.cc
@@ -26,6 +26,62 @@
   }
 };
 
+TEST_F(NGInlinePaintContextTest, VerticalAlign) {
+  LoadAhem();
+  SetBodyInnerHTML(R"HTML(
+    <style>
+    :root {
+      font-family: Ahem;
+      font-size: 10px;
+    }
+    .ul {
+      text-decoration-line: underline;
+    }
+    .up {
+      vertical-align: 1em;
+    }
+    </style>
+    <div>
+      <span id="span1" class="ul">
+        span1
+        <span id="span2" sclass="up ul">
+          span2
+          <span id="span3" class="up">
+            span3
+          </span>
+        </span>
+      </span>
+    </div>
+  )HTML");
+
+  const auto StringFromTextItem = [](const NGInlineCursor& cursor) {
+    return cursor.Current().Text(cursor).ToString().StripWhiteSpace();
+  };
+
+  NGInlineCursor cursor;
+  const LayoutObject* span1 = GetLayoutObjectByElementId("span1");
+  cursor.MoveToIncludingCulledInline(*span1);
+  EXPECT_EQ(StringFromTextItem(cursor), "span1");
+  const NGFragmentItem& span1_item = *cursor.Current();
+
+  const LayoutObject* span2 = GetLayoutObjectByElementId("span2");
+  cursor.MoveToIncludingCulledInline(*span2);
+  EXPECT_EQ(StringFromTextItem(cursor), "span2");
+  const NGFragmentItem& span2_item = *cursor.Current();
+
+  const LayoutObject* span3 = GetLayoutObjectByElementId("span3");
+  cursor.MoveToIncludingCulledInline(*span3);
+  EXPECT_EQ(StringFromTextItem(cursor), "span3");
+  const NGFragmentItem& span3_item = *cursor.Current();
+
+  // The bottom of ink overflows of `span1`, `span2`, and `span3` should match,
+  // because underlines are drawn at the decorating box; i.e., `span1`.
+  EXPECT_EQ(span1_item.InkOverflow().Bottom(),
+            span2_item.InkOverflow().Bottom());
+  EXPECT_EQ(span1_item.InkOverflow().Bottom(),
+            span3_item.InkOverflow().Bottom());
+}
+
 TEST_F(NGInlinePaintContextTest, NestedBlocks) {
   SetBodyInnerHTML(R"HTML(
     <style>
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 21278b93..85b4734 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -2175,8 +2175,7 @@
   LayoutSize current_size = GetLayoutBox()->Size();
   current_size.Scale(1 / zoom_factor);
 
-  LayoutSize adjusted_old_offset = LayoutSize(
-      old_offset.Width() / zoom_factor, old_offset.Height() / zoom_factor);
+  LayoutSize adjusted_old_offset = old_offset * (1.f / zoom_factor);
   if (GetLayoutBox()->ShouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
     new_offset.set_x(-new_offset.x());
     adjusted_old_offset.SetWidth(-adjusted_old_offset.Width());
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 466ae8e..ba0cf66b 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -2790,7 +2790,7 @@
       // Determine whether we're inside block fragmentation or not. OOF
       // descendants need special treatment inside block fragmentation.
       context_.current.is_in_block_fragmentation =
-          pre_paint_info_->fragmentainer_idx != WTF::kNotFound &&
+          pre_paint_info_->fragmentainer_is_oof_containing_block &&
           box->GetNGPaginationBreakability() != LayoutBox::kForbidBreaks;
     } else {
       // TODO(pdr): Several calls in this function walk back up the tree to
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
index e713267..43deda3 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
@@ -279,13 +279,16 @@
                  wtf_size_t fragmentainer_idx,
                  bool is_first_for_node,
                  bool is_last_for_node,
-                 bool is_inside_fragment_child)
+                 bool is_inside_fragment_child,
+                 bool fragmentainer_is_oof_containing_block)
       : box_fragment(box_fragment),
         paint_offset(paint_offset),
         fragmentainer_idx(fragmentainer_idx),
         is_first_for_node(is_first_for_node),
         is_last_for_node(is_last_for_node),
-        is_inside_fragment_child(is_inside_fragment_child) {}
+        is_inside_fragment_child(is_inside_fragment_child),
+        fragmentainer_is_oof_containing_block(
+            fragmentainer_is_oof_containing_block) {}
 
   // The fragment for the LayoutObject currently being processed, or, in the
   // case of text and non-atomic inlines: the fragment of the containing block.
@@ -301,6 +304,14 @@
   // currently being processed. Otherwise, |box_fragment| is a fragment for the
   // LayoutObject itself.
   bool is_inside_fragment_child;
+
+  // Due to how out-of-flow layout inside fragmentation works, if an out-of-flow
+  // positioned element is contained by something that's part of a fragmentation
+  // context (e.g. abspos in relpos in multicol) the containing block (as far as
+  // NG layout is concerned) is a fragmentainer, not the relpos. Then this flag
+  // is true. It's false if the containing block doesn't participate in block
+  // fragmentation, e.g. if we're inside monolithic content.
+  bool fragmentainer_is_oof_containing_block;
 };
 
 struct PaintPropertiesChangeInfo {
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc b/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc
index 0cfbf8d..a0a0893 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc
@@ -155,8 +155,10 @@
       PropertyTreePrinter<EffectPaintPropertyNodeOrAlias>& printer) {
     auto* supplement =
         DocumentTransitionSupplement::FromIfExists(object.GetDocument());
+    // `NeedsSharedElementEffectNode` is an indirect way to see if the object is
+    // participating in the transition.
     if (!supplement ||
-        !supplement->GetTransition()->IsTransitionParticipant(object)) {
+        !supplement->GetTransition()->NeedsSharedElementEffectNode(object)) {
       return;
     }
 
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
index 653b0e76..2fde62c 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -41,6 +41,10 @@
 
 }  // anonymous namespace
 
+bool PrePaintTreeWalk::ContainingFragment::IsInFragmentationContext() const {
+  return fragment && fragment->IsFragmentainerBox();
+}
+
 void PrePaintTreeWalk::WalkTree(LocalFrameView& root_frame_view) {
   if (root_frame_view.ShouldThrottleRendering()) {
     // Skip the throttled frame. Will update it when it becomes unthrottled.
@@ -344,9 +348,10 @@
     const PrePaintTreeWalkContext& context) {
   const auto& fragment = *To<NGPhysicalBoxFragment>(child.fragment.Get());
   return NGPrePaintInfo(fragment, child.offset,
-                        context.current_fragmentainer.fragmentainer_idx,
+                        context.current_container.fragmentainer_idx,
                         fragment.IsFirstForNode(), !fragment.BreakToken(),
-                        /* is_inside_fragment_child */ false);
+                        /* is_inside_fragment_child */ false,
+                        context.current_container.IsInFragmentationContext());
 }
 
 FragmentData* PrePaintTreeWalk::GetOrCreateFragmentData(
@@ -434,26 +439,33 @@
 
 void PrePaintTreeWalk::UpdateContextForOOFContainer(
     const LayoutObject& object,
-    PrePaintTreeWalkContext& context) {
-  DCHECK(object.CanContainAbsolutePositionObjects());
-
-  const LayoutBox* box = DynamicTo<LayoutBox>(&object);
-  if (context.current_fragmentainer.fragment && box &&
-      box->GetNGPaginationBreakability() == LayoutBox::kForbidBreaks) {
-    // If we're in a fragmentation context, the parent fragment of OOFs is the
-    // fragmentainer, unless the object is monolithic, in which case nothing
-    // inside the object participates in the current block fragmentation
-    // context.
-    context.ResetFragmentation();
+    PrePaintTreeWalkContext& context,
+    const NGPhysicalBoxFragment* fragment) {
+  // Flow threads don't exist, as far as LayoutNG is concerned. Yet, we
+  // encounter them here when performing an NG fragment accompanied LayoutObject
+  // subtree walk. Just ignore.
+  if (object.IsLayoutFlowThread())
     return;
+
+  // If we're in a fragmentation context, the parent fragment of OOFs is the
+  // fragmentainer, unless the object is monolithic, in which case nothing
+  // contained by the object participates in the current block fragmentation
+  // context. If we're not participating in block fragmentation, the containing
+  // fragment of an OOF fragment is always simply the parent.
+  const LayoutBox* box = DynamicTo<LayoutBox>(&object);
+  if (!context.current_container.IsInFragmentationContext() ||
+      (box && box->GetNGPaginationBreakability() == LayoutBox::kForbidBreaks)) {
+    context.current_container.fragment = fragment;
   }
 
+  if (!object.CanContainAbsolutePositionObjects())
+    return;
+
   // The OOF containing block structure is special under block fragmentation: A
   // fragmentable OOF is always a direct child of a fragmentainer.
-  context.absolute_positioned_container = context.current_fragmentainer;
-  if (object.CanContainFixedPositionObjects()) {
+  context.absolute_positioned_container = context.current_container;
+  if (object.CanContainFixedPositionObjects())
     context.fixed_positioned_container = context.absolute_positioned_container;
-  }
 }
 
 void PrePaintTreeWalk::WalkInternal(const LayoutObject& object,
@@ -519,10 +531,9 @@
     if (UNLIKELY(child->IsLayoutObjectDestroyedOrMoved()))
       continue;
     if ((child->IsOutOfFlowPositioned() &&
-         (context.current_fragmentainer.fragment ||
-          child->IsFixedPositioned())) ||
+         (context.current_container.fragment || child->IsFixedPositioned())) ||
         (child->IsFloating() && parent.IsInlineFormattingContext() &&
-         context.current_fragmentainer.fragment)) {
+         context.current_container.fragment)) {
       // We'll add resumed floats (or floats that couldn't fit a fragment in the
       // fragmentainer where it was discovered) that have escaped their inline
       // formatting context.
@@ -552,12 +563,15 @@
     return;
   RebuildContextForMissedDescendant(ancestor, *object.Parent(), context);
 
-  if (!object.CanContainAbsolutePositionObjects())
-    return;
+  // We don't need to pass a fragment here, since we're not actually going to
+  // search for any descendant fragment. We've already determined which fragment
+  // that we're going to visit (then one we missed), since we're here.
+  UpdateContextForOOFContainer(object, context, /* fragment */ nullptr);
 
-  UpdateContextForOOFContainer(object, context);
-  if (!context.tree_builder_context)
+  if (!object.CanContainAbsolutePositionObjects() ||
+      !context.tree_builder_context) {
     return;
+  }
 
   PaintPropertyTreeBuilderContext& property_context =
       *context.tree_builder_context;
@@ -661,19 +675,19 @@
     PrePaintTreeWalkContext fragmentainer_context(
         parent_context, NeedsTreeBuilderContextUpdate(object, parent_context));
 
-    fragmentainer_context.current_fragmentainer.fragmentation_nesting_level++;
+    fragmentainer_context.current_container.fragmentation_nesting_level++;
     fragmentainer_context.is_parent_first_for_node =
         box_fragment->IsFirstForNode();
 
     // Always keep track of the current innermost fragmentainer we're handling,
     // as they may serve as containing blocks for OOF descendants.
-    fragmentainer_context.current_fragmentainer.fragment = box_fragment;
+    fragmentainer_context.current_container.fragment = box_fragment;
 
     // Set up |inner_fragmentainer_idx| lazily, as it's O(n) (n == number of
     // multicol container fragments).
     if (!inner_fragmentainer_idx)
       inner_fragmentainer_idx = PreviousInnerFragmentainerIndex(fragment);
-    fragmentainer_context.current_fragmentainer.fragmentainer_idx =
+    fragmentainer_context.current_container.fragmentainer_idx =
         *inner_fragmentainer_idx;
 
     PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext*
@@ -763,8 +777,7 @@
     // chain). Furthermore, culled inlines have no fragments, but they still
     // need to be visited, since the invalidation code marks them for pre-paint.
     const NGPhysicalBoxFragment* box_fragment = nullptr;
-    wtf_size_t fragmentainer_idx =
-        context.current_fragmentainer.fragmentainer_idx;
+    wtf_size_t fragmentainer_idx = context.current_container.fragmentainer_idx;
     const ContainingFragment* oof_containing_fragment_info = nullptr;
     PhysicalOffset paint_offset;
     const auto* child_box = DynamicTo<LayoutBox>(child);
@@ -884,7 +897,7 @@
             child_box->IsFixedPositioned()
                 ? &context.fixed_positioned_container
                 : &context.absolute_positioned_container;
-        if (context.current_fragmentainer.fragmentation_nesting_level !=
+        if (context.current_container.fragmentation_nesting_level !=
             oof_containing_fragment_info->fragmentation_nesting_level) {
           // Only walk OOFs once if they aren't contained within the current
           // fragmentation context.
@@ -916,11 +929,12 @@
     }
 
     if (box_fragment) {
-      NGPrePaintInfo pre_paint_info(*box_fragment, paint_offset,
-                                    fragmentainer_idx, is_first_for_node,
-                                    is_last_for_node, is_inside_fragment_child);
+      NGPrePaintInfo pre_paint_info(
+          *box_fragment, paint_offset, fragmentainer_idx, is_first_for_node,
+          is_last_for_node, is_inside_fragment_child,
+          context.current_container.IsInFragmentationContext());
       if (oof_containing_fragment_info &&
-          context.current_fragmentainer.fragmentation_nesting_level !=
+          context.current_container.fragmentation_nesting_level !=
               oof_containing_fragment_info->fragmentation_nesting_level) {
         // We're walking an out-of-flow positioned descendant that isn't in the
         // same fragmentation context as parent_object. Update the context, so
@@ -928,7 +942,7 @@
         // and all its descendants.
         PrePaintTreeWalkContext oof_context(
             context, NeedsTreeBuilderContextUpdate(*child, context));
-        oof_context.current_fragmentainer = *oof_containing_fragment_info;
+        oof_context.current_container = *oof_containing_fragment_info;
         Walk(*child, oof_context, &pre_paint_info);
       } else {
         Walk(*child, context, &pre_paint_info);
@@ -986,8 +1000,7 @@
 
   // Keep track of fragments that act as containers for OOFs, so that we can
   // search their children when looking for an OOF further down in the tree.
-  if (object.CanContainAbsolutePositionObjects())
-    UpdateContextForOOFContainer(object, context);
+  UpdateContextForOOFContainer(object, context, traversable_fragment);
 
   bool has_missable_children = false;
   const NGPhysicalBoxFragment* fragment = traversable_fragment;
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
index a620cd2..b1340dc 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
@@ -36,10 +36,15 @@
   static bool ObjectRequiresPrePaint(const LayoutObject&);
   static bool ObjectRequiresTreeBuilderContext(const LayoutObject&);
 
+  // Keeps information about the parent fragment that we need to search inside
+  // to find out-of-flow positioned descendants, and also which fragmentainer
+  // we're inside (which will serve as a fragment ID in FragmentData).
   struct ContainingFragment {
     STACK_ALLOCATED();
 
    public:
+    bool IsInFragmentationContext() const;
+
     const NGPhysicalBoxFragment* fragment = nullptr;
     wtf_size_t fragmentainer_idx = WTF::kNotFound;
     int fragmentation_nesting_level = 0;
@@ -59,7 +64,7 @@
     // Reset fragmentation when entering something that shouldn't be affected by
     // the current fragmentation context(s).
     void ResetFragmentation() {
-      current_fragmentainer = {};
+      current_container = {};
       absolute_positioned_container = {};
       fixed_positioned_container = {};
     }
@@ -89,7 +94,7 @@
     // fragmented at all).
     bool is_parent_first_for_node = true;
 
-    ContainingFragment current_fragmentainer;
+    ContainingFragment current_container;
     ContainingFragment absolute_positioned_container;
     ContainingFragment fixed_positioned_container;
   };
@@ -148,7 +153,8 @@
                                         const NGPrePaintInfo&);
 
   void UpdateContextForOOFContainer(const LayoutObject&,
-                                    PrePaintTreeWalkContext&);
+                                    PrePaintTreeWalkContext&,
+                                    const NGPhysicalBoxFragment*);
 
   void Walk(LocalFrameView&, const PrePaintTreeWalkContext& parent_context);
 
diff --git a/third_party/blink/renderer/core/scheduler_integration_tests/build.gni b/third_party/blink/renderer/core/scheduler_integration_tests/build.gni
new file mode 100644
index 0000000..67a8f3c
--- /dev/null
+++ b/third_party/blink/renderer/core/scheduler_integration_tests/build.gni
@@ -0,0 +1,11 @@
+# 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.
+
+blink_core_tests_scheduler_integration_tests = [
+  "frame_scheduler_test.cc",
+  "frame_throttling_test.cc",
+  "scheduler_affecting_features_test.cc",
+  "throttling_test.cc",
+  "virtual_time_test.cc",
+]
diff --git a/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc b/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc
index 2cb0ac35..59bcf294 100644
--- a/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc
+++ b/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc
@@ -3,7 +3,9 @@
 // found in LICENSE file.
 
 #include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/web/web_script_source.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -47,6 +49,8 @@
     }
     return result;
   }
+
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 TEST_F(SchedulingAffectingFeaturesTest, WebSocketIsTracked) {
@@ -146,26 +150,75 @@
 }
 
 TEST_F(SchedulingAffectingFeaturesTest, Plugins) {
-  class PluginCreatingWebFrameClient
-      : public frame_test_helpers::TestWebFrameClient {
-   public:
-    // WebLocalFrameClient overrides:
-    WebPlugin* CreatePlugin(const WebPluginParams& params) override {
-      return new FakeWebPlugin(params);
-    }
-  };
+  scoped_feature_list_.InitAndEnableFeature(
+      features::kBackForwardCacheEnabledForNonPluginEmbed);
+  {
+    SimRequest main_resource("https://example.com/", "text/html");
+    LoadURL("https://example.com/");
+    main_resource.Complete(
+        "<object type='application/x-webkit-test-plugin'></object>");
 
-  ScopedFakePluginRegistry fake_plugins;
-  SimRequest main_resource("https://example.com/", "text/html");
-  LoadURL("https://example.com/");
-  main_resource.Complete(
-      "<object type='application/x-webkit-test-plugin'></object>");
+    // |RunUntilIdle| is required as |Complete| doesn't wait for loading plugin.
+    base::RunLoop().RunUntilIdle();
 
-  base::RunLoop().RunUntilIdle();
+    EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
+                testing::UnorderedElementsAre(
+                    SchedulingPolicy::Feature::kContainsPlugins));
+  }
+  {
+    SimRequest main_resource("https://example.com/", "text/html");
+    LoadURL("https://example.com/");
+    main_resource.Complete(
+        "<embed type='application/x-webkit-test-plugin'></embed>");
 
-  EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
-              testing::UnorderedElementsAre(
-                  SchedulingPolicy::Feature::kContainsPlugins));
+    // |RunUntilIdle| is required as |Complete| doesn't wait for loading plugin.
+    base::RunLoop().RunUntilIdle();
+
+    EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
+                testing::UnorderedElementsAre(
+                    SchedulingPolicy::Feature::kContainsPlugins));
+  }
+}
+
+TEST_F(SchedulingAffectingFeaturesTest, NonPlugins) {
+  scoped_feature_list_.InitAndEnableFeature(
+      features::kBackForwardCacheEnabledForNonPluginEmbed);
+  {
+    SimRequest main_resource("https://example.com/", "text/html");
+    LoadURL("https://example.com/");
+    main_resource.Complete("<object type='text/html'></object>");
+
+    EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
+                testing::Not(testing::Contains(
+                    SchedulingPolicy::Feature::kContainsPlugins)));
+  }
+  {
+    SimRequest main_resource("https://example.com/", "text/html");
+    LoadURL("https://example.com/");
+    main_resource.Complete("<embed type='text/html'></embed>");
+
+    EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
+                testing::Not(testing::Contains(
+                    SchedulingPolicy::Feature::kContainsPlugins)));
+  }
+  {
+    SimRequest main_resource("https://example.com/", "text/html");
+    LoadURL("https://example.com/");
+    main_resource.Complete("<object type='image/png'></object>");
+
+    EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
+                testing::Not(testing::Contains(
+                    SchedulingPolicy::Feature::kContainsPlugins)));
+  }
+  {
+    SimRequest main_resource("https://example.com/", "text/html");
+    LoadURL("https://example.com/");
+    main_resource.Complete("<embed type='image/png'></embed>");
+
+    EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
+                testing::Not(testing::Contains(
+                    SchedulingPolicy::Feature::kContainsPlugins)));
+  }
 }
 
 TEST_F(SchedulingAffectingFeaturesTest, WebLocks) {
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc
index 1f59b6b..77f361a 100644
--- a/third_party/blink/renderer/core/testing/internals.cc
+++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -30,6 +30,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "base/process/process_handle.h"
 #include "cc/layers/picture_layer.h"
 #include "cc/trees/layer_tree_host.h"
@@ -3109,7 +3110,7 @@
 
   base::span<const uint8_t> span = serialized_value->GetWireData();
   DOMArrayBuffer* buffer = DOMArrayBuffer::CreateUninitializedOrNull(
-      SafeCast<uint32_t>(span.size()), sizeof(uint8_t));
+      base::checked_cast<uint32_t>(span.size()), sizeof(uint8_t));
   if (buffer)
     memcpy(buffer->Data(), span.data(), span.size());
   return buffer;
diff --git a/third_party/blink/renderer/core/web_test/BUILD.gn b/third_party/blink/renderer/core/web_test/BUILD.gn
index 0c9288d..f77f42e0 100644
--- a/third_party/blink/renderer/core/web_test/BUILD.gn
+++ b/third_party/blink/renderer/core/web_test/BUILD.gn
@@ -30,7 +30,7 @@
     # are not built, and some generated mojom headers are missing. As a
     # workaround, add this dep so that `web_test_renderer` has all of the
     # headers it needs.
-    "//content/web_test:web_test_common",
+    "//content/web_test:web_test_renderer_public_deps",
 
     "//third_party/blink/public:blink_headers",
     "//third_party/blink/public:test_headers",
diff --git a/third_party/blink/renderer/core/xml/parser/shared_buffer_reader.cc b/third_party/blink/renderer/core/xml/parser/shared_buffer_reader.cc
index cbe28221..4def93c 100644
--- a/third_party/blink/renderer/core/xml/parser/shared_buffer_reader.cc
+++ b/third_party/blink/renderer/core/xml/parser/shared_buffer_reader.cc
@@ -30,12 +30,13 @@
 
 #include "third_party/blink/renderer/core/xml/parser/shared_buffer_reader.h"
 
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-
 #include <algorithm>
 #include <cstring>
 
+#include "base/memory/scoped_refptr.h"
+#include "base/numerics/safe_conversions.h"
+#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
+
 namespace blink {
 
 SharedBufferReader::SharedBufferReader(scoped_refptr<const SharedBuffer> buffer)
@@ -48,7 +49,7 @@
     return 0;
 
   size_t bytes_copied = 0;
-  size_t len_to_copy = std::min(SafeCast<size_t>(asked_to_read),
+  size_t len_to_copy = std::min(base::checked_cast<size_t>(asked_to_read),
                                 buffer_->size() - current_offset_);
   for (auto it = buffer_->GetIteratorAt(current_offset_); it != buffer_->cend();
        ++it) {
@@ -61,7 +62,7 @@
   }
 
   current_offset_ += bytes_copied;
-  return SafeCast<int>(bytes_copied);
+  return base::checked_cast<int>(bytes_copied);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
index 544f400..424bcd90 100644
--- a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
+++ b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
@@ -29,6 +29,8 @@
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/xmlversion.h>
+
+#include "base/numerics/safe_conversions.h"
 #if defined(LIBXML_CATALOG_ENABLED)
 #include <libxml/catalog.h>
 #endif
@@ -1453,7 +1455,7 @@
   DCHECK_LE(entity_length_in_utf8, kSharedXhtmlEntityResultLength);
 
   xmlEntityPtr entity = SharedXHTMLEntity();
-  entity->length = SafeCast<int>(entity_length_in_utf8);
+  entity->length = base::checked_cast<int>(entity_length_in_utf8);
   entity->name = name;
   return entity;
 }
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/BUILD.gn b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/BUILD.gn
index 8fd4493..76541e0f 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/BUILD.gn
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "cros_accelerator_event.cc",
     "cros_accelerator_event.h",
+    "cros_screen.cc",
+    "cros_screen.h",
     "cros_window.cc",
     "cros_window.h",
     "cros_window_management.cc",
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.cc b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.cc
new file mode 100644
index 0000000..709a437
--- /dev/null
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.cc
@@ -0,0 +1,20 @@
+// 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 "third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.h"
+
+#include "third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h"
+
+namespace blink {
+
+CrosScreen::CrosScreen(CrosWindowManagement* manager,
+                       mojom::blink::CrosScreenInfoPtr screen)
+    : window_management_(manager), screen_(std::move(screen)) {}
+
+void CrosScreen::Trace(Visitor* visitor) const {
+  visitor->Trace(window_management_);
+  ScriptWrappable::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.h b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.h
new file mode 100644
index 0000000..77407ff
--- /dev/null
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.h
@@ -0,0 +1,35 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_SYSTEM_EXTENSIONS_WINDOW_MANAGEMENT_CROS_SCREEN_H_
+#define THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_SYSTEM_EXTENSIONS_WINDOW_MANAGEMENT_CROS_SCREEN_H_
+
+#include <cstdint>
+#include "third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom-blink.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+
+namespace blink {
+class CrosWindowManagement;
+
+class CrosScreen : public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  CrosScreen(CrosWindowManagement* manager,
+             mojom::blink::CrosScreenInfoPtr screen);
+
+  void Trace(Visitor*) const override;
+
+  int32_t width() { return screen_->width; }
+
+ private:
+  Member<CrosWindowManagement> window_management_;
+
+  mojom::blink::CrosScreenInfoPtr screen_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_EXTENSIONS_CHROMEOS_SYSTEM_EXTENSIONS_WINDOW_MANAGEMENT_CROS_SCREEN_H_
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.idl b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.idl
new file mode 100644
index 0000000..cd04dd5
--- /dev/null
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.idl
@@ -0,0 +1,10 @@
+// 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.
+
+// The CrosScreen interface represents a screen and is returned in array using
+// chromeos.windowManagement.getScreens().
+interface CrosScreen {
+  // Returns the width of the screen.
+  readonly attribute long width;
+};
\ No newline at end of file
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc
index 522dc7f..2467a1a 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/extensions/chromeos/event_target_chromeos.h"
+#include "third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_screen.h"
 #include "third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window.h"
 
 namespace blink {
@@ -48,6 +49,8 @@
 void CrosWindowManagement::Trace(Visitor* visitor) const {
   visitor->Trace(cros_window_management_);
   visitor->Trace(receiver_);
+  visitor->Trace(windows_);
+  visitor->Trace(screens_);
   Supplement<ExecutionContext>::Trace(visitor);
   EventTargetWithInlineData::Trace(visitor);
   ExecutionContextClient::Trace(visitor);
@@ -95,10 +98,41 @@
   HeapVector<Member<CrosWindow>> results;
   results.ReserveInitialCapacity(windows.size());
   for (auto& w : windows) {
-    auto* result = MakeGarbageCollected<CrosWindow>(this, std::move(w));
-    results.push_back(result);
+    results.push_back(MakeGarbageCollected<CrosWindow>(this, std::move(w)));
   }
-  resolver->Resolve(results);
+
+  windows_.swap(results);
+
+  resolver->Resolve(windows_);
+}
+
+const HeapVector<Member<CrosWindow>>& CrosWindowManagement::windows() {
+  return windows_;
+}
+
+ScriptPromise CrosWindowManagement::getScreens(ScriptState* script_state) {
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  auto* window_management = GetCrosWindowManagementOrNull();
+  if (window_management) {
+    window_management->GetAllScreens(
+        WTF::Bind(&CrosWindowManagement::ScreensCallback, WrapPersistent(this),
+                  WrapPersistent(resolver)));
+  }
+  return resolver->Promise();
+}
+
+void CrosWindowManagement::ScreensCallback(
+    ScriptPromiseResolver* resolver,
+    WTF::Vector<mojom::blink::CrosScreenInfoPtr> screens) {
+  HeapVector<Member<CrosScreen>> results;
+  results.ReserveInitialCapacity(screens.size());
+  for (auto& s : screens) {
+    results.push_back(MakeGarbageCollected<CrosScreen>(this, std::move(s)));
+  }
+
+  screens_.swap(results);
+
+  resolver->Resolve(std::move(screens_));
 }
 
 void CrosWindowManagement::DispatchStartEvent() {
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h
index 2910fb4e..d89e2499 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.h
@@ -15,6 +15,8 @@
 #include "third_party/blink/renderer/platform/supplementable.h"
 
 namespace blink {
+class CrosWindow;
+class CrosScreen;
 class ScriptPromiseResolver;
 
 class CrosWindowManagement
@@ -50,9 +52,15 @@
   void WindowsCallback(ScriptPromiseResolver* resolver,
                        WTF::Vector<mojom::blink::CrosWindowInfoPtr> windows);
 
+  ScriptPromise getScreens(ScriptState* script_state);
+  void ScreensCallback(ScriptPromiseResolver* resolver,
+                       WTF::Vector<mojom::blink::CrosScreenInfoPtr> screens);
+
   // mojom::blink::CrosWindowManagementObserver
   void DispatchStartEvent() override;
 
+  const HeapVector<Member<CrosWindow>>& windows();
+
  private:
   void BindWindowManagerStartObserverImpl(
       mojo::PendingReceiver<mojom::blink::CrosWindowManagementStartObserver>
@@ -62,6 +70,10 @@
   HeapMojoReceiver<mojom::blink::CrosWindowManagementStartObserver,
                    CrosWindowManagement>
       receiver_;
+
+  HeapVector<Member<CrosWindow>> windows_;
+
+  HeapVector<Member<CrosScreen>> screens_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.idl b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.idl
index 74e32e7..1d453d6f 100644
--- a/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.idl
+++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/window_management/cros_window_management.idl
@@ -3,5 +3,11 @@
 // found in the LICENSE file.
 
 interface CrosWindowManagement : EventTarget {
-  [CallWith=ScriptState] Promise<sequence<CrosWindow>> getWindows();
+  [CallWith=ScriptState] Promise<FrozenArray<CrosWindow>> getWindows();
+
+  // Returns the list of screens that are currently available.
+  [CallWith=ScriptState] Promise<FrozenArray<CrosScreen>> getScreens();
+
+  // Cached property of windows visible to the window manager.
+  readonly attribute FrozenArray<CrosWindow> windows;
 };
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 40852ac7..724185c 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -668,6 +668,7 @@
     "//third_party/blink/renderer/modules/peerconnection:test_support",
     "//third_party/blink/renderer/modules/storage:unit_tests",
     "//third_party/blink/renderer/modules/webcodecs:unit_tests",
+    "//third_party/blink/renderer/modules/webgpu:unit_tests",
     "//third_party/blink/renderer/modules/webtransport:unit_tests",
     "//third_party/blink/renderer/platform",
     "//third_party/blink/renderer/platform:test_support",
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index c6b10bcf..b111e0c 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -35,6 +35,7 @@
 #include <queue>
 
 #include "base/auto_reset.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/input/web_keyboard_event.h"
@@ -2470,7 +2471,7 @@
                                        kUnpremul_SkAlphaType);
   size_t row_bytes = info.minRowBytes();
   Vector<char> pixel_storage(
-      SafeCast<wtf_size_t>(info.computeByteSize(row_bytes)));
+      base::checked_cast<wtf_size_t>(info.computeByteSize(row_bytes)));
   SkPixmap pixmap(info, pixel_storage.data(), row_bytes);
   if (!SkImage::MakeFromBitmap(bitmap)->readPixels(pixmap, 0, 0))
     return String();
diff --git a/third_party/blink/renderer/modules/ad_auction/auction_ad_interest_group.idl b/third_party/blink/renderer/modules/ad_auction/auction_ad_interest_group.idl
index 3246e79..0ca7fe4 100644
--- a/third_party/blink/renderer/modules/ad_auction/auction_ad_interest_group.idl
+++ b/third_party/blink/renderer/modules/ad_auction/auction_ad_interest_group.idl
@@ -5,10 +5,17 @@
 // Name, origin owner, and metadata for ad interest groups.
 // https://github.com/WICG/turtledove/blob/main/FLEDGE.md#11-joining-interest-groups
 
+enum WorkletExecutionMode {
+  "compatibility",
+  // "groupByOrigin",
+  // "frozenContext",
+};
+
 dictionary AuctionAdInterestGroup {
   required USVString owner;
   required USVString name;
   double priority;
+  WorkletExecutionMode executionMode;
   USVString biddingLogicUrl;
   USVString biddingWasmHelperUrl;
   USVString dailyUpdateUrl;
diff --git a/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc b/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
index 6e64ec09..df09d295 100644
--- a/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
+++ b/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
@@ -177,6 +177,27 @@
   return true;
 }
 
+bool CopyExecutionModeFromIdlToMojo(const ExecutionContext& execution_context,
+                                    ExceptionState& exception_state,
+                                    const AuctionAdInterestGroup& input,
+                                    mojom::blink::InterestGroup& output) {
+  if (!input.hasExecutionMode())
+    return true;
+
+  switch (input.executionMode().AsEnum()) {
+    case V8WorkletExecutionMode::Enum::kCompatibility:
+      output.execution_mode =
+          mojom::blink::InterestGroup::ExecutionMode::kCompatibilityMode;
+      break;
+    default:
+      exception_state.ThrowTypeError(ErrorInvalidInterestGroup(
+          input, "executionMode", input.executionMode().AsString(),
+          "is not a supported execution mode."));
+      return false;
+  }
+  return true;
+}
+
 bool CopyBiddingLogicUrlFromIdlToMojo(const ExecutionContext& context,
                                       ExceptionState& exception_state,
                                       const AuctionAdInterestGroup& input,
@@ -942,6 +963,10 @@
     return ScriptPromise();
   mojo_group->name = group->name();
   mojo_group->priority = (group->hasPriority()) ? group->priority() : 0.0;
+  if (!CopyExecutionModeFromIdlToMojo(*context, exception_state, *group,
+                                      *mojo_group)) {
+    return ScriptPromise();
+  }
   if (!CopyBiddingLogicUrlFromIdlToMojo(*context, exception_state, *group,
                                         *mojo_group)) {
     return ScriptPromise();
diff --git a/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.cc b/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.cc
index 33fecf2d..76918a3 100644
--- a/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.cc
+++ b/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group.cc
@@ -46,6 +46,7 @@
   size += group.owner->ToString().length();
   size += group.name.length();
   size += sizeof(group.priority);
+  size += sizeof(group.execution_mode);
 
   if (group.bidding_url)
     size += group.bidding_url->GetString().length();
@@ -102,6 +103,17 @@
     return false;
   }
 
+  // This check is here to keep it in sync with InterestGroup::IsValid(), but
+  // checks in navigator_auction.cc should ensure the execution mode is always
+  // valid.
+  if (group.execution_mode !=
+      mojom::blink::InterestGroup::ExecutionMode::kCompatibilityMode) {
+    error_field_name = "execution_mode";
+    error_field_value = String::Number(static_cast<int>(group.execution_mode));
+    error = "execution mode is not valid.";
+    return false;
+  }
+
   if (group.bidding_url) {
     if (!IsUrlAllowed(*group.bidding_url, group)) {
       error_field_name = "biddingUrl";
diff --git a/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group_test.cc b/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group_test.cc
index 5fc78c4..3113fc7 100644
--- a/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group_test.cc
+++ b/third_party/blink/renderer/modules/ad_auction/validate_blink_interest_group_test.cc
@@ -496,7 +496,7 @@
 TEST_F(ValidateBlinkInterestGroupTest, TooLarge) {
   mojom::blink::InterestGroupPtr blink_interest_group =
       CreateMinimalInterestGroup();
-  std::string long_string(51173, 'n');
+  std::string long_string(51169, 'n');
   blink_interest_group->name = String(long_string);
   ExpectInterestGroupIsNotValid(
       blink_interest_group, "size" /* expected_error_field_name */,
@@ -504,7 +504,7 @@
       "interest groups must be less than 51200 bytes" /* expected_error */);
 
   // Almost too big should still work.
-  long_string = std::string(51200 - 28, 'n');
+  long_string = std::string(51200 - 32, 'n');
   blink_interest_group->name = String(long_string);
 
   ExpectInterestGroupIsValid(blink_interest_group);
@@ -513,7 +513,7 @@
 TEST_F(ValidateBlinkInterestGroupTest, TooLargeAds) {
   mojom::blink::InterestGroupPtr blink_interest_group =
       CreateMinimalInterestGroup();
-  blink_interest_group->name = "padding to 51200.......";
+  blink_interest_group->name = "padding to 51200...";
   blink_interest_group->ad_components.emplace();
   for (int i = 0; i < 682; ++i) {
     // Each ad component is 75 bytes.
@@ -557,4 +557,23 @@
   }
 }
 
+TEST_F(ValidateBlinkInterestGroupTest, InvalidExecutionMode) {
+  struct {
+    blink::InterestGroup::ExecutionMode execution_mode;
+    const char* execution_mode_text;
+  } test_cases[] = {
+      {blink::InterestGroup::ExecutionMode::kGroupedByOriginMode, "1"},
+      {blink::InterestGroup::ExecutionMode::kFrozenContext, "2"},
+  };
+  for (const auto& test_case : test_cases) {
+    mojom::blink::InterestGroupPtr blink_interest_group =
+        CreateMinimalInterestGroup();
+    blink_interest_group->execution_mode = test_case.execution_mode;
+    ExpectInterestGroupIsNotValid(
+        blink_interest_group, "execution_mode" /* expected_error_field_name */,
+        test_case.execution_mode_text, /*expected_error_field_value */
+        "execution mode is not valid." /* expected_error */);
+  }
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc b/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc
index f797531..c4af75c 100644
--- a/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc
+++ b/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc
@@ -160,7 +160,8 @@
 
 void PushableMediaStreamVideoSource::StartSourceImpl(
     VideoCaptureDeliverFrameCB frame_callback,
-    EncodedVideoFrameCB encoded_frame_callback) {
+    EncodedVideoFrameCB encoded_frame_callback,
+    VideoCaptureCropVersionCB crop_version_callback) {
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
   DCHECK(frame_callback);
   broker_->OnSourceStarted(std::move(frame_callback));
diff --git a/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h b/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h
index 477c893a..57b4df9 100644
--- a/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h
+++ b/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h
@@ -95,8 +95,10 @@
   scoped_refptr<Broker> GetBroker() const { return broker_; }
 
   // MediaStreamVideoSource
-  void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback,
-                       EncodedVideoFrameCB encoded_frame_callback) override;
+  void StartSourceImpl(
+      VideoCaptureDeliverFrameCB frame_callback,
+      EncodedVideoFrameCB encoded_frame_callback,
+      VideoCaptureCropVersionCB crop_version_callback) override;
   void StopSourceImpl() override;
   base::WeakPtr<MediaStreamVideoSource> GetWeakPtr() const override;
   void SetCanDiscardAlpha(bool can_discard_alpha) override;
diff --git a/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc b/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
index e126fdc4..56be717 100644
--- a/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
+++ b/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
@@ -267,7 +267,8 @@
           request->credentials_mode, request->cache_mode,
           request->redirect_mode, request->integrity, request->priority,
           request->fetch_window_id, request->keepalive, request->is_reload,
-          request->is_history_navigation, request->devtools_stack_id);
+          request->is_history_navigation, request->devtools_stack_id,
+          request->trust_token_params.Clone());
       cache_remote_->Match(
           std::move(request), mojom::blink::CacheQueryOptions::New(),
           /*in_related_fetch_event=*/false, /*in_range_fetch_event=*/false,
diff --git a/third_party/blink/renderer/modules/crypto/crypto_key.cc b/third_party/blink/renderer/modules/crypto/crypto_key.cc
index 1583672..bee789d9 100644
--- a/third_party/blink/renderer/modules/crypto/crypto_key.cc
+++ b/third_party/blink/renderer/modules/crypto/crypto_key.cc
@@ -30,6 +30,7 @@
 
 #include "third_party/blink/renderer/modules/crypto/crypto_key.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
 #include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
 #include "third_party/blink/public/platform/web_string.h"
@@ -38,7 +39,6 @@
 #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/crypto_result.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -122,9 +122,10 @@
 
   void SetUint8Array(const char* property_name,
                      const WebVector<unsigned char>& vector) override {
-    builder_.Add(property_name,
-                 DOMUint8Array::Create(vector.data(),
-                                       SafeCast<wtf_size_t>(vector.size())));
+    builder_.Add(
+        property_name,
+        DOMUint8Array::Create(vector.data(),
+                              base::checked_cast<wtf_size_t>(vector.size())));
   }
 
  private:
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
index a194c33..32d8dd3 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
@@ -28,6 +28,7 @@
 #include <cmath>
 #include <limits>
 
+#include "base/numerics/safe_conversions.h"
 #include "media/base/content_decryption_module.h"
 #include "media/base/eme_constants.h"
 #include "third_party/blink/public/platform/task_type.h"
@@ -58,7 +59,6 @@
 #include "third_party/blink/renderer/platform/network/mime/content_type.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/timer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
 
 #define MEDIA_KEY_SESSION_LOG_LEVEL 3
@@ -959,8 +959,9 @@
       init->setMessageType("individualization-request");
       break;
   }
-  init->setMessage(DOMArrayBuffer::Create(static_cast<const void*>(message),
-                                          SafeCast<uint32_t>(message_length)));
+  init->setMessage(
+      DOMArrayBuffer::Create(static_cast<const void*>(message),
+                             base::checked_cast<uint32_t>(message_length)));
 
   MediaKeyMessageEvent* event =
       MediaKeyMessageEvent::Create(event_type_names::kMessage, init);
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc
index 747ebbf2..fe10c86 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
+#include "base/numerics/safe_conversions.h"
 #include "media/base/eme_constants.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
@@ -26,7 +27,6 @@
 #include "third_party/blink/renderer/modules/encryptedmedia/media_keys_controller.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/timer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -81,7 +81,7 @@
 // NavigatorRequestMediaKeySystemAccess.
 Vector<String> ConvertInitDataTypes(
     const WebVector<media::EmeInitDataType>& init_data_types) {
-  Vector<String> result(SafeCast<wtf_size_t>(init_data_types.size()));
+  Vector<String> result(base::checked_cast<wtf_size_t>(init_data_types.size()));
   for (wtf_size_t i = 0; i < result.size(); i++)
     result[i] =
         EncryptedMediaUtils::ConvertFromInitDataType(init_data_types[i]);
@@ -91,7 +91,7 @@
 HeapVector<Member<MediaKeySystemMediaCapability>> ConvertCapabilities(
     const WebVector<WebMediaKeySystemMediaCapability>& capabilities) {
   HeapVector<Member<MediaKeySystemMediaCapability>> result(
-      SafeCast<wtf_size_t>(capabilities.size()));
+      base::checked_cast<wtf_size_t>(capabilities.size()));
   for (wtf_size_t i = 0; i < result.size(); i++) {
     MediaKeySystemMediaCapability* capability =
         MediaKeySystemMediaCapability::Create();
@@ -129,7 +129,7 @@
 
 Vector<String> ConvertSessionTypes(
     const WebVector<WebEncryptedMediaSessionType>& session_types) {
-  Vector<String> result(SafeCast<wtf_size_t>(session_types.size()));
+  Vector<String> result(base::checked_cast<wtf_size_t>(session_types.size()));
   for (wtf_size_t i = 0; i < result.size(); i++)
     result[i] = EncryptedMediaUtils::ConvertFromSessionType(session_types[i]);
   return result;
diff --git a/third_party/blink/renderer/modules/font_access/font_metadata.cc b/third_party/blink/renderer/modules/font_access/font_metadata.cc
index 3708a51..97f8fc34 100644
--- a/third_party/blink/renderer/modules/font_access/font_metadata.cc
+++ b/third_party/blink/renderer/modules/font_access/font_metadata.cc
@@ -6,6 +6,7 @@
 
 #include "base/big_endian.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/sys_byteorder.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -112,7 +113,8 @@
   }
 
   base::UmaHistogramBoolean("Blink.Fonts.DataAccess.StreamCreation", true);
-  wtf_size_t font_byte_size = SafeCast<wtf_size_t>(stream->getLength());
+  wtf_size_t font_byte_size =
+      base::checked_cast<wtf_size_t>(stream->getLength());
 
   // TODO(https://crbug.com/1069900): This copies the font bytes. Lazy load and
   // stream the data instead.
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.cc b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.cc
index e0e6019..34404e08 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.cc
@@ -7,13 +7,13 @@
 #include <memory>
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_value.h"
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
@@ -151,7 +151,7 @@
   wire_data_buffer_.push_back(kVersionTag);
   wire_data_buffer_.push_back(kRequiresProcessingSSVPseudoVersion);
   wire_data_buffer_.push_back(kReplaceWithBlob);
-  IDBValueWrapper::WriteVarInt(SafeCast<unsigned>(wire_data_size),
+  IDBValueWrapper::WriteVarInt(base::checked_cast<unsigned>(wire_data_size),
                                wire_data_buffer_);
   IDBValueWrapper::WriteVarInt(serialized_value_->BlobDataHandles().size(),
                                wire_data_buffer_);
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
index 0133cb0..4d0f667 100644
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
+++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "mojo/public/cpp/base/string16_mojom_traits.h"
 #include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -14,7 +15,6 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
 #include "third_party/blink/renderer/platform/file_metadata.h"
 #include "third_party/blink/renderer/platform/mojo/string16_mojom_traits.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 using blink::mojom::IDBCursorDirection;
@@ -39,7 +39,7 @@
       object_stores;
   data.GetObjectStoresDataView(&object_stores);
   out->object_stores.ReserveCapacityForSize(
-      SafeCast<wtf_size_t>(object_stores.size()));
+      base::checked_cast<wtf_size_t>(object_stores.size()));
   for (size_t i = 0; i < object_stores.size(); ++i) {
     const int64_t key = object_stores.keys()[i];
     scoped_refptr<blink::IDBObjectStoreMetadata> object_store;
@@ -281,7 +281,8 @@
     case blink::mojom::IDBKeyPathType::Array: {
       const auto& array = key_path.Array();
       Vector<String> result;
-      result.ReserveInitialCapacity(SafeCast<wtf_size_t>(array.size()));
+      result.ReserveInitialCapacity(
+          base::checked_cast<wtf_size_t>(array.size()));
       for (const auto& item : array)
         result.push_back(item);
       return blink::mojom::blink::IDBKeyPathData::NewStringArray(
@@ -345,7 +346,8 @@
   value->max_index_id = data.max_index_id();
   MapDataView<int64_t, blink::mojom::IDBIndexMetadataDataView> indexes;
   data.GetIndexesDataView(&indexes);
-  value->indexes.ReserveCapacityForSize(SafeCast<wtf_size_t>(indexes.size()));
+  value->indexes.ReserveCapacityForSize(
+      base::checked_cast<wtf_size_t>(indexes.size()));
   for (size_t i = 0; i < indexes.size(); ++i) {
     const int64_t key = indexes.keys()[i];
     scoped_refptr<blink::IDBIndexMetadata> index;
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
index 7fa9a55..0f4f93a 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
@@ -59,6 +59,7 @@
   }
   void StartCapture(const media::VideoCaptureParams& params,
                     const blink::VideoCaptureDeliverFrameCB& frame_callback,
+                    const VideoCaptureCropVersionCB& crop_version_callback,
                     const RunningCallback& running_callback) override {
     DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
     if (canvas_handler_.get()) {
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
index fc28f85..d0e61e7 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
@@ -199,6 +199,7 @@
       params,
       base::BindRepeating(&CanvasCaptureHandlerTest::OnDeliverFrame,
                           base::Unretained(this)),
+      /*crop_version_callback=*/base::DoNothing(),
       base::BindRepeating(&CanvasCaptureHandlerTest::OnRunning,
                           base::Unretained(this)));
   copier_->Convert(GenerateTestImage(testing::get<0>(GetParam()),
@@ -230,6 +231,7 @@
       params,
       base::BindRepeating(&CanvasCaptureHandlerTest::OnVerifyDeliveredFrame,
                           base::Unretained(this), opaque_frame, width, height),
+      /*crop_version_callback=*/base::DoNothing(),
       base::BindRepeating(&CanvasCaptureHandlerTest::OnRunning,
                           base::Unretained(this)));
   copier_->Convert(GenerateTestImage(opaque_frame, width, height),
@@ -258,6 +260,7 @@
       base::BindRepeating(&CanvasCaptureHandlerTest::OnVerifyDeliveredFrame,
                           base::Unretained(this), /*opaque_frame=*/true, width,
                           height),
+      /*crop_version_callback=*/base::DoNothing(),
       base::BindRepeating(&CanvasCaptureHandlerTest::OnRunning,
                           base::Unretained(this)));
   copier_->Convert(GenerateTestImage(/*opaque=*/false, width, height),
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
index b418bdb..01c75034 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
@@ -73,6 +73,7 @@
 void HtmlVideoElementCapturerSource::StartCapture(
     const media::VideoCaptureParams& params,
     const VideoCaptureDeliverFrameCB& new_frame_callback,
+    const VideoCaptureCropVersionCB& crop_version_callback,
     const RunningCallback& running_callback) {
   DVLOG(2) << __func__ << " requested "
            << media::VideoCaptureFormat::ToString(params.requested_format);
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h
index f35835b..e0454c4 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h
@@ -49,6 +49,7 @@
   media::VideoCaptureFormats GetPreferredFormats() override;
   void StartCapture(const media::VideoCaptureParams& params,
                     const VideoCaptureDeliverFrameCB& new_frame_callback,
+                    const VideoCaptureCropVersionCB& crop_version_callback,
                     const RunningCallback& running_callback) override;
   void StopCapture() override;
 
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
index 555ff3a..9e06b826 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
@@ -169,6 +169,7 @@
       media::VideoCaptureParams(),
       WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
                          base::Unretained(this)),
+      base::DoNothing(),
       WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnRunning,
                          base::Unretained(this)));
 }
@@ -205,6 +206,7 @@
       params,
       WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
                          base::Unretained(this)),
+      base::DoNothing(),
       WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnRunning,
                          base::Unretained(this)));
 
@@ -246,6 +248,7 @@
       params,
       WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
                          base::Unretained(this)),
+      base::DoNothing(),
       WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnRunning,
                          base::Unretained(this)));
   html_video_capturer_->StopCapture();
@@ -277,6 +280,7 @@
         params,
         WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
                            base::Unretained(this)),
+        base::DoNothing(),
         WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnRunning,
                            base::Unretained(this)));
     run_loop.Run();
@@ -338,6 +342,7 @@
         params,
         WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
                            base::Unretained(this)),
+        base::DoNothing(),
         WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnRunning,
                            base::Unretained(this)));
     run_loop.Run();
@@ -380,6 +385,7 @@
       params,
       WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
                          base::Unretained(this)),
+      base::DoNothing(),
       WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnRunning,
                          base::Unretained(this)));
 
diff --git a/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc b/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc
index 4530215..4c5b802 100644
--- a/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "base/system/sys_info.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
@@ -143,7 +144,7 @@
         v_plane_offset_ = media::VideoFrame::PlaneSize(
                               frame->format(), VideoFrame::kUPlane, frame_size)
                               .GetArea();
-        alpha_dummy_planes_.resize(SafeCast<wtf_size_t>(
+        alpha_dummy_planes_.resize(base::checked_cast<wtf_size_t>(
             v_plane_offset_ + media::VideoFrame::PlaneSize(frame->format(),
                                                            VideoFrame::kVPlane,
                                                            frame_size)
@@ -168,10 +169,10 @@
                frame->data(VideoFrame::kAPlane),
                frame->visible_data(VideoFrame::kAPlane),
                frame->stride(VideoFrame::kAPlane), alpha_dummy_planes_.data(),
-               SafeCast<int>(u_plane_stride_),
+               base::checked_cast<int>(u_plane_stride_),
                alpha_dummy_planes_.data() + v_plane_offset_,
-               SafeCast<int>(v_plane_stride_), duration, keyframe, alpha_data,
-               &alpha_keyframe, VPX_IMG_FMT_I420);
+               base::checked_cast<int>(v_plane_stride_), duration, keyframe,
+               alpha_data, &alpha_keyframe, VPX_IMG_FMT_I420);
       DCHECK_EQ(keyframe, alpha_keyframe);
       break;
     }
diff --git a/third_party/blink/renderer/modules/mediasource/BUILD.gn b/third_party/blink/renderer/modules/mediasource/BUILD.gn
index 22bdc74..1cf60cf 100644
--- a/third_party/blink/renderer/modules/mediasource/BUILD.gn
+++ b/third_party/blink/renderer/modules/mediasource/BUILD.gn
@@ -10,6 +10,8 @@
     "attachment_creation_pass_key_provider.h",
     "cross_thread_media_source_attachment.cc",
     "cross_thread_media_source_attachment.h",
+    "handle_attachment_provider.cc",
+    "handle_attachment_provider.h",
     "html_video_element_media_source.cc",
     "html_video_element_media_source.h",
     "media_source.cc",
diff --git a/third_party/blink/renderer/modules/mediasource/handle_attachment_provider.cc b/third_party/blink/renderer/modules/mediasource/handle_attachment_provider.cc
new file mode 100644
index 0000000..9cfcccb
--- /dev/null
+++ b/third_party/blink/renderer/modules/mediasource/handle_attachment_provider.cc
@@ -0,0 +1,34 @@
+// 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 "third_party/blink/renderer/modules/mediasource/handle_attachment_provider.h"
+
+#include "base/logging.h"
+#include "third_party/blink/renderer/core/html/media/media_source_attachment.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
+
+namespace blink {
+
+HandleAttachmentProvider::HandleAttachmentProvider(
+    scoped_refptr<MediaSourceAttachment> attachment)
+    : attachment_(std::move(attachment)) {
+  DCHECK(attachment_);
+  DVLOG(1) << __func__ << " this=" << this << ", attachment_=" << attachment_;
+}
+
+HandleAttachmentProvider::~HandleAttachmentProvider() {
+  DVLOG(1) << __func__ << " this=" << this;
+}
+
+scoped_refptr<MediaSourceAttachment>
+HandleAttachmentProvider::TakeAttachment() {
+  MutexLocker lock(attachment_lock_);
+
+  DVLOG(1) << __func__ << " this=" << this << ", attachment_=" << attachment_;
+  return std::move(attachment_);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/mediasource/handle_attachment_provider.h b/third_party/blink/renderer/modules/mediasource/handle_attachment_provider.h
new file mode 100644
index 0000000..f82dd78
--- /dev/null
+++ b/third_party/blink/renderer/modules/mediasource/handle_attachment_provider.h
@@ -0,0 +1,52 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_HANDLE_ATTACHMENT_PROVIDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_HANDLE_ATTACHMENT_PROVIDER_H_
+
+#include "base/thread_annotations.h"
+#include "third_party/blink/renderer/core/html/media/media_source_attachment.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
+
+namespace blink {
+
+// Enables enforcement that a handle instance, originally retrieved from a
+// MediaSource instance via MediaSource::getHandle(), and any new clones of it
+// that may be produced during postMessage serialization of it (which can
+// surprisingly cause broadcast semantics) all drop their hard reference to the
+// underlying MediaSourceAttachment once one of those clones is used to
+// start attaching to an HTMLMediaElement. This prevents leakage of the attached
+// media element and MSE collection of objects in multiple GC heaps, as the
+// refcounted attachment object has persistent references to the element and the
+// mediasource. Once attached, only the media element and the mediasource should
+// have references to the attachment object, and when they close the attachment
+// and drop their references, there should be no other references remaining,
+// enabling GC. This object serves as a provider of either a never-yet attached
+// CrossThreadMediaSourceAttachment for a handle instance (and its potential
+// descendants due to serialization), or a nullptr once that attachment was
+// started. Locking is used to prevent read/write collision for this scenario.
+class HandleAttachmentProvider final
+    : public WTF::ThreadSafeRefCounted<HandleAttachmentProvider> {
+ public:
+  explicit HandleAttachmentProvider(
+      scoped_refptr<MediaSourceAttachment> attachment);
+  HandleAttachmentProvider(const HandleAttachmentProvider&) = delete;
+  HandleAttachmentProvider& operator=(const HandleAttachmentProvider&) = delete;
+  ~HandleAttachmentProvider();
+
+  // Returns |attachment_| and drops our reference to it. Will return nullptr if
+  // TakeAttachment() has already occurred.
+  scoped_refptr<MediaSourceAttachment> TakeAttachment()
+      LOCKS_EXCLUDED(attachment_lock_);
+
+ private:
+  Mutex attachment_lock_;
+  scoped_refptr<MediaSourceAttachment> attachment_ GUARDED_BY(attachment_lock_);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_HANDLE_ATTACHMENT_PROVIDER_H_
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.cc b/third_party/blink/renderer/modules/mediasource/media_source.cc
index 8924ad712..8fe5bc6 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.cc
+++ b/third_party/blink/renderer/modules/mediasource/media_source.cc
@@ -34,6 +34,7 @@
 #include "third_party/blink/renderer/core/html/track/audio_track_list.h"
 #include "third_party/blink/renderer/core/html/track/video_track_list.h"
 #include "third_party/blink/renderer/modules/mediasource/cross_thread_media_source_attachment.h"
+#include "third_party/blink/renderer/modules/mediasource/handle_attachment_provider.h"
 #include "third_party/blink/renderer/modules/mediasource/media_source_handle_impl.h"
 #include "third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.h"
 #include "third_party/blink/renderer/modules/mediasource/same_thread_media_source_tracer.h"
@@ -1258,6 +1259,8 @@
   scoped_refptr<CrossThreadMediaSourceAttachment> attachment =
       base::MakeRefCounted<CrossThreadMediaSourceAttachment>(
           this, AttachmentCreationPassKeyProvider::GetPassKey());
+  scoped_refptr<HandleAttachmentProvider> attachment_provider =
+      base::MakeRefCounted<HandleAttachmentProvider>(std::move(attachment));
   handle_already_retrieved_ = true;
 
   // Create, but don't "register" an internal blob URL with the security origin
@@ -1268,7 +1271,7 @@
   String internal_blob_url = BlobURL::CreatePublicURL(origin).GetString();
   DCHECK(!internal_blob_url.IsEmpty());
   return MakeGarbageCollected<MediaSourceHandleImpl>(
-      std::move(attachment), std::move(internal_blob_url));
+      std::move(attachment_provider), std::move(internal_blob_url));
 }
 
 bool MediaSource::IsOpen() const {
diff --git a/third_party/blink/renderer/modules/mediasource/media_source_handle_attachment.h b/third_party/blink/renderer/modules/mediasource/media_source_handle_attachment.h
index a61d1d9a..43c4db87 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source_handle_attachment.h
+++ b/third_party/blink/renderer/modules/mediasource/media_source_handle_attachment.h
@@ -7,7 +7,7 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
-#include "third_party/blink/renderer/core/html/media/media_source_attachment.h"
+#include "third_party/blink/renderer/modules/mediasource/handle_attachment_provider.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 
 namespace blink {
@@ -18,7 +18,7 @@
  public:
   // Internals of a MediaSourceHandle that are included in serialization.
   struct HandleInternals {
-    scoped_refptr<MediaSourceAttachment> attachment;
+    scoped_refptr<HandleAttachmentProvider> attachment_provider;
     String internal_blob_url;
   };
 
diff --git a/third_party/blink/renderer/modules/mediasource/media_source_handle_impl.cc b/third_party/blink/renderer/modules/mediasource/media_source_handle_impl.cc
index 5f83ec6..8858691 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source_handle_impl.cc
+++ b/third_party/blink/renderer/modules/mediasource/media_source_handle_impl.cc
@@ -6,19 +6,22 @@
 
 #include "base/logging.h"
 #include "third_party/blink/renderer/core/html/media/media_source_attachment.h"
+#include "third_party/blink/renderer/modules/mediasource/handle_attachment_provider.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
 
 MediaSourceHandleImpl::MediaSourceHandleImpl(
-    scoped_refptr<MediaSourceAttachment> attachment,
+    scoped_refptr<HandleAttachmentProvider> attachment_provider,
     String internal_blob_url)
-    : attachment_(attachment), internal_blob_url_(internal_blob_url) {
-  DCHECK(attachment_);
+    : attachment_provider_(std::move(attachment_provider)),
+      internal_blob_url_(internal_blob_url) {
+  DCHECK(attachment_provider_);
   DCHECK(!internal_blob_url.IsEmpty());
 
-  DVLOG(1) << __func__ << " this=" << this << ", attachment_=" << attachment_
+  DVLOG(1) << __func__ << " this=" << this
+           << ", attachment_provider_=" << attachment_provider_
            << ", internal_blob_url_=" << internal_blob_url_;
 }
 
@@ -26,8 +29,34 @@
   DVLOG(1) << __func__ << " this=" << this;
 }
 
+scoped_refptr<HandleAttachmentProvider>
+MediaSourceHandleImpl::TakeAttachmentProvider() {
+  return std::move(attachment_provider_);
+}
+
 scoped_refptr<MediaSourceAttachment> MediaSourceHandleImpl::TakeAttachment() {
-  return std::move(attachment_);
+  if (!attachment_provider_) {
+    // Either this handle instance has already been serialized, or it has been
+    // assigned as srcObject on an HTMLMediaElement and used later to begin
+    // asynchronous attachment start.
+    DCHECK(is_serialized() || is_used());
+    return nullptr;
+  }
+
+  // Otherwise, this handle instance must not yet have been serialized or used
+  // to begin an attachment. The only case we should be here is when this
+  // instance is being used to attempt asynchronous attachment start after it
+  // was set as srcObject on an HTMLMediaElement.
+  DCHECK(is_used() && !is_serialized());
+  scoped_refptr<MediaSourceAttachment> result =
+      attachment_provider_->TakeAttachment();
+  attachment_provider_ = nullptr;
+
+  // Note that |result| would be nullptr here if some other duplicated handle
+  // (due to postMessage's lack of true move-only semantics) has already started
+  // asynchronous attachment for the same underlying attachment (and
+  // MediaSource).
+  return result;
 }
 
 String MediaSourceHandleImpl::GetInternalBlobURL() {
@@ -39,11 +68,11 @@
   serialized_ = true;
 
   // Before being serialized, the serialization must have retrieved our
-  // reference to the |attachment_| precisely once. Note that immediately upon
-  // an instance of us being assigned to srcObject, that instance can no longer
-  // be serialized and there will be at most one async media element load that
-  // retrieves our attachment reference.
-  DCHECK(!attachment_);
+  // reference to the |attachment_provider_| precisely once. Note that
+  // immediately upon an instance of us being assigned to srcObject, that
+  // instance can no longer be serialized and there will be at most one async
+  // media element load that retrieves our provider's attachment reference.
+  DCHECK(!attachment_provider_);
 }
 
 void MediaSourceHandleImpl::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/modules/mediasource/media_source_handle_impl.h b/third_party/blink/renderer/modules/mediasource/media_source_handle_impl.h
index bd5ab93..f6c72ac 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source_handle_impl.h
+++ b/third_party/blink/renderer/modules/mediasource/media_source_handle_impl.h
@@ -8,6 +8,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/core/html/media/media_source_attachment.h"
 #include "third_party/blink/renderer/core/html/media/media_source_handle.h"
+#include "third_party/blink/renderer/modules/mediasource/handle_attachment_provider.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
@@ -19,10 +20,12 @@
 
  public:
   explicit MediaSourceHandleImpl(
-      scoped_refptr<MediaSourceAttachment> attachment,
+      scoped_refptr<HandleAttachmentProvider> attachment_provider,
       String internal_blob_url);
   ~MediaSourceHandleImpl() override;
 
+  scoped_refptr<HandleAttachmentProvider> TakeAttachmentProvider();
+
   scoped_refptr<MediaSourceAttachment> TakeAttachment() override;
   String GetInternalBlobURL() override;
 
@@ -31,7 +34,7 @@
   void Trace(Visitor*) const override;
 
  private:
-  scoped_refptr<MediaSourceAttachment> attachment_;
+  scoped_refptr<HandleAttachmentProvider> attachment_provider_;
   String internal_blob_url_;
 };
 
diff --git a/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.cc b/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.cc
index 6c5b12a..6a07579 100644
--- a/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.cc
@@ -45,6 +45,7 @@
 void LocalVideoCapturerSource::StartCapture(
     const media::VideoCaptureParams& params,
     const VideoCaptureDeliverFrameCB& new_frame_callback,
+    const VideoCaptureCropVersionCB& crop_version_callback,
     const RunningCallback& running_callback) {
   DCHECK(params.requested_format.IsValid());
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -56,7 +57,7 @@
           task_runner_, ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
                             &LocalVideoCapturerSource::OnStateUpdate,
                             weak_factory_.GetWeakPtr()))),
-      new_frame_callback);
+      new_frame_callback, crop_version_callback);
 }
 
 media::VideoCaptureFeedbackCB LocalVideoCapturerSource::GetFeedbackCallback()
diff --git a/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.h b/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.h
index c119e25..a257be75 100644
--- a/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.h
+++ b/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.h
@@ -54,6 +54,7 @@
   media::VideoCaptureFormats GetPreferredFormats() override;
   void StartCapture(const media::VideoCaptureParams& params,
                     const VideoCaptureDeliverFrameCB& new_frame_callback,
+                    const VideoCaptureCropVersionCB& crop_version_callback,
                     const RunningCallback& running_callback) override;
   void RequestRefreshFrame() override;
   void MaybeSuspend() override;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints.idl b/third_party/blink/renderer/modules/mediastream/media_stream_constraints.idl
index e880184..9a16c0f 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints.idl
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints.idl
@@ -2,13 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://w3c.github.io/mediacapture-main/#idl-def-mediastreamconstraints
+// https://github.com/w3c/mediacapture-screen-share/pull/222/files
+enum SystemAudioPreferenceEnum {
+  "include",
+  "exclude"
+};
 
+// https://w3c.github.io/mediacapture-main/#idl-def-mediastreamconstraints
 dictionary MediaStreamConstraints {
     (boolean or MediaTrackConstraints) video = false;
     (boolean or MediaTrackConstraints) audio = false;
+
     // https://wicg.github.io/prefer-current-tab/#prefer-current-tab
     boolean preferCurrentTab = false;
-    [RuntimeEnabled=GetDisplayMediaSetAutoSelectAllScreens]
-    boolean autoSelectAllScreens = false;
+
+    [
+      RuntimeEnabled = GetDisplayMediaSetAutoSelectAllScreens
+    ] boolean autoSelectAllScreens = false;
+
+    // https://github.com/w3c/mediacapture-screen-share/pull/222/files
+    [
+      RuntimeEnabled = SystemAudioConstraint
+    ] SystemAudioPreferenceEnum systemAudio;
 };
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_set_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_set_test.cc
index 73fc9934..af23b5cd 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_set_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_set_test.cc
@@ -34,8 +34,10 @@
     return weak_factory_.GetWeakPtr();
   }
 
-  void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback,
-                       EncodedVideoFrameCB encoded_frame_callback) override {}
+  void StartSourceImpl(
+      VideoCaptureDeliverFrameCB frame_callback,
+      EncodedVideoFrameCB encoded_frame_callback,
+      VideoCaptureCropVersionCB crop_version_callback) override {}
 
   void StopSourceImpl() override {}
 
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
index a35ef2a..bc76a9c 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
@@ -115,12 +115,16 @@
 
 void MediaStreamVideoCapturerSource::StartSourceImpl(
     VideoCaptureDeliverFrameCB frame_callback,
-    EncodedVideoFrameCB encoded_frame_callback) {
+    EncodedVideoFrameCB encoded_frame_callback,
+    VideoCaptureCropVersionCB crop_version_callback) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
   state_ = kStarting;
   frame_callback_ = std::move(frame_callback);
+  crop_version_callback_ = std::move(crop_version_callback);
+
   source_->StartCapture(
-      capture_params_, frame_callback_,
+      capture_params_, frame_callback_, crop_version_callback_,
       WTF::BindRepeating(&MediaStreamVideoCapturerSource::OnRunStateChanged,
                          WTF::Unretained(this), capture_params_));
 }
@@ -157,7 +161,7 @@
   new_capture_params.requested_format = new_format;
   state_ = kRestarting;
   source_->StartCapture(
-      new_capture_params, frame_callback_,
+      new_capture_params, frame_callback_, crop_version_callback_,
       WTF::BindRepeating(&MediaStreamVideoCapturerSource::OnRunStateChanged,
                          WTF::Unretained(this), new_capture_params));
 }
@@ -199,7 +203,7 @@
   SetDevice(new_device);
   source_ = device_capturer_factory_callback_.Run(new_device.session_id());
   source_->StartCapture(
-      capture_params_, frame_callback_,
+      capture_params_, frame_callback_, crop_version_callback_,
       WTF::BindRepeating(&MediaStreamVideoCapturerSource::OnRunStateChanged,
                          WTF::Unretained(this), capture_params_));
 }
@@ -228,6 +232,10 @@
 }
 #endif
 
+uint32_t MediaStreamVideoCapturerSource::GetCropVersion() const {
+  return current_crop_version_;
+}
+
 base::WeakPtr<MediaStreamVideoSource>
 MediaStreamVideoCapturerSource::GetWeakPtr() const {
   return weak_factory_.GetWeakPtr();
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h
index 0b0577d..d0349d0 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h
@@ -78,8 +78,10 @@
   void OnLog(const std::string& message) override;
   void OnHasConsumers(bool has_consumers) override;
   void OnCapturingLinkSecured(bool is_secure) override;
-  void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback,
-                       EncodedVideoFrameCB encoded_frame_callback) override;
+  void StartSourceImpl(
+      VideoCaptureDeliverFrameCB frame_callback,
+      EncodedVideoFrameCB encoded_frame_callback,
+      VideoCaptureCropVersionCB crop_version_callback) override;
   media::VideoCaptureFeedbackCB GetFeedbackCallback() const override;
   void StopSourceImpl() override;
   void StopSourceForRestartImpl() override;
@@ -95,6 +97,7 @@
       override;
   absl::optional<uint32_t> GetNextCropVersion() override;
 #endif
+  uint32_t GetCropVersion() const override;
   base::WeakPtr<MediaStreamVideoSource> GetWeakPtr() const override;
 
   // Method to bind as RunningCallback in VideoCapturerSource::StartCapture().
@@ -123,6 +126,7 @@
 
   media::VideoCaptureParams capture_params_;
   VideoCaptureDeliverFrameCB frame_callback_;
+  VideoCaptureCropVersionCB crop_version_callback_;
   DeviceCapturerFactoryCallback device_capturer_factory_callback_;
 
   // Each time Crop() is called, the source crop version increments.
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc
index ce8d0bd9..b7d5fd2 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc
@@ -50,6 +50,7 @@
   MOCK_METHOD0(MockStopCapture, void());
   void StartCapture(const media::VideoCaptureParams& params,
                     const VideoCaptureDeliverFrameCB& new_frame_callback,
+                    const VideoCaptureCropVersionCB& crop_version_callback,
                     const RunningCallback& running_callback) override {
     running_cb_ = running_callback;
     capture_params_ = params;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
index 9f020038..06ef8e1c 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
@@ -66,6 +66,7 @@
     const VideoCaptureDeliverFrameCB& frame_callback,
     const VideoCaptureNotifyFrameDroppedCB& notify_frame_dropped_callback,
     const EncodedVideoFrameCB& encoded_frame_callback,
+    const VideoCaptureCropVersionCB& crop_version_callback,
     const VideoTrackSettingsCallback& settings_callback,
     const VideoTrackFormatCallback& format_callback,
     ConstraintsOnceCallback callback) {
@@ -76,7 +77,8 @@
 
   pending_tracks_.push_back(PendingTrackInfo{
       track, frame_callback, notify_frame_dropped_callback,
-      encoded_frame_callback, settings_callback, format_callback,
+      encoded_frame_callback, crop_version_callback, settings_callback,
+      format_callback,
       std::make_unique<VideoTrackAdapterSettings>(track_adapter_settings),
       std::move(callback)});
 
@@ -88,7 +90,11 @@
               &VideoTrackAdapter::DeliverFrameOnIO, GetTrackAdapter())),
           ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
               &VideoTrackAdapter::DeliverEncodedVideoFrameOnIO,
-              GetTrackAdapter())));
+              GetTrackAdapter())),
+          ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+              &VideoTrackAdapter::NewCropVersionOnIO, GetTrackAdapter()))
+
+      );
       break;
     }
     case STARTING:
@@ -459,8 +465,9 @@
       GetTrackAdapter()->AddTrack(
           track_info.track, track_info.frame_callback,
           track_info.notify_frame_dropped_callback,
-          track_info.encoded_frame_callback, track_info.settings_callback,
-          track_info.format_callback, *track_info.adapter_settings);
+          track_info.encoded_frame_callback, track_info.crop_version_callback,
+          track_info.settings_callback, track_info.format_callback,
+          *track_info.adapter_settings);
       UpdateTrackSettings(track_info.track, *track_info.adapter_settings);
     }
 
@@ -546,6 +553,10 @@
 }
 #endif
 
+uint32_t MediaStreamVideoSource::GetCropVersion() const {
+  return 0;
+}
+
 VideoCaptureFeedbackCB MediaStreamVideoSource::GetFeedbackCallback() const {
   // Each source implementation has to implement its own feedback callbacks.
   return base::DoNothing();
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
index b495b870..db27cc90 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
@@ -84,7 +84,8 @@
 
   FrameDeliverer(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
                  base::WeakPtr<MediaStreamVideoTrack> media_stream_video_track,
-                 bool enabled);
+                 bool enabled,
+                 uint32_t crop_version);
 
   FrameDeliverer(const FrameDeliverer&) = delete;
   FrameDeliverer& operator=(const FrameDeliverer&) = delete;
@@ -134,6 +135,12 @@
   void DeliverEncodedVideoFrameOnIO(scoped_refptr<EncodedVideoFrame> frame,
                                     base::TimeTicks estimated_capture_time);
 
+  // Called when a crop-version is acknowledged by the capture module.
+  // After this, it is guaranteed that all subsequent frames will be
+  // associated with a crop-version that is >= |crop_version|.
+  // Must be called on the IO-thread.
+  void NewCropVersionOnIO(uint32_t crop_version);
+
   void SetIsRefreshingForMinFrameRate(bool is_refreshing_for_min_frame_rate);
 
   void AddCropVersionCallback(uint32_t crop_version,
@@ -176,8 +183,6 @@
                                   WTF::CrossThreadOnceClosure callback);
   void RemoveCropVersionCallbackOnIO(uint32_t crop_version);
 
-  void MaybeInvokeNewCropVersionCallbacksOnIO(uint32_t crop_version);
-
   // Returns a black frame where the size and time stamp is set to the same as
   // as in |reference_frame|.
   scoped_refptr<media::VideoFrame> GetBlackFrame(
@@ -208,19 +213,25 @@
 
   // This should only be accessed on the IO thread.
   bool is_refreshing_for_min_frame_rate_ = false;
+
+  // This monotonously increasing value indicates which crop-version
+  // is expected for delivered frames.
+  uint32_t crop_version_ = 0;
 };
 
 MediaStreamVideoTrack::FrameDeliverer::FrameDeliverer(
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     base::WeakPtr<MediaStreamVideoTrack> media_stream_video_track,
-    bool enabled)
+    bool enabled,
+    uint32_t crop_version)
     : io_task_runner_(std::move(io_task_runner)),
       // TODO(crbug.com/1223353, crbug.com/624696): Move to WebFrameScheduler.
       main_render_task_runner_(Thread::MainThread()->GetTaskRunner()),
       media_stream_video_track_(media_stream_video_track),
       enabled_(enabled),
       emit_frame_drop_events_(true),
-      await_next_key_frame_(false) {
+      await_next_key_frame_(false),
+      crop_version_(crop_version) {
   DCHECK(io_task_runner_.get());
 }
 
@@ -432,28 +443,12 @@
   crop_version_callbacks_.erase(crop_version);
 }
 
-void MediaStreamVideoTrack::FrameDeliverer::
-    MaybeInvokeNewCropVersionCallbacksOnIO(uint32_t crop_version) {
-  DCHECK(io_task_runner_->BelongsToCurrentThread());
-
-  Vector<uint32_t> to_be_removed_keys;
-  for (auto& iter : crop_version_callbacks_) {
-    if (iter.key > crop_version) {
-      continue;
-    }
-    std::move(iter.value).Run();
-    to_be_removed_keys.push_back(iter.key);
-  }
-  crop_version_callbacks_.RemoveAll(to_be_removed_keys);
-}
-
 void MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO(
     scoped_refptr<media::VideoFrame> frame,
     std::vector<scoped_refptr<media::VideoFrame>> scaled_video_frames,
     base::TimeTicks estimated_capture_time) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-
-  const uint32_t crop_version = frame->metadata().crop_version;
+  DCHECK_EQ(frame->metadata().crop_version, crop_version_);
 
   if (!enabled_ && main_render_task_runner_ && emit_frame_drop_events_) {
     emit_frame_drop_events_ = false;
@@ -492,8 +487,6 @@
         CrossThreadBindOnce(&MediaStreamVideoTrack::ResetRefreshTimer,
                             media_stream_video_track_));
   }
-
-  MaybeInvokeNewCropVersionCallbacksOnIO(crop_version);
 }
 
 void MediaStreamVideoTrack::FrameDeliverer::NotifyFrameDroppedOnIO() {
@@ -519,6 +512,24 @@
   }
 }
 
+void MediaStreamVideoTrack::FrameDeliverer::NewCropVersionOnIO(
+    uint32_t crop_version) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  DCHECK_GT(crop_version, crop_version_);
+
+  crop_version_ = crop_version;
+
+  Vector<uint32_t> to_be_removed_keys;
+  for (auto& iter : crop_version_callbacks_) {
+    if (iter.key > crop_version) {
+      continue;
+    }
+    std::move(iter.value).Run();
+    to_be_removed_keys.push_back(iter.key);
+  }
+  crop_version_callbacks_.RemoveAll(to_be_removed_keys);
+}
+
 scoped_refptr<media::VideoFrame>
 MediaStreamVideoTrack::FrameDeliverer::GetBlackFrame(
     const media::VideoFrame& reference_frame) {
@@ -599,7 +610,8 @@
       source_(source->GetWeakPtr()) {
   frame_deliverer_ =
       base::MakeRefCounted<MediaStreamVideoTrack::FrameDeliverer>(
-          source->io_task_runner(), weak_factory_.GetWeakPtr(), enabled);
+          source->io_task_runner(), weak_factory_.GetWeakPtr(), enabled,
+          source->GetCropVersion());
   source->AddTrack(
       this, VideoTrackAdapterSettings(),
       ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
@@ -611,6 +623,9 @@
       ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
           &MediaStreamVideoTrack::FrameDeliverer::DeliverEncodedVideoFrameOnIO,
           frame_deliverer_)),
+      ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+          &MediaStreamVideoTrack::FrameDeliverer::NewCropVersionOnIO,
+          frame_deliverer_)),
       media::BindToCurrentLoop(WTF::BindRepeating(
           &MediaStreamVideoTrack::SetSizeAndComputedFrameRate,
           weak_factory_.GetWeakPtr())),
@@ -644,7 +659,8 @@
       source_(source->GetWeakPtr()) {
   frame_deliverer_ =
       base::MakeRefCounted<MediaStreamVideoTrack::FrameDeliverer>(
-          source->io_task_runner(), weak_factory_.GetWeakPtr(), enabled);
+          source->io_task_runner(), weak_factory_.GetWeakPtr(), enabled,
+          source->GetCropVersion());
   source->AddTrack(
       this, adapter_settings,
       ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
@@ -656,6 +672,9 @@
       ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
           &MediaStreamVideoTrack::FrameDeliverer::DeliverEncodedVideoFrameOnIO,
           frame_deliverer_)),
+      ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
+          &MediaStreamVideoTrack::FrameDeliverer::NewCropVersionOnIO,
+          frame_deliverer_)),
       media::BindToCurrentLoop(WTF::BindRepeating(
           &MediaStreamVideoTrack::SetSizeAndComputedFrameRate,
           weak_factory_.GetWeakPtr())),
diff --git a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
index 492358a..12e34188 100644
--- a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.cc
@@ -84,7 +84,8 @@
 
 void MockMediaStreamVideoSource::StartSourceImpl(
     VideoCaptureDeliverFrameCB frame_callback,
-    EncodedVideoFrameCB encoded_frame_callback) {
+    EncodedVideoFrameCB encoded_frame_callback,
+    VideoCaptureCropVersionCB crop_version_callback) {
   DCHECK(frame_callback_.is_null());
   DCHECK(encoded_frame_callback_.is_null());
   attempted_to_start_ = true;
diff --git a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
index 17f9431..edd7df7 100644
--- a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
+++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
@@ -88,8 +88,10 @@
   void DoChangeSource(const blink::MediaStreamDevice& new_device) override;
 
   // Implements blink::MediaStreamVideoSource.
-  void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback,
-                       EncodedVideoFrameCB encoded_frame_callback) override;
+  void StartSourceImpl(
+      VideoCaptureDeliverFrameCB frame_callback,
+      EncodedVideoFrameCB encoded_frame_callback,
+      VideoCaptureCropVersionCB crop_version_callback) override;
   void StopSourceImpl() override;
   absl::optional<media::VideoCaptureFormat> GetCurrentFormat() const override;
   void StopSourceForRestartImpl() override;
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
index a708f48..c940960 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
+++ b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
@@ -637,22 +637,23 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(current_request_info_);
   DCHECK(current_request_info_->request()->Audio());
-  SendLogMessage(
-      base::StringPrintf("SetupAudioInput({request_id=%d}, {constraints=%s})",
-                         current_request_info_->request_id(),
-                         current_request_info_->request()
-                             ->AudioConstraints()
-                             .ToString()
-                             .Utf8()
-                             .c_str()));
 
-  auto& audio_controls = current_request_info_->stream_controls()->audio;
-  InitializeAudioTrackControls(current_request_info_->request(),
-                               &audio_controls);
+  UserMediaRequest* const request = current_request_info_->request();
+
+  SendLogMessage(base::StringPrintf(
+      "SetupAudioInput({request_id=%d}, {constraints=%s})",
+      current_request_info_->request_id(),
+      request->AudioConstraints().ToString().Utf8().c_str()));
+
+  StreamControls* const stream_controls =
+      current_request_info_->stream_controls();
+  stream_controls->exclude_system_audio = request->exclude_system_audio();
+
+  TrackControls& audio_controls = stream_controls->audio;
+  InitializeAudioTrackControls(request, &audio_controls);
 
   if (audio_controls.stream_type == MediaStreamType::DISPLAY_AUDIO_CAPTURE) {
-    SelectAudioSettings(current_request_info_->request(),
-                        {blink::AudioDeviceCaptureCapability()});
+    SelectAudioSettings(request, {blink::AudioDeviceCaptureCapability()});
     return;
   }
 
@@ -663,22 +664,17 @@
                            current_request_info_->request_id()));
     GetMediaDevicesDispatcher()->GetAudioInputCapabilities(
         WTF::Bind(&UserMediaProcessor::SelectAudioDeviceSettings,
-                  WrapWeakPersistent(this),
-                  WrapPersistent(current_request_info_->request())));
+                  WrapWeakPersistent(this), WrapPersistent(request)));
   } else {
     if (!blink::IsAudioInputMediaType(audio_controls.stream_type)) {
-      String failed_constraint_name =
-          String(current_request_info_->request()
-                     ->AudioConstraints()
-                     .Basic()
-                     .media_stream_source.GetName());
+      String failed_constraint_name = String(
+          request->AudioConstraints().Basic().media_stream_source.GetName());
       MediaStreamRequestResult result =
           MediaStreamRequestResult::CONSTRAINT_NOT_SATISFIED;
       GetUserMediaRequestFailed(result, failed_constraint_name);
       return;
     }
-    SelectAudioSettings(current_request_info_->request(),
-                        {blink::AudioDeviceCaptureCapability()});
+    SelectAudioSettings(request, {blink::AudioDeviceCaptureCapability()});
   }
 }
 
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.cc b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
index 2e7fd8e..f5ed59f 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_request.cc
+++ b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
@@ -391,9 +391,18 @@
   if (!video.IsNull())
     CountVideoConstraintUses(context, video);
 
-  return MakeGarbageCollected<UserMediaRequest>(
+  UserMediaRequest* const result = MakeGarbageCollected<UserMediaRequest>(
       context, controller, media_type, audio, video,
       options->preferCurrentTab(), callbacks, surface);
+
+  // The default is to include.
+  // Note that this option is no-op if audio is not requested.
+  result->set_exclude_system_audio(
+      options->hasSystemAudio() &&
+      options->systemAudio().AsEnum() ==
+          V8SystemAudioPreferenceEnum::Enum::kExclude);
+
+  return result;
 }
 
 UserMediaRequest* UserMediaRequest::CreateForTesting(
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.h b/third_party/blink/renderer/modules/mediastream/user_media_request.h
index 8d7d0747..ec8adde 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_request.h
+++ b/third_party/blink/renderer/modules/mediastream/user_media_request.h
@@ -147,6 +147,9 @@
 
   bool should_prefer_current_tab() const { return should_prefer_current_tab_; }
 
+  void set_exclude_system_audio(bool value) { exclude_system_audio_ = value; }
+  bool exclude_system_audio() const { return exclude_system_audio_; }
+
   // Mark this request as an GetOpenDevice request for initializing a
   // TransferredMediaStreamTrack from the deviced identified by session_id.
   void SetTransferData(const base::UnguessableToken& session_id,
@@ -167,6 +170,7 @@
   MediaConstraints audio_;
   MediaConstraints video_;
   const bool should_prefer_current_tab_ = false;
+  bool exclude_system_audio_ = false;
   bool should_disable_hardware_noise_suppression_;
   bool has_transient_user_activation_ = false;
   int32_t request_id_ = -1;
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
index 2601a92..4cceeff 100644
--- a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
+++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
@@ -140,6 +140,7 @@
     VideoCaptureNotifyFrameDroppedInternalCallback
         notify_frame_dropped_callback;
     DeliverEncodedVideoFrameInternalCallback encoded_frame_callback;
+    VideoCaptureCropVersionInternalCallback crop_version_callback;
     VideoTrackSettingsInternalCallback settings_callback;
     VideoTrackFormatInternalCallback format_callback;
   };
@@ -155,15 +156,17 @@
       delete;
 
   // Add |frame_callback|, |encoded_frame_callback| to receive video frames on
-  // the IO-thread and |settings_callback| to set track settings on the main
-  // thread. |frame_callback| will however be released on the main render
-  // thread.
+  // the IO-thread, |crop_version_callback| to receive notifications when
+  // a new crop version is acknowledged, and |settings_callback| to set track
+  // settings on the main thread. |frame_callback| will however be released
+  // on the main render thread.
   void AddCallbacks(
       const MediaStreamVideoTrack* track,
       VideoCaptureDeliverFrameInternalCallback frame_callback,
       VideoCaptureNotifyFrameDroppedInternalCallback
           notify_frame_dropped_callback,
       DeliverEncodedVideoFrameInternalCallback encoded_frame_callback,
+      VideoCaptureCropVersionInternalCallback crop_version_callback,
       VideoTrackSettingsInternalCallback settings_callback,
       VideoTrackFormatInternalCallback format_callback);
 
@@ -189,6 +192,8 @@
   void DeliverEncodedVideoFrame(scoped_refptr<EncodedVideoFrame> frame,
                                 base::TimeTicks estimated_capture_time);
 
+  void NewCropVersionOnIO(uint32_t crop_version);
+
   // Returns true if all arguments match with the output of this adapter.
   bool SettingsMatch(const VideoTrackAdapterSettings& settings) const;
 
@@ -280,6 +285,7 @@
     VideoCaptureNotifyFrameDroppedInternalCallback
         notify_frame_dropped_callback,
     DeliverEncodedVideoFrameInternalCallback encoded_frame_callback,
+    VideoCaptureCropVersionInternalCallback crop_version_callback,
     VideoTrackSettingsInternalCallback settings_callback,
     VideoTrackFormatInternalCallback format_callback) {
   DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
@@ -294,8 +300,11 @@
   }
 
   VideoTrackCallbacks track_callbacks = {
-      std::move(frame_callback), std::move(notify_frame_dropped_callback),
-      std::move(encoded_frame_callback), std::move(settings_callback),
+      std::move(frame_callback),
+      std::move(notify_frame_dropped_callback),
+      std::move(encoded_frame_callback),
+      std::move(crop_version_callback),
+      std::move(settings_callback),
       std::move(format_callback)};
   callbacks_.emplace(track, std::move(track_callbacks));
 }
@@ -419,6 +428,14 @@
   }
 }
 
+void VideoTrackAdapter::VideoFrameResolutionAdapter::NewCropVersionOnIO(
+    uint32_t crop_version) {
+  DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+  for (const auto& callback : callbacks_) {
+    callback.second.crop_version_callback.Run(crop_version);
+  }
+}
+
 bool VideoTrackAdapter::VideoFrameResolutionAdapter::SettingsMatch(
     const VideoTrackAdapterSettings& settings) const {
   DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
@@ -588,6 +605,7 @@
     VideoCaptureDeliverFrameCB frame_callback,
     VideoCaptureNotifyFrameDroppedCB notify_frame_dropped_callback,
     EncodedVideoFrameCB encoded_frame_callback,
+    VideoCaptureCropVersionCB crop_version_callback,
     VideoTrackSettingsCallback settings_callback,
     VideoTrackFormatCallback format_callback,
     const VideoTrackAdapterSettings& settings) {
@@ -601,6 +619,7 @@
           CrossThreadBindRepeating(std::move(frame_callback)),
           CrossThreadBindRepeating(std::move(notify_frame_dropped_callback)),
           CrossThreadBindRepeating(std::move(encoded_frame_callback)),
+          CrossThreadBindRepeating(std::move(crop_version_callback)),
           CrossThreadBindRepeating(std::move(settings_callback)),
           CrossThreadBindRepeating(std::move(format_callback)), settings));
 }
@@ -611,6 +630,7 @@
     VideoCaptureNotifyFrameDroppedInternalCallback
         notify_frame_dropped_callback,
     DeliverEncodedVideoFrameInternalCallback encoded_frame_callback,
+    VideoCaptureCropVersionInternalCallback crop_version_callback,
     VideoTrackSettingsInternalCallback settings_callback,
     VideoTrackFormatInternalCallback format_callback,
     const VideoTrackAdapterSettings& settings) {
@@ -628,11 +648,11 @@
     adapters_.push_back(adapter);
   }
 
-  adapter->AddCallbacks(track, std::move(frame_callback),
-                        std::move(notify_frame_dropped_callback),
-                        std::move(encoded_frame_callback),
-                        std::move(settings_callback),
-                        std::move(format_callback));
+  adapter->AddCallbacks(
+      track, std::move(frame_callback),
+      std::move(notify_frame_dropped_callback),
+      std::move(encoded_frame_callback), std::move(crop_version_callback),
+      std::move(settings_callback), std::move(format_callback));
 }
 
 void VideoTrackAdapter::RemoveTrack(const MediaStreamVideoTrack* track) {
@@ -822,6 +842,7 @@
     AddTrackOnIO(track, std::move(track_callbacks.frame_callback),
                  std::move(track_callbacks.notify_frame_dropped_callback),
                  std::move(track_callbacks.encoded_frame_callback),
+                 std::move(track_callbacks.crop_version_callback),
                  std::move(track_callbacks.settings_callback),
                  std::move(track_callbacks.format_callback), settings);
   }
@@ -868,6 +889,13 @@
     adapter->DeliverEncodedVideoFrame(frame, estimated_capture_time);
 }
 
+void VideoTrackAdapter::NewCropVersionOnIO(uint32_t crop_version) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  TRACE_EVENT0("media", "VideoTrackAdapter::NewCropVersionOnIO");
+  for (const auto& adapter : adapters_)
+    adapter->NewCropVersionOnIO(crop_version);
+}
+
 void VideoTrackAdapter::CheckFramesReceivedOnIO() {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
 
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter.h b/third_party/blink/renderer/modules/mediastream/video_track_adapter.h
index b1d085f..c5f4ba3 100644
--- a/third_party/blink/renderer/modules/mediastream/video_track_adapter.h
+++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.h
@@ -58,6 +58,7 @@
                 VideoCaptureDeliverFrameCB frame_callback,
                 VideoCaptureNotifyFrameDroppedCB notify_frame_dropped_callback,
                 EncodedVideoFrameCB encoded_frame_callback,
+                VideoCaptureCropVersionCB crop_version_callback,
                 VideoTrackSettingsCallback settings_callback,
                 VideoTrackFormatCallback track_callback,
                 const VideoTrackAdapterSettings& settings);
@@ -77,6 +78,11 @@
   void DeliverEncodedVideoFrameOnIO(scoped_refptr<EncodedVideoFrame> frame,
                                     base::TimeTicks estimated_capture_time);
 
+  // Called when it is guaranteed that all subsequent frames delivered
+  // over DeliverFrameOnIO() will have a crop version that is
+  // equal-to-or-greater-than the given crop version.
+  void NewCropVersionOnIO(uint32_t crop_version);
+
   base::SingleThreadTaskRunner* io_task_runner() const {
     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     return io_task_runner_.get();
@@ -123,6 +129,8 @@
       WTF::CrossThreadFunction<void(
           scoped_refptr<EncodedVideoFrame> video_frame,
           base::TimeTicks estimated_capture_time)>;
+  using VideoCaptureCropVersionInternalCallback =
+      WTF::CrossThreadFunction<void(uint32_t)>;
   using VideoTrackSettingsInternalCallback =
       WTF::CrossThreadFunction<void(gfx::Size frame_size, double frame_rate)>;
   using VideoTrackFormatInternalCallback =
@@ -133,6 +141,7 @@
       VideoCaptureNotifyFrameDroppedInternalCallback
           notify_frame_dropped_callback,
       DeliverEncodedVideoFrameInternalCallback encoded_frame_callback,
+      VideoCaptureCropVersionInternalCallback crop_version_callback,
       VideoTrackSettingsInternalCallback settings_callback,
       VideoTrackFormatInternalCallback track_callback,
       const VideoTrackAdapterSettings& settings);
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc
index e02ac9e..5c1ab8b 100644
--- a/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc
+++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc
@@ -267,7 +267,9 @@
             base::BindRepeating(
                 &VideoTrackAdapterFixtureTest::OnEncodedVideoFrameDelivered,
                 base::Unretained(this)),
-            base::DoNothing(), base::DoNothing(), adapter_settings));
+            /*crop_version_callback=*/base::DoNothing(),
+            /*settings_callback=*/base::DoNothing(),
+            /*format_callback=*/base::DoNothing(), adapter_settings));
   }
 
   void SetFrameValidationCallback(VideoCaptureDeliverFrameCB callback) {
@@ -443,6 +445,7 @@
           /*frame_callback=*/base::DoNothing(),
           /*notify_dropped_frame_callback=*/base::DoNothing(),
           /*encoded_frame_callback=*/base::DoNothing(),
+          /*crop_version_callback=*/base::DoNothing(),
           /*settings_callback=*/base::BindLambdaForTesting(check_dimensions),
           /*track_callback=*/base::DoNothing(), adapter_settings));
   settings_callback_run_.Wait();
@@ -485,7 +488,9 @@
           base::BindRepeating(
               &VideoTrackAdapterEncodedTest::OnEncodedVideoFrameDelivered,
               base::Unretained(this)),
-          base::DoNothing(), base::DoNothing(), VideoTrackAdapterSettings());
+          /*crop_version_callback=*/base::DoNothing(),
+          /*settings_callback=*/base::DoNothing(),
+          /*track_callback=*/base::DoNothing(), VideoTrackAdapterSettings());
     });
     return track;
   }
diff --git a/third_party/blink/renderer/modules/notifications/notification_data.cc b/third_party/blink/renderer/modules/notifications/notification_data.cc
index 64cbc40..41ad15b 100644
--- a/third_party/blink/renderer/modules/notifications/notification_data.cc
+++ b/third_party/blink/renderer/modules/notifications/notification_data.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/notifications/notification_data.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/common/notifications/notification_constants.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h"
@@ -18,7 +19,6 @@
 #include "third_party/blink/renderer/platform/bindings/enumeration_base.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_view.h"
 
 namespace blink {
@@ -122,7 +122,8 @@
     notification_data->data = Vector<uint8_t>();
     notification_data->data->Append(
         serialized_script_value->Data(),
-        SafeCast<wtf_size_t>(serialized_script_value->DataLengthInBytes()));
+        base::checked_cast<wtf_size_t>(
+            serialized_script_value->DataLengthInBytes()));
   }
 
   Vector<mojom::blink::NotificationActionPtr> actions;
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
index df8546f..0b76345 100644
--- a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
+++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
@@ -82,7 +82,8 @@
   RemoteVideoSourceDelegate(
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
       VideoCaptureDeliverFrameCB new_frame_callback,
-      EncodedVideoFrameCB encoded_frame_callback);
+      EncodedVideoFrameCB encoded_frame_callback,
+      VideoCaptureCropVersionCB crop_version_callback);
 
  protected:
   friend class WTF::ThreadSafeRefCounted<RemoteVideoSourceDelegate>;
@@ -111,6 +112,9 @@
   // |encoded_frame_callback_| is accessed on the IO thread.
   EncodedVideoFrameCB encoded_frame_callback_;
 
+  // |crop_version_callback| is accessed on the IO thread.
+  VideoCaptureCropVersionCB crop_version_callback_;
+
   // Timestamp of the first received frame.
   absl::optional<base::TimeTicks> start_timestamp_;
 
@@ -129,10 +133,12 @@
     RemoteVideoSourceDelegate(
         scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
         VideoCaptureDeliverFrameCB new_frame_callback,
-        EncodedVideoFrameCB encoded_frame_callback)
+        EncodedVideoFrameCB encoded_frame_callback,
+        VideoCaptureCropVersionCB crop_version_callback)
     : io_task_runner_(io_task_runner),
       frame_callback_(std::move(new_frame_callback)),
       encoded_frame_callback_(std::move(encoded_frame_callback)),
+      crop_version_callback_(std::move(crop_version_callback)),
       clock_(webrtc::Clock::GetRealTimeClock()),
       ntp_offset_(clock_->TimeInMilliseconds() -
                   clock_->CurrentNtpInMilliseconds()),
@@ -144,7 +150,11 @@
 
 void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
     const webrtc::VideoFrame& incoming_frame) {
-  const bool render_immediately = incoming_frame.timestamp_us() == 0;
+  const webrtc::VideoFrame::RenderParameters render_parameters =
+      incoming_frame.render_parameters();
+  const bool render_immediately = render_parameters.use_low_latency_rendering ||
+                                  incoming_frame.timestamp_us() == 0;
+
   const base::TimeTicks current_time = base::TimeTicks::Now();
   const base::TimeTicks render_time =
       render_immediately
@@ -201,9 +211,9 @@
   if (!render_immediately)
     video_frame->metadata().reference_time = render_time;
 
-  if (incoming_frame.max_composition_delay_in_frames()) {
+  if (render_parameters.max_composition_delay_in_frames) {
     video_frame->metadata().maximum_composition_delay_in_frames =
-        *incoming_frame.max_composition_delay_in_frames();
+        render_parameters.max_composition_delay_in_frames;
   }
 
   video_frame->metadata().decode_end_time = current_time;
@@ -312,12 +322,13 @@
 
 void MediaStreamRemoteVideoSource::StartSourceImpl(
     VideoCaptureDeliverFrameCB frame_callback,
-    EncodedVideoFrameCB encoded_frame_callback) {
+    EncodedVideoFrameCB encoded_frame_callback,
+    VideoCaptureCropVersionCB crop_version_callback) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(!delegate_.get());
   delegate_ = base::MakeRefCounted<RemoteVideoSourceDelegate>(
       io_task_runner(), std::move(frame_callback),
-      std::move(encoded_frame_callback));
+      std::move(encoded_frame_callback), std::move(crop_version_callback));
   scoped_refptr<webrtc::VideoTrackInterface> video_track(
       static_cast<webrtc::VideoTrackInterface*>(observer_->track().get()));
   video_track->AddOrUpdateSink(delegate_.get(), rtc::VideoSinkWants());
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h
index b6f2cfb..739c2484 100644
--- a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h
+++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h
@@ -46,8 +46,10 @@
 
  protected:
   // Implements MediaStreamVideoSource.
-  void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback,
-                       EncodedVideoFrameCB encoded_frame_callback) override;
+  void StartSourceImpl(
+      VideoCaptureDeliverFrameCB frame_callback,
+      EncodedVideoFrameCB encoded_frame_callback,
+      VideoCaptureCropVersionCB crop_version_callback) override;
   void StopSourceImpl() override;
   void OnEncodedSinkEnabled() override;
   void OnEncodedSinkDisabled() override;
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
index 4785941..6478004 100644
--- a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
@@ -205,7 +205,6 @@
   source()->SinkInterfaceForTesting()->OnFrame(
       webrtc::VideoFrame::Builder()
           .set_video_frame_buffer(buffer)
-          .set_rotation(webrtc::kVideoRotation_0)
           .set_timestamp_us(1000)
           .build());
   run_loop.Run();
@@ -271,13 +270,10 @@
                                  webrtc::ColorSpace::TransferID::kSMPTE240M,
                                  webrtc::ColorSpace::MatrixID::kSMPTE240M,
                                  webrtc::ColorSpace::RangeID::kLimited);
-  const webrtc::VideoFrame& input_frame =
-      webrtc::VideoFrame::Builder()
-          .set_video_frame_buffer(buffer)
-          .set_timestamp_ms(0)
-          .set_rotation(webrtc::kVideoRotation_0)
-          .set_color_space(kColorSpace)
-          .build();
+  const webrtc::VideoFrame& input_frame = webrtc::VideoFrame::Builder()
+                                              .set_video_frame_buffer(buffer)
+                                              .set_color_space(kColorSpace)
+                                              .build();
   source()->SinkInterfaceForTesting()->OnFrame(input_frame);
   run_loop.Run();
 
@@ -309,13 +305,10 @@
                                  webrtc::ColorSpace::TransferID::kUnspecified,
                                  webrtc::ColorSpace::MatrixID::kUnspecified,
                                  webrtc::ColorSpace::RangeID::kLimited);
-  const webrtc::VideoFrame& input_frame =
-      webrtc::VideoFrame::Builder()
-          .set_video_frame_buffer(buffer)
-          .set_timestamp_ms(0)
-          .set_rotation(webrtc::kVideoRotation_0)
-          .set_color_space(kColorSpace)
-          .build();
+  const webrtc::VideoFrame& input_frame = webrtc::VideoFrame::Builder()
+                                              .set_video_frame_buffer(buffer)
+                                              .set_color_space(kColorSpace)
+                                              .build();
   source()->SinkInterfaceForTesting()->OnFrame(input_frame);
   run_loop.Run();
 
@@ -349,13 +342,10 @@
                                  webrtc::ColorSpace::TransferID::kUnspecified,
                                  webrtc::ColorSpace::MatrixID::kUnspecified,
                                  webrtc::ColorSpace::RangeID::kLimited);
-  const webrtc::VideoFrame& input_frame =
-      webrtc::VideoFrame::Builder()
-          .set_video_frame_buffer(buffer)
-          .set_timestamp_ms(0)
-          .set_rotation(webrtc::kVideoRotation_0)
-          .set_color_space(kColorSpace)
-          .build();
+  const webrtc::VideoFrame& input_frame = webrtc::VideoFrame::Builder()
+                                              .set_video_frame_buffer(buffer)
+                                              .set_color_space(kColorSpace)
+                                              .build();
   source()->SinkInterfaceForTesting()->OnFrame(input_frame);
   run_loop.Run();
 
@@ -520,6 +510,7 @@
 
   webrtc::VideoFrame input_frame =
       webrtc::VideoFrame::Builder().set_video_frame_buffer(buffer).build();
+  input_frame.set_render_parameters({.use_low_latency_rendering = true});
 
   source()->SinkInterfaceForTesting()->OnFrame(input_frame);
   run_loop.Run();
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
index b429934..78d28d6 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
@@ -31,6 +31,7 @@
 
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/events/message_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -49,7 +50,6 @@
 #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_std.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
 
 namespace WTF {
@@ -140,12 +140,12 @@
 
   if (channel.reliable()) {
     UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.ReliableDataChannelMessageSize",
-                                SafeCast<int>(num_bytes), 1, kMaxBucketSize,
-                                kNumBuckets);
+                                base::checked_cast<int>(num_bytes), 1,
+                                kMaxBucketSize, kNumBuckets);
   } else {
     UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.UnreliableDataChannelMessageSize",
-                                SafeCast<int>(num_bytes), 1, kMaxBucketSize,
-                                kNumBuckets);
+                                base::checked_cast<int>(num_bytes), 1,
+                                kMaxBucketSize, kNumBuckets);
   }
 }
 
@@ -264,7 +264,7 @@
       *main_thread_, FROM_HERE,
       CrossThreadBindOnce(&RTCDataChannel::Observer::OnBufferedAmountChangeImpl,
                           scoped_refptr<Observer>(this),
-                          SafeCast<unsigned>(sent_data_size)));
+                          base::checked_cast<unsigned>(sent_data_size)));
 }
 
 void RTCDataChannel::Observer::OnMessage(const webrtc::DataBuffer& buffer) {
@@ -666,7 +666,8 @@
     }
     if (binary_type_ == kBinaryTypeArrayBuffer) {
       DOMArrayBuffer* dom_buffer = DOMArrayBuffer::Create(
-          buffer->data.cdata(), SafeCast<unsigned>(buffer->data.size()));
+          buffer->data.cdata(),
+          base::checked_cast<unsigned>(buffer->data.size()));
       ScheduleDispatchEvent(MessageEvent::Create(dom_buffer));
       return;
     }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index bcb9e9f1..868d6f5 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -39,6 +39,7 @@
 #include "base/lazy_instance.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
@@ -129,7 +130,6 @@
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/webrtc/api/data_channel_interface.h"
 #include "third_party/webrtc/api/dtls_transport_interface.h"
 #include "third_party/webrtc/api/jsep.h"
@@ -1561,12 +1561,13 @@
 
   HeapVector<Member<RTCIceServer>> ice_servers;
   ice_servers.ReserveCapacity(
-      SafeCast<wtf_size_t>(webrtc_configuration.servers.size()));
+      base::checked_cast<wtf_size_t>(webrtc_configuration.servers.size()));
   for (const auto& webrtc_server : webrtc_configuration.servers) {
     auto* ice_server = RTCIceServer::Create();
 
     Vector<String> url_vector;
-    url_vector.ReserveCapacity(SafeCast<wtf_size_t>(webrtc_server.urls.size()));
+    url_vector.ReserveCapacity(
+        base::checked_cast<wtf_size_t>(webrtc_server.urls.size()));
     for (const auto& url : webrtc_server.urls) {
       url_vector.emplace_back(url.c_str());
     }
@@ -1582,8 +1583,8 @@
 
   if (!webrtc_configuration.certificates.empty()) {
     HeapVector<blink::Member<RTCCertificate>> certificates;
-    certificates.ReserveCapacity(
-        SafeCast<wtf_size_t>(webrtc_configuration.certificates.size()));
+    certificates.ReserveCapacity(base::checked_cast<wtf_size_t>(
+        webrtc_configuration.certificates.size()));
     for (const auto& webrtc_certificate : webrtc_configuration.certificates) {
       certificates.emplace_back(
           MakeGarbageCollected<RTCCertificate>(webrtc_certificate));
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
index 7662f2cd..228f630 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -21,6 +21,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_checker.h"
 #include "base/trace_event/trace_event.h"
@@ -2465,13 +2466,14 @@
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   DCHECK_EQ(configuration_.sdp_semantics, webrtc::SdpSemantics::kUnifiedPlan);
   Vector<std::unique_ptr<RTCRtpTransceiverPlatform>> platform_transceivers(
-      SafeCast<WTF::wtf_size_t>(transceiver_states.size()));
+      base::checked_cast<WTF::wtf_size_t>(transceiver_states.size()));
   PeerConnectionTracker::TransceiverUpdatedReason update_reason =
       !is_remote_description ? PeerConnectionTracker::TransceiverUpdatedReason::
                                    kSetLocalDescription
                              : PeerConnectionTracker::TransceiverUpdatedReason::
                                    kSetRemoteDescription;
-  Vector<uintptr_t> ids(SafeCast<wtf_size_t>(transceiver_states.size()));
+  Vector<uintptr_t> ids(
+      base::checked_cast<wtf_size_t>(transceiver_states.size()));
   for (WTF::wtf_size_t i = 0; i < transceiver_states.size(); ++i) {
     // Figure out if this transceiver is new or if setting the state modified
     // the transceiver such that it should be logged by the
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
index 1b32074d..7d95c6e7 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "base/synchronization/lock.h"
 #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
 #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
@@ -36,7 +37,6 @@
 #include "third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_stats.h"
 #include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/webrtc/api/rtp_parameters.h"
 
@@ -251,7 +251,7 @@
 
   HeapVector<Member<RTCRtpCodecCapability>> codecs;
   codecs.ReserveInitialCapacity(
-      SafeCast<wtf_size_t>(rtc_capabilities->codecs.size()));
+      base::checked_cast<wtf_size_t>(rtc_capabilities->codecs.size()));
   for (const auto& rtc_codec : rtc_capabilities->codecs) {
     auto* codec = RTCRtpCodecCapability::Create();
     codec->setMimeType(WTF::String::FromUTF8(rtc_codec.mime_type()));
@@ -277,8 +277,8 @@
   capabilities->setCodecs(codecs);
 
   HeapVector<Member<RTCRtpHeaderExtensionCapability>> header_extensions;
-  header_extensions.ReserveInitialCapacity(
-      SafeCast<wtf_size_t>(rtc_capabilities->header_extensions.size()));
+  header_extensions.ReserveInitialCapacity(base::checked_cast<wtf_size_t>(
+      rtc_capabilities->header_extensions.size()));
   for (const auto& rtc_header_extension : rtc_capabilities->header_extensions) {
     auto* header_extension = RTCRtpHeaderExtensionCapability::Create();
     header_extension->setUri(WTF::String::FromUTF8(rtc_header_extension.uri));
@@ -312,7 +312,7 @@
 
   HeapVector<Member<RTCRtpDecodingParameters>> encodings;
   encodings.ReserveCapacity(
-      SafeCast<wtf_size_t>(webrtc_parameters->encodings.size()));
+      base::checked_cast<wtf_size_t>(webrtc_parameters->encodings.size()));
   for (const auto& webrtc_encoding : webrtc_parameters->encodings) {
     RTCRtpDecodingParameters* encoding = RTCRtpDecodingParameters::Create();
     if (!webrtc_encoding.rid.empty()) {
@@ -323,8 +323,8 @@
   parameters->setEncodings(encodings);
 
   HeapVector<Member<RTCRtpHeaderExtensionParameters>> headers;
-  headers.ReserveCapacity(
-      SafeCast<wtf_size_t>(webrtc_parameters->header_extensions.size()));
+  headers.ReserveCapacity(base::checked_cast<wtf_size_t>(
+      webrtc_parameters->header_extensions.size()));
   for (const auto& webrtc_header : webrtc_parameters->header_extensions) {
     headers.push_back(ToRtpHeaderExtensionParameters(webrtc_header));
   }
@@ -332,7 +332,7 @@
 
   HeapVector<Member<RTCRtpCodecParameters>> codecs;
   codecs.ReserveCapacity(
-      SafeCast<wtf_size_t>(webrtc_parameters->codecs.size()));
+      base::checked_cast<wtf_size_t>(webrtc_parameters->codecs.size()));
   for (const auto& webrtc_codec : webrtc_parameters->codecs) {
     codecs.push_back(ToRtpCodecParameters(webrtc_codec));
   }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
index 2d49b549b..2e4dfc3 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -9,6 +9,7 @@
 #include <tuple>
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
 #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
 #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
@@ -49,7 +50,6 @@
 #include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -490,7 +490,7 @@
 
   HeapVector<Member<RTCRtpEncodingParameters>> encodings;
   encodings.ReserveCapacity(
-      SafeCast<wtf_size_t>(webrtc_parameters->encodings.size()));
+      base::checked_cast<wtf_size_t>(webrtc_parameters->encodings.size()));
   for (const auto& webrtc_encoding : webrtc_parameters->encodings) {
     RTCRtpEncodingParameters* encoding = RTCRtpEncodingParameters::Create();
     if (!webrtc_encoding.rid.empty()) {
@@ -521,8 +521,8 @@
   parameters->setEncodings(encodings);
 
   HeapVector<Member<RTCRtpHeaderExtensionParameters>> headers;
-  headers.ReserveCapacity(
-      SafeCast<wtf_size_t>(webrtc_parameters->header_extensions.size()));
+  headers.ReserveCapacity(base::checked_cast<wtf_size_t>(
+      webrtc_parameters->header_extensions.size()));
   for (const auto& webrtc_header : webrtc_parameters->header_extensions) {
     headers.push_back(ToRtpHeaderExtensionParameters(webrtc_header));
   }
@@ -530,7 +530,7 @@
 
   HeapVector<Member<RTCRtpCodecParameters>> codecs;
   codecs.ReserveCapacity(
-      SafeCast<wtf_size_t>(webrtc_parameters->codecs.size()));
+      base::checked_cast<wtf_size_t>(webrtc_parameters->codecs.size()));
   for (const auto& webrtc_codec : webrtc_parameters->codecs) {
     codecs.push_back(ToRtpCodecParameters(webrtc_codec));
   }
@@ -756,7 +756,7 @@
 
   HeapVector<Member<RTCRtpCodecCapability>> codecs;
   codecs.ReserveInitialCapacity(
-      SafeCast<wtf_size_t>(rtc_capabilities->codecs.size()));
+      base::checked_cast<wtf_size_t>(rtc_capabilities->codecs.size()));
   for (const auto& rtc_codec : rtc_capabilities->codecs) {
     auto* codec = RTCRtpCodecCapability::Create();
     codec->setMimeType(WTF::String::FromUTF8(rtc_codec.mime_type()));
@@ -813,8 +813,8 @@
   capabilities->setCodecs(codecs);
 
   HeapVector<Member<RTCRtpHeaderExtensionCapability>> header_extensions;
-  header_extensions.ReserveInitialCapacity(
-      SafeCast<wtf_size_t>(rtc_capabilities->header_extensions.size()));
+  header_extensions.ReserveInitialCapacity(base::checked_cast<wtf_size_t>(
+      rtc_capabilities->header_extensions.size()));
   for (const auto& rtc_header_extension : rtc_capabilities->header_extensions) {
     auto* header_extension = RTCRtpHeaderExtensionCapability::Create();
     header_extension->setUri(WTF::String::FromUTF8(rtc_header_extension.uri));
diff --git a/third_party/blink/renderer/modules/push_messaging/push_subscription.cc b/third_party/blink/renderer/modules/push_messaging/push_subscription.cc
index 9379c83e..d74a8d3 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_subscription.cc
+++ b/third_party/blink/renderer/modules/push_messaging/push_subscription.cc
@@ -5,6 +5,8 @@
 #include "third_party/blink/renderer/modules/push_messaging/push_subscription.h"
 
 #include <memory>
+
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
@@ -15,7 +17,6 @@
 #include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/base64.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
@@ -86,10 +87,11 @@
       options_(MakeGarbageCollected<PushSubscriptionOptions>(
           user_visible_only,
           application_server_key)),
-      p256dh_(DOMArrayBuffer::Create(p256dh.data(),
-                                     SafeCast<unsigned>(p256dh.size()))),
-      auth_(
-          DOMArrayBuffer::Create(auth.data(), SafeCast<unsigned>(auth.size()))),
+      p256dh_(
+          DOMArrayBuffer::Create(p256dh.data(),
+                                 base::checked_cast<unsigned>(p256dh.size()))),
+      auth_(DOMArrayBuffer::Create(auth.data(),
+                                   base::checked_cast<unsigned>(auth.size()))),
       expiration_time_(expiration_time),
       service_worker_registration_(service_worker_registration) {}
 
diff --git a/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc b/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc
index 082210a..3d00a21 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc
+++ b/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc
@@ -4,13 +4,13 @@
 
 #include "third_party/blink/renderer/modules/push_messaging/push_subscription_options.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_push_subscription_options_init.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
 #include "third_party/blink/renderer/platform/wtf/text/base64.h"
 
@@ -100,7 +100,7 @@
     : user_visible_only_(user_visible_only),
       application_server_key_(DOMArrayBuffer::Create(
           application_server_key.data(),
-          SafeCast<unsigned>(application_server_key.size()))) {}
+          base::checked_cast<unsigned>(application_server_key.size()))) {}
 
 void PushSubscriptionOptions::Trace(Visitor* visitor) const {
   visitor->Trace(application_server_key_);
diff --git a/third_party/blink/renderer/modules/remote_objects/remote_object.cc b/third_party/blink/renderer/modules/remote_objects/remote_object.cc
index 3172da2..ebc4c5c 100644
--- a/third_party/blink/renderer/modules/remote_objects/remote_object.cc
+++ b/third_party/blink/renderer/modules/remote_objects/remote_object.cc
@@ -7,6 +7,7 @@
 #include <tuple>
 
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "gin/converter.h"
 #include "third_party/blink/public/web/blink.h"
 #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
@@ -231,7 +232,7 @@
     }
 
     WTF::Vector<mojom::blink::RemoteInvocationArgumentPtr> nested_arguments(
-        SafeCast<wtf_size_t>(length));
+        base::checked_cast<wtf_size_t>(length));
     for (uint32_t i = 0; i < property_names->Length(); ++i) {
       v8::Local<v8::Value> key;
       if (!property_names->Get(isolate->GetCurrentContext(), i).ToLocal(&key) ||
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
index 68649ba..965ff39 100644
--- a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
+++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
@@ -72,7 +73,8 @@
   // encoded string representation of the source URL.
   std::string source_string = source.GetString().Utf8();
   String encoded_source = WTF::Base64URLEncode(
-      source_string.data(), SafeCast<unsigned>(source_string.length()));
+      source_string.data(),
+      base::checked_cast<unsigned>(source_string.length()));
 
   return KURL("remote-playback://" + encoded_source);
 }
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc b/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
index 9569803..3f5667c 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/barrier_closure.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/threading/thread_checker.h"
 #include "base/trace_event/trace_event.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -25,7 +26,6 @@
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 #include "third_party/blink/renderer/platform/wtf/wtf.h"
@@ -52,7 +52,7 @@
                  mojo::SimpleWatcher::ArmingPolicy::MANUAL,
                  std::move(task_runner)),
         remaining_bytes_(total_bytes) {
-    data_.ReserveInitialCapacity(SafeCast<wtf_size_t>(total_bytes));
+    data_.ReserveInitialCapacity(base::checked_cast<wtf_size_t>(total_bytes));
   }
 
   void Start(base::OnceClosure callback) {
diff --git a/third_party/blink/renderer/modules/shared_storage/shared_storage.cc b/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
index 3f14882..3a2d0c0 100644
--- a/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
+++ b/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
@@ -8,6 +8,7 @@
 #include <tuple>
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
@@ -71,7 +72,7 @@
 
   std::pair<uint8_t*, size_t> buffer = serializer.Release();
 
-  output.ReserveInitialCapacity(SafeCast<wtf_size_t>(buffer.second));
+  output.ReserveInitialCapacity(base::checked_cast<wtf_size_t>(buffer.second));
   output.Append(buffer.first, static_cast<wtf_size_t>(buffer.second));
   DCHECK_EQ(output.size(), buffer.second);
 
diff --git a/third_party/blink/renderer/modules/webaudio/audio_listener.cc b/third_party/blink/renderer/modules/webaudio/audio_listener.cc
index dfefe90..c1e5b96 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_listener.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_listener.cc
@@ -278,11 +278,11 @@
   // to check for the audio thread.)
   DCHECK(!IsMainThread());
 
-  MutexTryLocker try_locker(listener_lock_);
+  const MutexTryLocker try_locker(listener_lock_);
   if (try_locker.Locked()) {
-    gfx::Point3F current_position = GetPosition();
-    gfx::Vector3dF current_forward = Orientation();
-    gfx::Vector3dF current_up = UpVector();
+    const gfx::Point3F current_position = GetPosition();
+    const gfx::Vector3dF current_forward = Orientation();
+    const gfx::Vector3dF current_up = UpVector();
 
     is_listener_dirty_ = current_position != last_position_ ||
                          current_forward != last_forward_ ||
@@ -332,9 +332,9 @@
   DCHECK(IsMainThread());
 
   // This synchronizes with panner's process().
-  MutexLocker listener_locker(listener_lock_);
+  const MutexLocker listener_locker(listener_lock_);
 
-  double now = position_x_->Context()->currentTime();
+  const double now = position_x_->Context()->currentTime();
 
   position_x_->setValueAtTime(position.x(), now, exceptionState);
   position_y_->setValueAtTime(position.y(), now, exceptionState);
@@ -349,9 +349,9 @@
   DCHECK(IsMainThread());
 
   // This synchronizes with panner's process().
-  MutexLocker listener_locker(listener_lock_);
+  const MutexLocker listener_locker(listener_lock_);
 
-  double now = forward_x_->Context()->currentTime();
+  const double now = forward_x_->Context()->currentTime();
 
   forward_x_->setValueAtTime(orientation.x(), now, exceptionState);
   forward_y_->setValueAtTime(orientation.y(), now, exceptionState);
@@ -365,9 +365,9 @@
   DCHECK(IsMainThread());
 
   // This synchronizes with panner's process().
-  MutexLocker listener_locker(listener_lock_);
+  const MutexLocker listener_locker(listener_lock_);
 
-  double now = up_x_->Context()->currentTime();
+  const double now = up_x_->Context()->currentTime();
 
   up_x_->setValueAtTime(up_vector.x(), now, exceptionState);
   up_y_->setValueAtTime(up_vector.y(), now, exceptionState);
diff --git a/third_party/blink/renderer/modules/webaudio/panner_handler.cc b/third_party/blink/renderer/modules/webaudio/panner_handler.cc
index e58dd58b..4f52b5a5 100644
--- a/third_party/blink/renderer/modules/webaudio/panner_handler.cc
+++ b/third_party/blink/renderer/modules/webaudio/panner_handler.cc
@@ -99,7 +99,7 @@
   // inputs.  The first time we're called during this time slice we process, but
   // after that we don't want to re-process, instead our output(s) will already
   // have the results cached in their bus
-  double current_time = Context()->currentTime();
+  const double current_time = Context()->currentTime();
   if (last_processing_time_ != current_time) {
     // important to first update this time because of feedback loops in the
     // rendering graph.
@@ -107,7 +107,7 @@
 
     PullInputs(frames_to_process);
 
-    bool silent_inputs = InputsAreSilent();
+    const bool silent_inputs = InputsAreSilent();
 
     {
       // Need to protect calls to PropagetesSilence (and Process) because the
@@ -201,7 +201,7 @@
                    frames_to_process, InternalChannelInterpretation());
 
       // Get the distance and cone gain.
-      float total_gain = DistanceConeGain();
+      const float total_gain = DistanceConeGain();
 
       // Apply gain in-place.
       destination->CopyWithGainFrom(*destination, total_gain);
diff --git a/third_party/blink/renderer/modules/webcodecs/image_decoder_core.cc b/third_party/blink/renderer/modules/webcodecs/image_decoder_core.cc
index 77f3701b..012d410 100644
--- a/third_party/blink/renderer/modules/webcodecs/image_decoder_core.cc
+++ b/third_party/blink/renderer/modules/webcodecs/image_decoder_core.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/time/time.h"
 #include "media/base/timestamp_constants.h"
 #include "media/base/video_frame.h"
@@ -123,7 +124,7 @@
   }
 
   metadata.has_size = true;
-  metadata.frame_count = SafeCast<uint32_t>(decoder_->FrameCount());
+  metadata.frame_count = base::checked_cast<uint32_t>(decoder_->FrameCount());
   metadata.repetition_count = decoder_->RepetitionCount();
   metadata.image_has_both_still_and_animated_sub_images =
       decoder_->ImageHasBothStillAndAnimatedSubImages();
@@ -286,7 +287,7 @@
   data_complete_ = data_complete;
   if (data) {
     stream_buffer_->Append(reinterpret_cast<const char*>(data.get()),
-                           SafeCast<wtf_size_t>(data_size));
+                           base::checked_cast<wtf_size_t>(data_size));
   } else {
     DCHECK_EQ(data_size, 0u);
   }
diff --git a/third_party/blink/renderer/modules/webgpu/BUILD.gn b/third_party/blink/renderer/modules/webgpu/BUILD.gn
index d8eda7f..a919ed0 100644
--- a/third_party/blink/renderer/modules/webgpu/BUILD.gn
+++ b/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -99,3 +99,17 @@
     "//third_party/dawn/include/dawn:headers",
   ]
 }
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [ "gpu_context_lost_test.cc" ]
+
+  deps = [
+    "//base/test:test_support",
+    "//third_party/blink/renderer/controller:blink_bindings_test_sources",
+    "//third_party/blink/renderer/core",
+    "//third_party/blink/renderer/core:testing",
+    "//third_party/blink/renderer/modules",
+    "//third_party/blink/renderer/platform:test_support",
+  ]
+}
diff --git a/third_party/blink/renderer/modules/webgpu/DEPS b/third_party/blink/renderer/modules/webgpu/DEPS
index c7774f83..1238fdd 100644
--- a/third_party/blink/renderer/modules/webgpu/DEPS
+++ b/third_party/blink/renderer/modules/webgpu/DEPS
@@ -9,6 +9,7 @@
     "+gpu/command_buffer/client/raster_interface.h",
     "+gpu/command_buffer/client/shared_image_interface.h",
     "+gpu/command_buffer/client/webgpu_interface.h",
+    "+gpu/command_buffer/client/webgpu_interface_stub.h",
     "+media/base/video_frame.h",
     "+media/base/wait_and_replace_sync_token_client.h",
     "+media/renderers/paint_canvas_video_renderer.h",
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
index f799baa..25fab793 100644
--- a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
+++ b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.h"
 
+#include "base/notreached.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_address_mode.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_blend_factor.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_blend_operation.h"
@@ -126,6 +127,20 @@
   }
 }
 
+const char* FromDawnEnum(WGPUQueryType dawn_enum) {
+  switch (dawn_enum) {
+    case WGPUQueryType_Occlusion:
+      return "occlusion";
+    case WGPUQueryType_Timestamp:
+      return "timestamp";
+    case WGPUQueryType_PipelineStatistics:
+      return "pipeline-statistics";
+    case WGPUQueryType_Force32:
+      NOTREACHED();
+  }
+  return "";
+}
+
 WGPUPipelineStatisticName AsDawnEnum(
     const V8GPUPipelineStatisticName& webgpu_enum) {
   switch (webgpu_enum.AsEnum()) {
@@ -354,6 +369,222 @@
   }
 }
 
+const char* FromDawnEnum(WGPUTextureFormat dawn_enum) {
+  switch (dawn_enum) {
+    // Normal 8 bit formats
+    case WGPUTextureFormat_R8Unorm:
+      return "r8unorm";
+    case WGPUTextureFormat_R8Snorm:
+      return "r8snorm";
+    case WGPUTextureFormat_R8Uint:
+      return "r8uint";
+    case WGPUTextureFormat_R8Sint:
+      return "r8sint";
+
+    // Normal 16 bit formats
+    case WGPUTextureFormat_R16Uint:
+      return "r16uint";
+    case WGPUTextureFormat_R16Sint:
+      return "r16sint";
+    case WGPUTextureFormat_R16Float:
+      return "r16float";
+    case WGPUTextureFormat_RG8Unorm:
+      return "rg8unorm";
+    case WGPUTextureFormat_RG8Snorm:
+      return "rg8snorm";
+    case WGPUTextureFormat_RG8Uint:
+      return "rg8uint";
+    case WGPUTextureFormat_RG8Sint:
+      return "rg8sint";
+
+    // Normal 32 bit formats
+    case WGPUTextureFormat_R32Uint:
+      return "r32uint";
+    case WGPUTextureFormat_R32Sint:
+      return "r32sint";
+    case WGPUTextureFormat_R32Float:
+      return "r32float";
+    case WGPUTextureFormat_RG16Uint:
+      return "rg16uint";
+    case WGPUTextureFormat_RG16Sint:
+      return "rg16sint";
+    case WGPUTextureFormat_RG16Float:
+      return "rg16float";
+    case WGPUTextureFormat_RGBA8Unorm:
+      return "rgba8unorm";
+    case WGPUTextureFormat_RGBA8UnormSrgb:
+      return "rgba8unorm-srgb";
+    case WGPUTextureFormat_RGBA8Snorm:
+      return "rgba8snorm";
+    case WGPUTextureFormat_RGBA8Uint:
+      return "rgba8uint";
+    case WGPUTextureFormat_RGBA8Sint:
+      return "rgba8sint";
+    case WGPUTextureFormat_BGRA8Unorm:
+      return "bgra8unorm";
+    case WGPUTextureFormat_BGRA8UnormSrgb:
+      return "bgra8unorm-srgb";
+
+    // Packed 32 bit formats
+    case WGPUTextureFormat_RGB9E5Ufloat:
+      return "rgb9e5ufloat";
+    case WGPUTextureFormat_RGB10A2Unorm:
+      return "rgb10a2unorm";
+    case WGPUTextureFormat_RG11B10Ufloat:
+      return "rg11b10ufloat";
+
+    // Normal 64 bit formats
+    case WGPUTextureFormat_RG32Uint:
+      return "rg32uint";
+    case WGPUTextureFormat_RG32Sint:
+      return "rg32sint";
+    case WGPUTextureFormat_RG32Float:
+      return "rg32float";
+    case WGPUTextureFormat_RGBA16Uint:
+      return "rgba16uint";
+    case WGPUTextureFormat_RGBA16Sint:
+      return "rgba16sint";
+    case WGPUTextureFormat_RGBA16Float:
+      return "rgba16float";
+
+    // Normal 128 bit formats
+    case WGPUTextureFormat_RGBA32Uint:
+      return "rgba32uint";
+    case WGPUTextureFormat_RGBA32Sint:
+      return "rgba32sint";
+    case WGPUTextureFormat_RGBA32Float:
+      return "rgba32float";
+
+    // Depth / Stencil formats
+    case WGPUTextureFormat_Depth32Float:
+      return "depth32float";
+    case WGPUTextureFormat_Depth32FloatStencil8:
+      return "depth32float-stencil8";
+    case WGPUTextureFormat_Depth24Plus:
+      return "depth24plus";
+    case WGPUTextureFormat_Depth24PlusStencil8:
+      return "depth24plus-stencil8";
+    case WGPUTextureFormat_Depth16Unorm:
+      return "depth16unorm";
+    case WGPUTextureFormat_Stencil8:
+      return "stencil8";
+
+    // Block Compression (BC) formats
+    case WGPUTextureFormat_BC1RGBAUnorm:
+      return "bc1-rgba-unorm";
+    case WGPUTextureFormat_BC1RGBAUnormSrgb:
+      return "bc1-rgba-unorm-srgb";
+    case WGPUTextureFormat_BC2RGBAUnorm:
+      return "bc2-rgba-unorm";
+    case WGPUTextureFormat_BC2RGBAUnormSrgb:
+      return "bc2-rgba-unorm-srgb";
+    case WGPUTextureFormat_BC3RGBAUnorm:
+      return "bc3-rgba-unorm";
+    case WGPUTextureFormat_BC3RGBAUnormSrgb:
+      return "bc3-rgba-unorm-srgb";
+    case WGPUTextureFormat_BC4RUnorm:
+      return "bc4-r-unorm";
+    case WGPUTextureFormat_BC4RSnorm:
+      return "bc4-r-snorm";
+    case WGPUTextureFormat_BC5RGUnorm:
+      return "bc5-rg-unorm";
+    case WGPUTextureFormat_BC5RGSnorm:
+      return "bc5-rg-snorm";
+    case WGPUTextureFormat_BC6HRGBUfloat:
+      return "bc6h-rgb-ufloat";
+    case WGPUTextureFormat_BC6HRGBFloat:
+      return "bc6h-rgb-float";
+    case WGPUTextureFormat_BC7RGBAUnorm:
+      return "bc7-rgba-unorm";
+    case WGPUTextureFormat_BC7RGBAUnormSrgb:
+      return "bc7-rgba-unorm-srgb";
+
+    // Ericsson Compression (ETC2) formats
+    case WGPUTextureFormat_ETC2RGB8Unorm:
+      return "etc2-rgb8unorm";
+    case WGPUTextureFormat_ETC2RGB8UnormSrgb:
+      return "etc2-rgb8unorm-srgb";
+    case WGPUTextureFormat_ETC2RGB8A1Unorm:
+      return "etc2-rgb8a1unorm";
+    case WGPUTextureFormat_ETC2RGB8A1UnormSrgb:
+      return "etc2-rgb8a1unorm-srgb";
+    case WGPUTextureFormat_ETC2RGBA8Unorm:
+      return "etc2-rgba8unorm";
+    case WGPUTextureFormat_ETC2RGBA8UnormSrgb:
+      return "etc2-rgba8unorm-srgb";
+    case WGPUTextureFormat_EACR11Unorm:
+      return "eac-r11unorm";
+    case WGPUTextureFormat_EACR11Snorm:
+      return "eac-r11snorm";
+    case WGPUTextureFormat_EACRG11Unorm:
+      return "eac-rg11unorm";
+    case WGPUTextureFormat_EACRG11Snorm:
+      return "eac-rg11snorm";
+
+    // Adaptable Scalable Compression (ASTC) formats
+    case WGPUTextureFormat_ASTC4x4Unorm:
+      return "astc-4x4-unorm";
+    case WGPUTextureFormat_ASTC4x4UnormSrgb:
+      return "astc-4x4-unorm-srgb";
+    case WGPUTextureFormat_ASTC5x4Unorm:
+      return "astc-5x4-unorm";
+    case WGPUTextureFormat_ASTC5x4UnormSrgb:
+      return "astc-5x4-unorm-srgb";
+    case WGPUTextureFormat_ASTC5x5Unorm:
+      return "astc-5x5-unorm";
+    case WGPUTextureFormat_ASTC5x5UnormSrgb:
+      return "astc-5x5-unorm-srgb";
+    case WGPUTextureFormat_ASTC6x5Unorm:
+      return "astc-6x5-unorm";
+    case WGPUTextureFormat_ASTC6x5UnormSrgb:
+      return "astc-6x5-unorm-srgb";
+    case WGPUTextureFormat_ASTC6x6Unorm:
+      return "astc-6x6-unorm";
+    case WGPUTextureFormat_ASTC6x6UnormSrgb:
+      return "astc-6x6-unorm-srgb";
+    case WGPUTextureFormat_ASTC8x5Unorm:
+      return "astc-8x5-unorm";
+    case WGPUTextureFormat_ASTC8x5UnormSrgb:
+      return "astc-8x5-unorm-srgb";
+    case WGPUTextureFormat_ASTC8x6Unorm:
+      return "astc-8x6-unorm";
+    case WGPUTextureFormat_ASTC8x6UnormSrgb:
+      return "astc-8x6-unorm-srgb";
+    case WGPUTextureFormat_ASTC8x8Unorm:
+      return "astc-8x8-unorm";
+    case WGPUTextureFormat_ASTC8x8UnormSrgb:
+      return "astc-8x8-unorm-srgb";
+    case WGPUTextureFormat_ASTC10x5Unorm:
+      return "astc-10x5-unorm";
+    case WGPUTextureFormat_ASTC10x5UnormSrgb:
+      return "astc-10x5-unorm-srgb";
+    case WGPUTextureFormat_ASTC10x6Unorm:
+      return "astc-10x6-unorm";
+    case WGPUTextureFormat_ASTC10x6UnormSrgb:
+      return "astc-10x6-unorm-srgb";
+    case WGPUTextureFormat_ASTC10x8Unorm:
+      return "astc-10x8-unorm";
+    case WGPUTextureFormat_ASTC10x8UnormSrgb:
+      return "astc-10x8-unorm-srgb";
+    case WGPUTextureFormat_ASTC10x10Unorm:
+      return "astc-10x10-unorm";
+    case WGPUTextureFormat_ASTC10x10UnormSrgb:
+      return "astc-10x10-unorm-srgb";
+    case WGPUTextureFormat_ASTC12x10Unorm:
+      return "astc-12x10-unorm";
+    case WGPUTextureFormat_ASTC12x10UnormSrgb:
+      return "astc-12x10-unorm-srgb";
+    case WGPUTextureFormat_ASTC12x12Unorm:
+      return "astc-12x12-unorm";
+    case WGPUTextureFormat_ASTC12x12UnormSrgb:
+      return "astc-12x12-unorm-srgb";
+
+    default:
+      NOTREACHED();
+  }
+  return "";
+}
+
 WGPUTextureDimension AsDawnEnum(const V8GPUTextureDimension& webgpu_enum) {
   switch (webgpu_enum.AsEnum()) {
     case V8GPUTextureDimension::Enum::k1d:
@@ -365,6 +596,20 @@
   }
 }
 
+const char* FromDawnEnum(WGPUTextureDimension dawn_enum) {
+  switch (dawn_enum) {
+    case WGPUTextureDimension_1D:
+      return "1d";
+    case WGPUTextureDimension_2D:
+      return "2d";
+    case WGPUTextureDimension_3D:
+      return "3d";
+    case WGPUTextureDimension_Force32:
+      NOTREACHED();
+  }
+  return "";
+}
+
 WGPUTextureViewDimension AsDawnEnum(
     const V8GPUTextureViewDimension& webgpu_enum) {
   switch (webgpu_enum.AsEnum()) {
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.h b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.h
index 4a79520..2a9440b 100644
--- a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.h
+++ b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.h
@@ -72,6 +72,12 @@
 WGPUFrontFace AsDawnEnum(const V8GPUFrontFace& webgpu_enum);
 WGPUTextureAspect AsDawnEnum(const V8GPUTextureAspect& webgpu_enum);
 WGPUErrorFilter AsDawnEnum(const V8GPUErrorFilter& webgpu_enum);
+
+// Convert Dawn enums to WebGPU IDL enums.
+const char* FromDawnEnum(WGPUQueryType dawn_enum);
+const char* FromDawnEnum(WGPUTextureDimension dawn_enum);
+const char* FromDawnEnum(WGPUTextureFormat dawn_enum);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_DAWN_ENUM_CONVERSIONS_H_
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.cc b/third_party/blink/renderer/modules/webgpu/gpu.cc
index caab5d1..cbef3b03 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu.cc
@@ -327,4 +327,9 @@
   contents_.clear();
 }
 
+void GPU::SetDawnControlClientHolderForTesting(
+    scoped_refptr<DawnControlClientHolder> dawn_control_client) {
+  dawn_control_client_ = std::move(dawn_control_client);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.h b/third_party/blink/renderer/modules/webgpu/gpu.h
index fbba4196..2de1f92 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu.h
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
@@ -49,9 +50,9 @@
   HashSet<void*> contents_;
 };
 
-class GPU final : public ScriptWrappable,
-                  public Supplement<NavigatorBase>,
-                  public ExecutionContextLifecycleObserver {
+class MODULES_EXPORT GPU final : public ScriptWrappable,
+                                 public Supplement<NavigatorBase>,
+                                 public ExecutionContextLifecycleObserver {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -89,6 +90,9 @@
     return mappable_buffer_handles_.get();
   }
 
+  void SetDawnControlClientHolderForTesting(
+      scoped_refptr<DawnControlClientHolder> dawn_control_client);
+
  private:
   void OnRequestAdapterCallback(ScriptState* script_state,
                                 const GPURequestAdapterOptions* options,
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
index eddfc74..32cddab 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
@@ -210,6 +210,14 @@
   mappable_buffer_handles_ = nullptr;
 }
 
+uint64_t GPUBuffer::size() const {
+  return size_;
+}
+
+uint32_t GPUBuffer::usage() const {
+  return GetProcs().bufferGetUsage(GetHandle());
+}
+
 ScriptPromise GPUBuffer::MapAsyncImpl(ScriptState* script_state,
                                       uint32_t mode,
                                       uint64_t offset,
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.h b/third_party/blink/renderer/modules/webgpu/gpu_buffer.h
index 13191c0..d5d8f00 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.h
@@ -54,6 +54,8 @@
                                  ExceptionState& exception_state);
   void unmap(ScriptState* script_state);
   void destroy(ScriptState* script_state);
+  uint64_t size() const;
+  uint32_t usage() const;
 
   void DetachMappedArrayBuffers(v8::Isolate* isolate);
 
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.idl b/third_party/blink/renderer/modules/webgpu/gpu_buffer.idl
index 33ad997..2305ef7 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.idl
@@ -17,5 +17,8 @@
         optional GPUSize64 size);
     [CallWith=ScriptState] void unmap();
     [CallWith=ScriptState] void destroy();
+
+    readonly attribute GPUSize64 size;
+    readonly attribute GPUBufferUsageFlags usage;
 };
 GPUBuffer includes GPUObjectBase;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_context_lost_test.cc b/third_party/blink/renderer/modules/webgpu/gpu_context_lost_test.cc
new file mode 100644
index 0000000..1063295a
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/gpu_context_lost_test.cc
@@ -0,0 +1,229 @@
+// 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 "base/callback.h"
+#include "base/run_loop.h"
+#include "base/test/mock_callback.h"
+#include "gpu/command_buffer/client/webgpu_interface_stub.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h"
+
+namespace blink {
+
+namespace {
+
+class WebGPUContextProviderForTest
+    : public WebGraphicsContext3DProviderForTests {
+ public:
+  explicit WebGPUContextProviderForTest(
+      base::MockCallback<base::OnceClosure>* destruction_callback)
+      : WebGraphicsContext3DProviderForTests(
+            std::make_unique<gpu::webgpu::WebGPUInterfaceStub>()),
+        destruction_callback_(destruction_callback) {}
+  ~WebGPUContextProviderForTest() override {
+    if (destruction_callback_) {
+      destruction_callback_->Run();
+    }
+  }
+
+  static WebGPUContextProviderForTest* From(
+      scoped_refptr<DawnControlClientHolder>& dawn_control_client) {
+    return static_cast<WebGPUContextProviderForTest*>(
+        dawn_control_client->GetContextProviderWeakPtr()->ContextProvider());
+  }
+
+  void ClearDestructionCallback() { destruction_callback_ = nullptr; }
+
+  void SetLostContextCallback(
+      base::RepeatingClosure lost_context_callback) override {
+    lost_context_callback_ = std::move(lost_context_callback);
+  }
+
+  void CallLostContextCallback() { lost_context_callback_.Run(); }
+
+ private:
+  base::MockCallback<base::OnceClosure>* destruction_callback_;
+  base::RepeatingClosure lost_context_callback_;
+};
+
+class WebGPUContextLostTest : public testing::Test {
+ protected:
+  void SetUp() override { page_ = std::make_unique<DummyPageHolder>(); }
+
+  std::tuple<ExecutionContext*, GPU*> SetUpGPU(V8TestingScope* v8_test_scope) {
+    ExecutionContext* execution_context =
+        ExecutionContext::From(v8_test_scope->GetScriptState());
+
+    Navigator* navigator = page_->GetFrame().DomWindow()->navigator();
+    GPU* gpu = MakeGarbageCollected<GPU>(*navigator);
+    return std::make_tuple(execution_context, gpu);
+  }
+
+  std::unique_ptr<DummyPageHolder> page_;
+};
+
+// Test that the context provider is destructed after the last reference to
+// its owning DawnControlClientHolder is dropped.
+TEST_F(WebGPUContextLostTest, DestructedAfterLastRefDropped) {
+  V8TestingScope v8_test_scope;
+  ExecutionContext* execution_context =
+      ExecutionContext::From(v8_test_scope.GetScriptState());
+
+  base::MockCallback<base::OnceClosure> destruction_callback;
+  auto context_provider =
+      std::make_unique<WebGPUContextProviderForTest>(&destruction_callback);
+
+  auto dawn_control_client = DawnControlClientHolder::Create(
+      std::move(context_provider),
+      execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+  // Drop the last reference to the DawnControlClientHolder which will
+  // now destroy the context provider.
+  EXPECT_CALL(destruction_callback, Run()).Times(1);
+  dawn_control_client = nullptr;
+}
+
+// Test that the GPU lost context callback marks the context lost, but does not
+// destruct it.
+TEST_F(WebGPUContextLostTest, GPULostContext) {
+  V8TestingScope v8_test_scope;
+  auto [execution_context, gpu] = SetUpGPU(&v8_test_scope);
+
+  base::MockCallback<base::OnceClosure> destruction_callback;
+  auto context_provider =
+      std::make_unique<WebGPUContextProviderForTest>(&destruction_callback);
+
+  auto dawn_control_client = DawnControlClientHolder::Create(
+      std::move(context_provider),
+      execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+  gpu->SetDawnControlClientHolderForTesting(dawn_control_client);
+
+  // Trigger the lost context callback, but the context should not be destroyed.
+  EXPECT_CALL(destruction_callback, Run()).Times(0);
+  WebGPUContextProviderForTest::From(dawn_control_client)
+      ->CallLostContextCallback();
+  testing::Mock::VerifyAndClear(&destruction_callback);
+
+  // The context should be marked lost.
+  EXPECT_TRUE(dawn_control_client->IsContextLost());
+
+  // The context provider should still be live.
+  auto context_provider_weak_ptr =
+      dawn_control_client->GetContextProviderWeakPtr();
+  EXPECT_NE(context_provider_weak_ptr, nullptr);
+
+  // Clear the destruction callback since it is stack-allocated in this frame.
+  static_cast<WebGPUContextProviderForTest*>(
+      context_provider_weak_ptr->ContextProvider())
+      ->ClearDestructionCallback();
+}
+
+// Test that the GPU lost context callback marks the context lost, and then when
+// the context is recreated, the context still lives until the previous
+// DawnControlClientHolder is destroyed.
+TEST_F(WebGPUContextLostTest, RecreatedAfterGPULostContext) {
+  V8TestingScope v8_test_scope;
+  auto [execution_context, gpu] = SetUpGPU(&v8_test_scope);
+
+  base::MockCallback<base::OnceClosure> destruction_callback;
+  auto context_provider =
+      std::make_unique<WebGPUContextProviderForTest>(&destruction_callback);
+
+  auto dawn_control_client = DawnControlClientHolder::Create(
+      std::move(context_provider),
+      execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+  gpu->SetDawnControlClientHolderForTesting(dawn_control_client);
+
+  // Trigger the lost context callback, but the context should not be destroyed.
+  EXPECT_CALL(destruction_callback, Run()).Times(0);
+  WebGPUContextProviderForTest::From(dawn_control_client)
+      ->CallLostContextCallback();
+  testing::Mock::VerifyAndClear(&destruction_callback);
+
+  // The context should be marked lost.
+  EXPECT_TRUE(dawn_control_client->IsContextLost());
+
+  // The context provider should still be live.
+  auto context_provider_weak_ptr =
+      dawn_control_client->GetContextProviderWeakPtr();
+  EXPECT_NE(context_provider_weak_ptr, nullptr);
+
+  // Make a new context provider and DawnControlClientHolder
+  base::MockCallback<base::OnceClosure> destruction_callback2;
+  auto context_provider2 =
+      std::make_unique<WebGPUContextProviderForTest>(&destruction_callback2);
+
+  auto dawn_control_client2 = DawnControlClientHolder::Create(
+      std::move(context_provider2),
+      execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+  // Set the new context, but the previous context should still not be
+  // destroyed.
+  EXPECT_CALL(destruction_callback, Run()).Times(0);
+  gpu->SetDawnControlClientHolderForTesting(dawn_control_client2);
+  testing::Mock::VerifyAndClear(&destruction_callback);
+
+  // Drop the last reference to the previous DawnControlClientHolder which will
+  // now destroy the previous context provider.
+  EXPECT_CALL(destruction_callback, Run()).Times(1);
+  dawn_control_client = nullptr;
+  testing::Mock::VerifyAndClear(&destruction_callback);
+
+  // Clear the destruction callback since it is stack-allocated in this frame.
+  static_cast<WebGPUContextProviderForTest*>(
+      dawn_control_client2->GetContextProviderWeakPtr()->ContextProvider())
+      ->ClearDestructionCallback();
+}
+
+// Test that ContextDestroyed lifecycle event destructs the context.
+TEST_F(WebGPUContextLostTest, ContextDestroyed) {
+  V8TestingScope v8_test_scope;
+  auto [execution_context, gpu] = SetUpGPU(&v8_test_scope);
+
+  base::MockCallback<base::OnceClosure> destruction_callback;
+  auto context_provider =
+      std::make_unique<WebGPUContextProviderForTest>(&destruction_callback);
+
+  auto dawn_control_client = DawnControlClientHolder::Create(
+      std::move(context_provider),
+      execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+  gpu->SetDawnControlClientHolderForTesting(dawn_control_client);
+
+  // Trigger the context destroyed lifecycle event. The context should not be
+  // destroyed yet.
+  EXPECT_CALL(destruction_callback, Run()).Times(0);
+  gpu->ContextDestroyed();
+  testing::Mock::VerifyAndClear(&destruction_callback);
+
+  // The context should be marked lost.
+  EXPECT_TRUE(dawn_control_client->IsContextLost());
+
+  // Getting the context provider should return null.
+  EXPECT_EQ(dawn_control_client->GetContextProviderWeakPtr(), nullptr);
+
+  // The context is destructed in a posted task with a fresh callstack to avoid
+  // re-entrancy issues. Expectations should resolve by the end of the next
+  // task.
+  EXPECT_CALL(destruction_callback, Run()).Times(1);
+  base::RunLoop loop;
+  execution_context->GetTaskRunner(TaskType::kWebGPU)
+      ->PostTask(FROM_HERE, loop.QuitClosure());
+  loop.Run();
+  testing::Mock::VerifyAndClear(&destruction_callback);
+}
+
+}  // namespace
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc b/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc
index 17e76e7..b6d311e 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc
@@ -52,4 +52,12 @@
   GetProcs().querySetDestroy(GetHandle());
 }
 
+String GPUQuerySet::type() const {
+  return FromDawnEnum(GetProcs().querySetGetType(GetHandle()));
+}
+
+uint32_t GPUQuerySet::count() const {
+  return GetProcs().querySetGetCount(GetHandle());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_query_set.h b/third_party/blink/renderer/modules/webgpu/gpu_query_set.h
index 91b7fb83..cd83c12d 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_query_set.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_query_set.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_QUERY_SET_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_QUERY_SET_H_
 
+#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_query_type.h"
 #include "third_party/blink/renderer/modules/webgpu/dawn_object.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 
@@ -25,6 +26,8 @@
 
   // gpu_queryset.idl
   void destroy();
+  String type() const;
+  uint32_t count() const;
 
  private:
   void setLabelImpl(const String& value) override {
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_query_set.idl b/third_party/blink/renderer/modules/webgpu/gpu_query_set.idl
index c37c47a..c86892c 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_query_set.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_query_set.idl
@@ -9,5 +9,8 @@
     SecureContext
 ] interface GPUQuerySet {
     void destroy();
+
+    readonly attribute GPUQueryType type;
+    readonly attribute GPUSize32 count;
 };
 GPUQuerySet includes GPUObjectBase;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture.cc b/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
index fdb261a0..8b82771 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
@@ -293,4 +293,36 @@
   mailbox_texture_.reset();
 }
 
+uint32_t GPUTexture::width() const {
+  return GetProcs().textureGetWidth(GetHandle());
+}
+
+uint32_t GPUTexture::height() const {
+  return GetProcs().textureGetHeight(GetHandle());
+}
+
+uint32_t GPUTexture::depthOrArrayLayers() const {
+  return GetProcs().textureGetDepthOrArrayLayers(GetHandle());
+}
+
+uint32_t GPUTexture::mipLevelCount() const {
+  return GetProcs().textureGetMipLevelCount(GetHandle());
+}
+
+uint32_t GPUTexture::sampleCount() const {
+  return GetProcs().textureGetSampleCount(GetHandle());
+}
+
+String GPUTexture::dimension() const {
+  return FromDawnEnum(GetProcs().textureGetDimension(GetHandle()));
+}
+
+String GPUTexture::format() const {
+  return FromDawnEnum(GetProcs().textureGetFormat(GetHandle()));
+}
+
+uint32_t GPUTexture::usage() const {
+  return GetProcs().textureGetUsage(GetHandle());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture.h b/third_party/blink/renderer/modules/webgpu/gpu_texture.h
index af9ce11..4f03701a 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_texture.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_texture.h
@@ -48,6 +48,14 @@
   GPUTextureView* createView(const GPUTextureViewDescriptor* webgpu_desc,
                              ExceptionState& exception_state);
   void destroy();
+  uint32_t width() const;
+  uint32_t height() const;
+  uint32_t depthOrArrayLayers() const;
+  uint32_t mipLevelCount() const;
+  uint32_t sampleCount() const;
+  String dimension() const;
+  String format() const;
+  uint32_t usage() const;
 
   WGPUTextureDimension Dimension() { return dimension_; }
   WGPUTextureFormat Format() { return format_; }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture.idl b/third_party/blink/renderer/modules/webgpu/gpu_texture.idl
index e390105..3bd1001 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_texture.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_texture.idl
@@ -10,5 +10,14 @@
 ] interface GPUTexture {
     [RaisesException] GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});
     void destroy();
+
+    readonly attribute GPUIntegerCoordinate width;
+    readonly attribute GPUIntegerCoordinate height;
+    readonly attribute GPUIntegerCoordinate depthOrArrayLayers;
+    readonly attribute GPUIntegerCoordinate mipLevelCount;
+    readonly attribute GPUSize32 sampleCount;
+    readonly attribute GPUTextureDimension dimension;
+    readonly attribute GPUTextureFormat format;
+    readonly attribute GPUTextureUsageFlags usage;
 };
 GPUTexture includes GPUObjectBase;
diff --git a/third_party/blink/renderer/modules/webmidi/midi_input.cc b/third_party/blink/renderer/modules/webmidi/midi_input.cc
index 043e78d..363b2f96 100644
--- a/third_party/blink/renderer/modules/webmidi/midi_input.cc
+++ b/third_party/blink/renderer/modules/webmidi/midi_input.cc
@@ -30,12 +30,12 @@
 
 #include "third_party/blink/renderer/modules/webmidi/midi_input.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/modules/webmidi/midi_access.h"
 #include "third_party/blink/renderer/modules/webmidi/midi_message_event.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -90,7 +90,7 @@
   if (data[0] == 0xf0 && !midiAccess()->sysexEnabled())
     return;
   DOMUint8Array* array =
-      DOMUint8Array::Create(data, SafeCast<unsigned>(length));
+      DOMUint8Array::Create(data, base::checked_cast<unsigned>(length));
   DispatchEvent(*MakeGarbageCollected<MIDIMessageEvent>(time_stamp, array));
 
   UseCounter::Count(GetExecutionContext(), WebFeature::kMIDIMessageEvent);
diff --git a/third_party/blink/renderer/platform/audio/equal_power_panner.cc b/third_party/blink/renderer/platform/audio/equal_power_panner.cc
index 21e8d02..ab715ce 100644
--- a/third_party/blink/renderer/platform/audio/equal_power_panner.cc
+++ b/third_party/blink/renderer/platform/audio/equal_power_panner.cc
@@ -47,7 +47,7 @@
   DCHECK_GE(input_bus->NumberOfChannels(), 1u);
   DCHECK_LE(input_bus->NumberOfChannels(), 2u);
 
-  unsigned number_of_input_channels = input_bus->NumberOfChannels();
+  const unsigned number_of_input_channels = input_bus->NumberOfChannels();
 
   DCHECK(output_bus);
   DCHECK_EQ(output_bus->NumberOfChannels(), 2u);
@@ -70,10 +70,10 @@
 
   // Alias the azimuth ranges behind us to in front of us:
   // -90 -> -180 to -90 -> 0 and 90 -> 180 to 90 -> 0
-  if (azimuth < -90) {
-    azimuth = -180 - azimuth;
-  } else if (azimuth > 90) {
-    azimuth = 180 - azimuth;
+  if (azimuth < -90.0) {
+    azimuth = -180.0 - azimuth;
+  } else if (azimuth > 90.0) {
+    azimuth = 180.0 - azimuth;
   }
 
   double desired_pan_position;
@@ -83,18 +83,18 @@
   if (number_of_input_channels == 1) {  // For mono source case.
     // Pan smoothly from left to right with azimuth going from -90 -> +90
     // degrees.
-    desired_pan_position = (azimuth + 90) / 180;
+    desired_pan_position = (azimuth + 90.0) / 180.0;
   } else {               // For stereo source case.
     if (azimuth <= 0) {  // from -90 -> 0
       // sourceL -> destL and "equal-power pan" sourceR as in mono case
       // by transforming the "azimuth" value from -90 -> 0 degrees into the
       // range -90 -> +90.
-      desired_pan_position = (azimuth + 90) / 90;
+      desired_pan_position = (azimuth + 90.0) / 90.0;
     } else {  // from 0 -> +90
       // sourceR -> destR and "equal-power pan" sourceL as in mono case
       // by transforming the "azimuth" value from 0 -> +90 degrees into the
       // range -90 -> +90.
-      desired_pan_position = azimuth / 90;
+      desired_pan_position = azimuth / 90.0;
     }
   }
 
@@ -105,7 +105,7 @@
 
   if (number_of_input_channels == 1) {  // For mono source case.
     while (n--) {
-      float input_l = *source_l++;
+      const float input_l = *source_l++;
 
       *destination_l++ = static_cast<float>(input_l * desired_gain_l);
       *destination_r++ = static_cast<float>(input_l * desired_gain_r);
@@ -113,8 +113,8 @@
   } else {               // For stereo source case.
     if (azimuth <= 0) {  // from -90 -> 0
       while (n--) {
-        float input_l = *source_l++;
-        float input_r = *source_r++;
+        const float input_l = *source_l++;
+        const float input_r = *source_r++;
 
         *destination_l++ =
             static_cast<float>(input_l + input_r * desired_gain_l);
@@ -122,8 +122,8 @@
       }
     } else {  // from 0 -> +90
       while (n--) {
-        float input_l = *source_l++;
-        float input_r = *source_r++;
+        const float input_l = *source_l++;
+        const float input_r = *source_r++;
 
         *destination_l++ = static_cast<float>(input_l * desired_gain_l);
         *destination_r++ =
@@ -133,45 +133,6 @@
   }
 }
 
-void EqualPowerPanner::CalculateDesiredGain(double& desired_gain_l,
-                                            double& desired_gain_r,
-                                            double azimuth,
-                                            int number_of_input_channels) {
-  // Clamp azimuth to allowed range of -180 -> +180.
-  azimuth = ClampTo(azimuth, -180.0, 180.0);
-
-  // Alias the azimuth ranges behind us to in front of us:
-  // -90 -> -180 to -90 -> 0 and 90 -> 180 to 90 -> 0
-  if (azimuth < -90) {
-    azimuth = -180 - azimuth;
-  } else if (azimuth > 90) {
-    azimuth = 180 - azimuth;
-  }
-
-  double desired_pan_position;
-
-  if (number_of_input_channels == 1) {  // For mono source case.
-    // Pan smoothly from left to right with azimuth going from -90 -> +90
-    // degrees.
-    desired_pan_position = (azimuth + 90) / 180;
-  } else {               // For stereo source case.
-    if (azimuth <= 0) {  // from -90 -> 0
-      // sourceL -> destL and "equal-power pan" sourceR as in mono case
-      // by transforming the "azimuth" value from -90 -> 0 degrees into the
-      // range -90 -> +90.
-      desired_pan_position = (azimuth + 90) / 90;
-    } else {  // from 0 -> +90
-      // sourceR -> destR and "equal-power pan" sourceL as in mono case
-      // by transforming the "azimuth" value from 0 -> +90 degrees into the
-      // range -90 -> +90.
-      desired_pan_position = azimuth / 90;
-    }
-  }
-
-  desired_gain_l = fdlibm::cos(kPiOverTwoDouble * desired_pan_position);
-  desired_gain_r = fdlibm::sin(kPiOverTwoDouble * desired_pan_position);
-}
-
 void EqualPowerPanner::PanWithSampleAccurateValues(
     double* azimuth,
     double* /*elevation*/,
@@ -184,7 +145,7 @@
   DCHECK_GE(input_bus->NumberOfChannels(), 1u);
   DCHECK_LE(input_bus->NumberOfChannels(), 2u);
 
-  unsigned number_of_input_channels = input_bus->NumberOfChannels();
+  const unsigned number_of_input_channels = input_bus->NumberOfChannels();
 
   DCHECK(output_bus);
   DCHECK_EQ(output_bus->NumberOfChannels(), 2u);
@@ -209,7 +170,7 @@
     for (int k = 0; k < n; ++k) {
       double desired_gain_l;
       double desired_gain_r;
-      float input_l = *source_l++;
+      const float input_l = *source_l++;
 
       CalculateDesiredGain(desired_gain_l, desired_gain_r, azimuth[k],
                            number_of_input_channels);
@@ -224,14 +185,14 @@
       CalculateDesiredGain(desired_gain_l, desired_gain_r, azimuth[k],
                            number_of_input_channels);
       if (azimuth[k] <= 0) {  // from -90 -> 0
-        float input_l = *source_l++;
-        float input_r = *source_r++;
+        const float input_l = *source_l++;
+        const float input_r = *source_r++;
         *destination_l++ =
             static_cast<float>(input_l + input_r * desired_gain_l);
         *destination_r++ = static_cast<float>(input_r * desired_gain_r);
       } else {  // from 0 -> +90
-        float input_l = *source_l++;
-        float input_r = *source_r++;
+        const float input_l = *source_l++;
+        const float input_r = *source_r++;
         *destination_l++ = static_cast<float>(input_l * desired_gain_l);
         *destination_r++ =
             static_cast<float>(input_r + input_l * desired_gain_r);
@@ -240,4 +201,43 @@
   }
 }
 
+void EqualPowerPanner::CalculateDesiredGain(double& desired_gain_l,
+                                            double& desired_gain_r,
+                                            double azimuth,
+                                            int number_of_input_channels) {
+  // Clamp azimuth to allowed range of -180 -> +180.
+  azimuth = ClampTo(azimuth, -180.0, 180.0);
+
+  // Alias the azimuth ranges behind us to in front of us:
+  // -90 -> -180 to -90 -> 0 and 90 -> 180 to 90 -> 0
+  if (azimuth < -90.0) {
+    azimuth = -180.0 - azimuth;
+  } else if (azimuth > 90.0) {
+    azimuth = 180.0 - azimuth;
+  }
+
+  double desired_pan_position;
+
+  if (number_of_input_channels == 1) {  // For mono source case.
+    // Pan smoothly from left to right with azimuth going from -90 -> +90
+    // degrees.
+    desired_pan_position = (azimuth + 90.0) / 180.0;
+  } else {               // For stereo source case.
+    if (azimuth <= 0) {  // from -90 -> 0
+      // sourceL -> destL and "equal-power pan" sourceR as in mono case
+      // by transforming the "azimuth" value from -90 -> 0 degrees into the
+      // range -90 -> +90.
+      desired_pan_position = (azimuth + 90.0) / 90.0;
+    } else {  // from 0 -> +90
+      // sourceR -> destR and "equal-power pan" sourceL as in mono case
+      // by transforming the "azimuth" value from 0 -> +90 degrees into the
+      // range -90 -> +90.
+      desired_pan_position = azimuth / 90.0;
+    }
+  }
+
+  desired_gain_l = fdlibm::cos(kPiOverTwoDouble * desired_pan_position);
+  desired_gain_r = fdlibm::sin(kPiOverTwoDouble * desired_pan_position);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/audio/equal_power_panner.h b/third_party/blink/renderer/platform/audio/equal_power_panner.h
index 001e17f..ac060836b 100644
--- a/third_party/blink/renderer/platform/audio/equal_power_panner.h
+++ b/third_party/blink/renderer/platform/audio/equal_power_panner.h
@@ -59,7 +59,7 @@
   void CalculateDesiredGain(double& desired_gain_l,
                             double& desired_gain_r,
                             double azimuth,
-                            int number_of_channels);
+                            int number_of_input_channels);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database.cc b/third_party/blink/renderer/platform/audio/hrtf_database.cc
index 302e1c9..0d0b85d72 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_database.cc
+++ b/third_party/blink/renderer/platform/audio/hrtf_database.cc
@@ -87,7 +87,7 @@
                                                   HRTFKernel*& kernel_l,
                                                   HRTFKernel*& kernel_r,
                                                   double& frame_delay_l,
-                                                  double& frame_delay_r) {
+                                                  double& frame_delay_r) const {
   unsigned elevation_index = IndexFromElevationAngle(elevation_angle);
   SECURITY_DCHECK(elevation_index < elevations_.size());
   SECURITY_DCHECK(elevations_.size() > 0);
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database.h b/third_party/blink/renderer/platform/audio/hrtf_database.h
index 65522c3..0def11a2 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_database.h
+++ b/third_party/blink/renderer/platform/audio/hrtf_database.h
@@ -30,6 +30,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_HRTF_DATABASE_H_
 
 #include <memory>
+
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/platform/audio/hrtf_elevation.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -62,7 +63,7 @@
                                       HRTFKernel*& kernel_l,
                                       HRTFKernel*& kernel_r,
                                       double& frame_delay_l,
-                                      double& frame_delay_r);
+                                      double& frame_delay_r) const;
 
   // Returns the number of different azimuth angles.
   static unsigned NumberOfAzimuths() {
diff --git a/third_party/blink/renderer/platform/audio/hrtf_elevation.cc b/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
index 63e9695..15a33bd 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
+++ b/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
@@ -36,38 +36,68 @@
 #include "base/memory/ptr_util.h"
 #include "base/synchronization/lock.h"
 #include "third_party/blink/renderer/platform/audio/audio_bus.h"
+#include "third_party/blink/renderer/platform/audio/hrtf_database.h"
 #include "third_party/blink/renderer/platform/audio/hrtf_panner.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
 
 namespace blink {
 
-const unsigned HRTFElevation::kAzimuthSpacing = 15;
-const unsigned HRTFElevation::kNumberOfRawAzimuths = 360 / kAzimuthSpacing;
-const unsigned HRTFElevation::kInterpolationFactor = 8;
-const unsigned HRTFElevation::kNumberOfTotalAzimuths =
-    kNumberOfRawAzimuths * kInterpolationFactor;
+namespace {
 
 // Total number of components of an HRTF database.
-const size_t kTotalNumberOfResponses = 240;
+constexpr size_t kTotalNumberOfResponses = 240;
 
 // Number of frames in an individual impulse response.
-const size_t kResponseFrameSize = 256;
+constexpr size_t kResponseFrameSize = 256;
 
 // Sample-rate of the spatialization impulse responses as stored in the resource
 // file.  The impulse responses may be resampled to a different sample-rate
 // (depending on the audio hardware) when they are loaded.
-const float kResponseSampleRate = 44100;
+constexpr float kResponseSampleRate = 44100;
 
 // This table maps the index into the elevation table with the corresponding
 // angle. See https://bugs.webkit.org/show_bug.cgi?id=98294#c9 for the
 // elevation angles and their order in the concatenated response.
-const int kElevationIndexTableSize = 10;
-const int kElevationIndexTable[kElevationIndexTableSize] = {
+constexpr int kElevationIndexTableSize = 10;
+constexpr int kElevationIndexTable[kElevationIndexTableSize] = {
     0, 15, 30, 45, 60, 75, 90, 315, 330, 345};
 
+// The range of elevations for the IRCAM impulse responses varies depending on
+// azimuth, but the minimum elevation appears to always be -45.
+//
+// Here's how it goes:
+constexpr int kMaxElevations[] = {
+    //  Azimuth
+    //
+    90,  // 0
+    45,  // 15
+    60,  // 30
+    45,  // 45
+    75,  // 60
+    45,  // 75
+    60,  // 90
+    45,  // 105
+    75,  // 120
+    45,  // 135
+    60,  // 150
+    45,  // 165
+    75,  // 180
+    45,  // 195
+    60,  // 210
+    45,  // 225
+    75,  // 240
+    45,  // 255
+    60,  // 270
+    45,  // 285
+    75,  // 300
+    45,  // 315
+    60,  // 330
+    45   // 345
+};
+
 // Lazily load a concatenated HRTF database for given subject and store it in a
 // local hash table to ensure quick efficient future retrievals.
-static scoped_refptr<AudioBus> GetConcatenatedImpulseResponsesForSubject(
+scoped_refptr<AudioBus> GetConcatenatedImpulseResponsesForSubject(
     int subject_resource_id) {
   typedef HashMap<int, scoped_refptr<AudioBus>> AudioBusMap;
   DEFINE_THREAD_SAFE_STATIC_LOCAL(AudioBusMap, audio_bus_map, ());
@@ -98,6 +128,8 @@
   return bus;
 }
 
+}  // namespace
+
 bool HRTFElevation::CalculateKernelsForAzimuthElevation(
     int azimuth,
     int elevation,
@@ -116,7 +148,7 @@
   DCHECK_LE(elevation, 90);
   DCHECK_EQ((elevation / 15) * 15, elevation);
 
-  int positive_elevation = elevation < 0 ? elevation + 360 : elevation;
+  const int positive_elevation = elevation < 0 ? elevation + 360 : elevation;
 
   scoped_refptr<AudioBus> bus(
       GetConcatenatedImpulseResponsesForSubject(subject_resource_id));
@@ -190,39 +222,6 @@
   return true;
 }
 
-// The range of elevations for the IRCAM impulse responses varies depending on
-// azimuth, but the minimum elevation appears to always be -45.
-//
-// Here's how it goes:
-static int g_max_elevations[] = {
-    //  Azimuth
-    //
-    90,  // 0
-    45,  // 15
-    60,  // 30
-    45,  // 45
-    75,  // 60
-    45,  // 75
-    60,  // 90
-    45,  // 105
-    75,  // 120
-    45,  // 135
-    60,  // 150
-    45,  // 165
-    75,  // 180
-    45,  // 195
-    60,  // 210
-    45,  // 225
-    75,  // 240
-    45,  // 255
-    60,  // 270
-    45,  // 285
-    75,  // 300
-    45,  // 315
-    60,  // 330
-    45   //  345
-};
-
 std::unique_ptr<HRTFElevation> HRTFElevation::CreateForSubject(
     int subject_resource_id,
     int elevation,
@@ -240,10 +239,10 @@
   int interpolated_index = 0;
   for (unsigned raw_index = 0; raw_index < kNumberOfRawAzimuths; ++raw_index) {
     // Don't let elevation exceed maximum for this azimuth.
-    int max_elevation = g_max_elevations[raw_index];
-    int actual_elevation = std::min(elevation, max_elevation);
+    const int max_elevation = kMaxElevations[raw_index];
+    const int actual_elevation = std::min(elevation, max_elevation);
 
-    bool success = CalculateKernelsForAzimuthElevation(
+    const bool success = CalculateKernelsForAzimuthElevation(
         raw_index * kAzimuthSpacing, actual_elevation, sample_rate,
         subject_resource_id, kernel_list_l->at(interpolated_index),
         kernel_list_r->at(interpolated_index));
@@ -307,8 +306,8 @@
   }
 
   // Interpolate elevation angle.
-  double angle = (1.0 - x) * hrtf_elevation1->ElevationAngle() +
-                 x * hrtf_elevation2->ElevationAngle();
+  const double angle = (1.0 - x) * hrtf_elevation1->ElevationAngle() +
+                       x * hrtf_elevation2->ElevationAngle();
 
   std::unique_ptr<HRTFElevation> hrtf_elevation = base::WrapUnique(
       new HRTFElevation(std::move(kernel_list_l), std::move(kernel_list_r),
@@ -325,7 +324,7 @@
   DCHECK_GE(azimuth_blend, 0.0);
   DCHECK_LT(azimuth_blend, 1.0);
 
-  unsigned num_kernels = kernel_list_l_->size();
+  const unsigned num_kernels = kernel_list_l_->size();
 
   DCHECK_LT(azimuth_index, num_kernels);
 
@@ -336,9 +335,9 @@
   frame_delay_l = kernel_list_l_->at(azimuth_index)->FrameDelay();
   frame_delay_r = kernel_list_r_->at(azimuth_index)->FrameDelay();
 
-  int azimuth_index2 = (azimuth_index + 1) % num_kernels;
-  double frame_delay2l = kernel_list_l_->at(azimuth_index2)->FrameDelay();
-  double frame_delay2r = kernel_list_r_->at(azimuth_index2)->FrameDelay();
+  const int azimuth_index2 = (azimuth_index + 1) % num_kernels;
+  const double frame_delay2l = kernel_list_l_->at(azimuth_index2)->FrameDelay();
+  const double frame_delay2r = kernel_list_r_->at(azimuth_index2)->FrameDelay();
 
   // Linearly interpolate delays.
   frame_delay_l =
diff --git a/third_party/blink/renderer/platform/audio/hrtf_elevation.h b/third_party/blink/renderer/platform/audio/hrtf_elevation.h
index e79cc62a1..fc09bbe 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_elevation.h
+++ b/third_party/blink/renderer/platform/audio/hrtf_elevation.h
@@ -30,6 +30,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_HRTF_ELEVATION_H_
 
 #include <memory>
+
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/platform/audio/hrtf_kernel.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
@@ -85,17 +86,18 @@
                              double& frame_delay_r);
 
   // Spacing, in degrees, between every azimuth loaded from resource.
-  static const unsigned kAzimuthSpacing;
+  static constexpr unsigned kAzimuthSpacing = 15;
 
   // Number of azimuths loaded from resource.
-  static const unsigned kNumberOfRawAzimuths;
+  static constexpr unsigned kNumberOfRawAzimuths = 360 / kAzimuthSpacing;
 
   // Interpolates by this factor to get the total number of azimuths from every
   // azimuth loaded from resource.
-  static const unsigned kInterpolationFactor;
+  static constexpr unsigned kInterpolationFactor = 8;
 
   // Total number of azimuths after interpolation.
-  static const unsigned kNumberOfTotalAzimuths;
+  static constexpr unsigned kNumberOfTotalAzimuths =
+      kNumberOfRawAzimuths * kInterpolationFactor;
 
   // Given a specific azimuth and elevation angle, returns the left and right
   // HRTFKernel.
diff --git a/third_party/blink/renderer/platform/audio/hrtf_kernel.cc b/third_party/blink/renderer/platform/audio/hrtf_kernel.cc
index 0adef94..fbe16b4 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_kernel.cc
+++ b/third_party/blink/renderer/platform/audio/hrtf_kernel.cc
@@ -37,13 +37,15 @@
 
 namespace blink {
 
+namespace {
+
 // Takes the input AudioChannel as an input impulse response and calculates the
 // average group delay.  This represents the initial delay before the most
 // energetic part of the impulse response.  The sample-frame delay is removed
 // from the impulseP impulse response, and this value  is returned.  The length
 // of the passed in AudioChannel must be a power of 2.
-static float ExtractAverageGroupDelay(AudioChannel* channel,
-                                      unsigned analysis_fft_size) {
+float ExtractAverageGroupDelay(AudioChannel* channel,
+                               unsigned analysis_fft_size) {
   DCHECK(channel);
 
   float* impulse_p = channel->MutableData();
@@ -57,13 +59,15 @@
   FFTFrame estimation_frame(analysis_fft_size);
   estimation_frame.DoFFT(impulse_p);
 
-  float frame_delay =
+  const float frame_delay =
       ClampTo<float>(estimation_frame.ExtractAverageGroupDelay());
   estimation_frame.DoInverseFFT(impulse_p);
 
   return frame_delay;
 }
 
+}  // namespace
+
 HRTFKernel::HRTFKernel(AudioChannel* channel,
                        unsigned fft_size,
                        float sample_rate)
@@ -74,15 +78,16 @@
   frame_delay_ = ExtractAverageGroupDelay(channel, fft_size / 2);
 
   float* impulse_response = channel->MutableData();
-  uint32_t response_length = channel->length();
+  const uint32_t response_length = channel->length();
 
   // We need to truncate to fit into 1/2 the FFT size (with zero padding) in
   // order to do proper convolution.
   // Truncate if necessary to max impulse response length allowed by FFT.
-  unsigned truncated_response_length = std::min(response_length, fft_size / 2);
+  const unsigned truncated_response_length =
+      std::min(response_length, fft_size / 2);
 
   // Quick fade-out (apply window) at truncation point
-  unsigned number_of_fade_out_frames = static_cast<unsigned>(
+  const unsigned number_of_fade_out_frames = static_cast<unsigned>(
       sample_rate / 4410);  // 10 sample-frames @44.1KHz sample-rate
   DCHECK_LT(number_of_fade_out_frames, truncated_response_length);
   for (unsigned i = truncated_response_length - number_of_fade_out_frames;
@@ -108,11 +113,11 @@
   DCHECK_LT(x, 1.0);
   x = ClampTo(x, 0.0f, 1.0f);
 
-  float sample_rate1 = kernel1->SampleRate();
-  float sample_rate2 = kernel2->SampleRate();
+  const float sample_rate1 = kernel1->SampleRate();
+  const float sample_rate2 = kernel2->SampleRate();
   DCHECK_EQ(sample_rate1, sample_rate2);
 
-  float frame_delay =
+  const float frame_delay =
       (1 - x) * kernel1->FrameDelay() + x * kernel2->FrameDelay();
 
   std::unique_ptr<FFTFrame> interpolated_frame =
diff --git a/third_party/blink/renderer/platform/audio/hrtf_panner.cc b/third_party/blink/renderer/platform/audio/hrtf_panner.cc
index 970c1ff..363fcdd0 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_panner.cc
+++ b/third_party/blink/renderer/platform/audio/hrtf_panner.cc
@@ -30,29 +30,57 @@
 #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
 #include "third_party/blink/renderer/platform/audio/fft_frame.h"
 #include "third_party/blink/renderer/platform/audio/hrtf_database.h"
+#include "third_party/blink/renderer/platform/audio/hrtf_database_loader.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
 
 namespace blink {
 
+namespace {
+
 // The value of 2 milliseconds is larger than the largest delay which exists in
 // any HRTFKernel from the default HRTFDatabase (0.0136 seconds).
 // We ASSERT the delay values used in process() with this value.
-const double kMaxDelayTimeSeconds = 0.002;
+constexpr double kMaxDelayTimeSeconds = 0.002;
 
-const int kUninitializedAzimuth = -1;
+constexpr int kUninitializedAzimuth = -1;
+
+// Given an azimuth angle in the range -180 -> +180, returns the corresponding
+// azimuth index for the database, and azimuthBlend which is an interpolation
+// value from 0 -> 1.
+int CalculateDesiredAzimuthIndexAndBlend(double azimuth,
+                                         double& azimuth_blend) {
+  // Convert the azimuth angle from the range -180 -> +180 into the range 0 ->
+  // 360.  The azimuth index may then be calculated from this positive value.
+  if (azimuth < 0) {
+    azimuth += 360.0;
+  }
+
+  const int number_of_azimuths = HRTFDatabase::NumberOfAzimuths();
+  const double angle_between_azimuths = 360.0 / number_of_azimuths;
+
+  // Calculate the azimuth index and the blend (0 -> 1) for interpolation.
+  const double desired_azimuth_index_float = azimuth / angle_between_azimuths;
+  int desired_azimuth_index = static_cast<int>(desired_azimuth_index_float);
+  azimuth_blend =
+      desired_azimuth_index_float - static_cast<double>(desired_azimuth_index);
+
+  // We don't immediately start using this azimuth index, but instead approach
+  // this index from the last index we rendered at.  This minimizes the clicks
+  // and graininess for moving sources which occur otherwise.
+  desired_azimuth_index =
+      ClampTo(desired_azimuth_index, 0, number_of_azimuths - 1);
+  return desired_azimuth_index;
+}
+
+}  // namespace
 
 HRTFPanner::HRTFPanner(float sample_rate,
                        unsigned render_quantum_frames,
                        HRTFDatabaseLoader* database_loader)
     : database_loader_(database_loader),
       sample_rate_(sample_rate),
-      crossfade_selection_(kCrossfadeSelection1),
       azimuth_index1_(kUninitializedAzimuth),
-      elevation1_(0),
       azimuth_index2_(kUninitializedAzimuth),
-      elevation2_(0),
-      crossfade_x_(0),
-      crossfade_incr_(0),
       convolver_l1_(FftSizeForSampleRate(sample_rate)),
       convolver_r1_(FftSizeForSampleRate(sample_rate)),
       convolver_l2_(FftSizeForSampleRate(sample_rate)),
@@ -81,9 +109,9 @@
 
   DCHECK(audio_utilities::IsValidAudioBufferSampleRate(sample_rate));
 
-  int truncated_impulse_length = 256;
-  double sample_rate_ratio = sample_rate / 44100;
-  double resampled_length = truncated_impulse_length * sample_rate_ratio;
+  constexpr int truncated_impulse_length = 256;
+  const double sample_rate_ratio = sample_rate / 44100;
+  const double resampled_length = truncated_impulse_length * sample_rate_ratio;
 
   // This is the size used for analysis frames in the HRTF kernel.  The
   // convolvers used by the kernel are twice this size.
@@ -93,7 +121,7 @@
   // Don't let the analysis size be smaller than the supported size
   analysis_fft_size = std::max(analysis_fft_size, FFTFrame::MinFFTSize());
 
-  unsigned convolver_fft_size = 2 * analysis_fft_size;
+  const unsigned convolver_fft_size = 2 * analysis_fft_size;
 
   // Make sure this size of convolver is supported.
   DCHECK_LE(convolver_fft_size, FFTFrame::MaxFFTSize());
@@ -110,38 +138,14 @@
   delay_line_r_.Reset();
 }
 
-int HRTFPanner::CalculateDesiredAzimuthIndexAndBlend(double azimuth,
-                                                     double& azimuth_blend) {
-  // Convert the azimuth angle from the range -180 -> +180 into the range 0 ->
-  // 360.  The azimuth index may then be calculated from this positive value.
-  if (azimuth < 0) {
-    azimuth += 360.0;
-  }
-
-  int number_of_azimuths = HRTFDatabase::NumberOfAzimuths();
-  const double angle_between_azimuths = 360.0 / number_of_azimuths;
-
-  // Calculate the azimuth index and the blend (0 -> 1) for interpolation.
-  double desired_azimuth_index_float = azimuth / angle_between_azimuths;
-  int desired_azimuth_index = static_cast<int>(desired_azimuth_index_float);
-  azimuth_blend =
-      desired_azimuth_index_float - static_cast<double>(desired_azimuth_index);
-
-  // We don't immediately start using this azimuth index, but instead approach
-  // this index from the last index we rendered at.  This minimizes the clicks
-  // and graininess for moving sources which occur otherwise.
-  desired_azimuth_index =
-      ClampTo(desired_azimuth_index, 0, number_of_azimuths - 1);
-  return desired_azimuth_index;
-}
-
 void HRTFPanner::Pan(double desired_azimuth,
                      double elevation,
                      const AudioBus* input_bus,
                      AudioBus* output_bus,
                      uint32_t frames_to_process,
                      AudioBus::ChannelInterpretation channel_interpretation) {
-  unsigned num_input_channels = input_bus ? input_bus->NumberOfChannels() : 0;
+  const unsigned num_input_channels =
+      input_bus ? input_bus->NumberOfChannels() : 0;
 
   DCHECK(input_bus);
   DCHECK_GE(num_input_channels, 1u);
@@ -151,7 +155,7 @@
   DCHECK_EQ(output_bus->NumberOfChannels(), 2u);
   DCHECK_LE(frames_to_process, output_bus->length());
 
-  HRTFDatabase* database = database_loader_->Database();
+  const HRTFDatabase* const database = database_loader_->Database();
   if (!database) {
     output_bus->CopyFrom(*input_bus, channel_interpretation);
     return;
@@ -159,7 +163,7 @@
 
   // IRCAM HRTF azimuths values from the loaded database is reversed from the
   // panner's notion of azimuth.
-  double azimuth = -desired_azimuth;
+  const double azimuth = -desired_azimuth;
 
   DCHECK_GE(azimuth, -180.0);
   DCHECK_LE(azimuth, 180.0);
@@ -183,7 +187,7 @@
       output_bus->ChannelByType(AudioBus::kChannelRight)->MutableData();
 
   double azimuth_blend;
-  int desired_azimuth_index =
+  const int desired_azimuth_index =
       CalculateDesiredAzimuthIndexAndBlend(azimuth, azimuth_blend);
 
   // Initially snap azimuth and elevation values to first values encountered.
@@ -220,7 +224,7 @@
   }
 
   // This algorithm currently requires that we process in power-of-two size
-  // chunks of at least |RenderQuantumFrames()|.
+  // chunks of at least `RenderQuantumFrames()`.
   DCHECK_EQ(1UL << static_cast<int>(log2(frames_to_process)),
             frames_to_process);
   DCHECK_GE(frames_to_process, RenderQuantumFrames());
@@ -255,13 +259,13 @@
     DCHECK_LT(frame_delay_r2 / SampleRate(), kMaxDelayTimeSeconds);
 
     // Crossfade inter-aural delays based on transitions.
-    double frame_delay_l =
+    const double frame_delay_l =
         (1 - crossfade_x_) * frame_delay_l1 + crossfade_x_ * frame_delay_l2;
-    double frame_delay_r =
+    const double frame_delay_r =
         (1 - crossfade_x_) * frame_delay_r1 + crossfade_x_ * frame_delay_r2;
 
     // Calculate the source and destination pointers for the current segment.
-    unsigned offset = segment * kFramesPerSegment;
+    const unsigned offset = segment * kFramesPerSegment;
     const float* segment_source_l = source_l + offset;
     const float* segment_source_r = source_r + offset;
     float* segment_destination_l = destination_l + offset;
@@ -275,7 +279,7 @@
     delay_line_r_.Process(segment_source_r, segment_destination_r,
                           kFramesPerSegment);
 
-    bool needs_crossfading = crossfade_incr_;
+    const bool needs_crossfading = crossfade_incr_;
 
     // Have the convolvers render directly to the final destination if we're not
     // cross-fading.
@@ -309,7 +313,7 @@
     if (needs_crossfading) {
       // Apply linear cross-fade.
       float x = crossfade_x_;
-      float incr = crossfade_incr_;
+      const float incr = crossfade_incr_;
       for (unsigned i = 0; i < kFramesPerSegment; ++i) {
         segment_destination_l[i] = (1 - x) * convolution_destination_l1[i] +
                                    x * convolution_destination_l2[i];
diff --git a/third_party/blink/renderer/platform/audio/hrtf_panner.h b/third_party/blink/renderer/platform/audio/hrtf_panner.h
index 3aa7864..36f5b5ed 100644
--- a/third_party/blink/renderer/platform/audio/hrtf_panner.h
+++ b/third_party/blink/renderer/platform/audio/hrtf_panner.h
@@ -28,12 +28,13 @@
 
 #include "third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.h"
 #include "third_party/blink/renderer/platform/audio/fft_convolver.h"
-#include "third_party/blink/renderer/platform/audio/hrtf_database_loader.h"
 #include "third_party/blink/renderer/platform/audio/panner.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 
 namespace blink {
 
+class HRTFDatabaseLoader;
+
 class PLATFORM_EXPORT HRTFPanner final : public Panner {
  public:
   HRTFPanner(float sample_rate,
@@ -69,16 +70,6 @@
   unsigned RenderQuantumFrames() const { return render_quantum_frames_; }
 
  private:
-  // Given an azimuth angle in the range -180 -> +180, returns the corresponding
-  // azimuth index for the database, and azimuthBlend which is an interpolation
-  // value from 0 -> 1.
-  int CalculateDesiredAzimuthIndexAndBlend(double azimuth,
-                                           double& azimuth_blend);
-
-  scoped_refptr<HRTFDatabaseLoader> database_loader_;
-
-  float sample_rate_;
-
   // We maintain two sets of convolvers for smooth cross-faded interpolations
   // when then azimuth and elevation are dynamically changing.  When the
   // azimuth and elevation are not changing, we simply process with one
@@ -94,21 +85,25 @@
   // (m_convolverL2, m_convolverR2).
   enum CrossfadeSelection { kCrossfadeSelection1, kCrossfadeSelection2 };
 
-  CrossfadeSelection crossfade_selection_;
+  scoped_refptr<HRTFDatabaseLoader> database_loader_;
+
+  float sample_rate_;
+
+  CrossfadeSelection crossfade_selection_ = kCrossfadeSelection1;
 
   // azimuth/elevation for CrossfadeSelection1.
   int azimuth_index1_;
-  double elevation1_;
+  double elevation1_ = 0.0;
 
   // azimuth/elevation for CrossfadeSelection2.
   int azimuth_index2_;
-  double elevation2_;
+  double elevation2_ = 0.0;
 
   // A crossfade value 0 <= m_crossfadeX <= 1.
-  float crossfade_x_;
+  float crossfade_x_ = 0.0;
 
   // Per-sample-frame crossfade value increment.
-  float crossfade_incr_;
+  float crossfade_incr_ = 0.0;
 
   FFTConvolver convolver_l1_;
   FFTConvolver convolver_r1_;
diff --git a/third_party/blink/renderer/platform/audio/panner.cc b/third_party/blink/renderer/platform/audio/panner.cc
index 1e708e0..0fa8165 100644
--- a/third_party/blink/renderer/platform/audio/panner.cc
+++ b/third_party/blink/renderer/platform/audio/panner.cc
@@ -29,6 +29,8 @@
 #include "third_party/blink/renderer/platform/audio/panner.h"
 
 #include <memory>
+
+#include "base/notreached.h"
 #include "third_party/blink/renderer/platform/audio/equal_power_panner.h"
 #include "third_party/blink/renderer/platform/audio/hrtf_panner.h"
 
diff --git a/third_party/blink/renderer/platform/bindings/to_v8.h b/third_party/blink/renderer/platform/bindings/to_v8.h
index 10552497..63ca126 100644
--- a/third_party/blink/renderer/platform/bindings/to_v8.h
+++ b/third_party/blink/renderer/platform/bindings/to_v8.h
@@ -14,6 +14,7 @@
 #include <utility>
 
 #include "base/containers/span.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/time/time.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/platform/bindings/callback_function_base.h"
@@ -26,7 +27,6 @@
 #include "third_party/blink/renderer/platform/bindings/union_base.h"
 #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "v8/include/v8.h"
 
 namespace blink {
@@ -327,7 +327,7 @@
   {
     v8::Context::Scope context_scope(
         creation_context->GetCreationContextChecked());
-    array = v8::Array::New(isolate, SafeCast<int>(sequence.size()));
+    array = v8::Array::New(isolate, base::checked_cast<int>(sequence.size()));
   }
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   uint32_t index = 0;
diff --git a/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc b/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
index 8b17038..6885224 100644
--- a/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
+++ b/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
@@ -204,8 +204,8 @@
     return;
   }
 
-  int64_t seek_distance =
-      file.Seek(base::File::FROM_BEGIN, SafeCast<int64_t>(file_offset));
+  int64_t seek_distance = file.Seek(base::File::FROM_BEGIN,
+                                    base::checked_cast<int64_t>(file_offset));
   bool seek_failed = seek_distance < 0;
   if (seek_failed) {
     std::move(callback).Run(absl::nullopt);
diff --git a/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager.cc b/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager.cc
index d3ad927..75c22eb9 100644
--- a/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager.cc
+++ b/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager.cc
@@ -123,7 +123,8 @@
     const media::VideoCaptureSessionId& id,
     const media::VideoCaptureParams& params,
     const VideoCaptureStateUpdateCB& state_update_cb,
-    const VideoCaptureDeliverFrameCB& deliver_frame_cb) {
+    const VideoCaptureDeliverFrameCB& deliver_frame_cb,
+    const VideoCaptureCropVersionCB& crop_version_cb) {
   DCHECK(render_main_task_runner_->BelongsToCurrentThread());
   const auto it = base::ranges::find(devices_, id, &DeviceEntry::session_id);
   if (it == devices_.end())
@@ -135,7 +136,8 @@
   Platform::Current()->GetIOTaskRunner()->PostTask(
       FROM_HERE,
       base::BindOnce(&VideoCaptureImpl::StartCapture, it->impl->GetWeakPtr(),
-                     client_id, params, state_update_cb, deliver_frame_cb));
+                     client_id, params, state_update_cb, deliver_frame_cb,
+                     crop_version_cb));
   return base::BindOnce(&WebVideoCaptureImplManager::StopCapture,
                         weak_factory_.GetWeakPtr(), client_id, id);
 }
diff --git a/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc b/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc
index aacb74b3..2442912 100644
--- a/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc
+++ b/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc
@@ -236,7 +236,8 @@
             CrossThreadUnretained(this), id)),
         ConvertToBaseRepeatingCallback(
             CrossThreadBindRepeating(&VideoCaptureImplManagerTest::OnFrameReady,
-                                     CrossThreadUnretained(this))));
+                                     CrossThreadUnretained(this))),
+        base::DoNothing());
   }
 
   base::test::TaskEnvironment task_environment_;
diff --git a/third_party/blink/renderer/platform/fonts/font_fallback_list.cc b/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
index f6a36091..5dc3da6 100644
--- a/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
+++ b/third_party/blink/renderer/platform/fonts/font_fallback_list.cc
@@ -43,9 +43,7 @@
 namespace blink {
 
 FontFallbackList::FontFallbackList(FontFallbackMap& font_fallback_map)
-    : cached_primary_simple_font_data_(nullptr),
-      font_fallback_map_(font_fallback_map),
-      family_index_(0),
+    : font_fallback_map_(font_fallback_map),
       generation_(FontCache::Get().Generation()),
       has_loading_fallback_(false),
       has_custom_font_(false),
diff --git a/third_party/blink/renderer/platform/fonts/font_fallback_list.h b/third_party/blink/renderer/platform/fonts/font_fallback_list.h
index 2dc8899..e279cdd 100644
--- a/third_party/blink/renderer/platform/fonts/font_fallback_list.h
+++ b/third_party/blink/renderer/platform/fonts/font_fallback_list.h
@@ -123,10 +123,10 @@
   bool ComputeCanShapeWordByWord(const FontDescription&);
 
   Vector<scoped_refptr<FontData>, 1> font_list_;
-  const SimpleFontData* cached_primary_simple_font_data_;
+  const SimpleFontData* cached_primary_simple_font_data_ = nullptr;
   const WeakPersistent<FontFallbackMap> font_fallback_map_;
-  int family_index_;
-  uint16_t generation_;
+  int family_index_ = 0;
+  const uint16_t generation_;
   bool has_loading_fallback_ : 1;
   bool has_custom_font_ : 1;
   bool can_shape_word_by_word_ : 1;
diff --git a/third_party/blink/renderer/platform/fonts/font_selector.h b/third_party/blink/renderer/platform/fonts/font_selector.h
index da32354..ff22b4e6 100644
--- a/third_party/blink/renderer/platform/fonts/font_selector.h
+++ b/third_party/blink/renderer/platform/fonts/font_selector.h
@@ -56,8 +56,8 @@
   virtual scoped_refptr<FontData> GetFontData(const FontDescription&,
                                               const FontFamily&) = 0;
 
-  // TODO crbug.com/542629 - The String variant of this method shouldbe replaced
-  // with a better approach, now that we only have complex text.
+  // TODO(crbug.com/542629): The String variant of this method should be
+  // replaced with a better approach, now that we only have complex text.
   virtual void WillUseFontData(const FontDescription&,
                                const FontFamily& family,
                                const String& text) = 0;
diff --git a/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc b/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc
index 7815ddc..2dbfee3 100644
--- a/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc
+++ b/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc
@@ -26,10 +26,10 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/fonts/opentype/open_type_types.h"
 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
 #include "third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/skia/include/core/SkTypeface.h"
 
 namespace blink {
@@ -136,7 +136,7 @@
                               SkFontTableTag tag,
                               Vector<char>& destination) {
   const size_t table_size = typeface->getTableSize(tag);
-  destination.resize(SafeCast<wtf_size_t>(table_size));
+  destination.resize(base::checked_cast<wtf_size_t>(table_size));
   if (table_size) {
     typeface->getTableData(tag, 0, table_size, destination.data());
   }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
index 5561f7a..b4bb5a3 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
@@ -371,7 +371,7 @@
   SkTypeface* typeface = reinterpret_cast<SkTypeface*>(user_data);
 
   const wtf_size_t table_size =
-      SafeCast<wtf_size_t>(typeface->getTableSize(tag));
+      base::checked_cast<wtf_size_t>(typeface->getTableSize(tag));
   if (!table_size) {
     return nullptr;
   }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face_from_typeface.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face_from_typeface.cc
index 05c13c5..9947ea9b 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face_from_typeface.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face_from_typeface.cc
@@ -4,7 +4,7 @@
 
 #include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face_from_typeface.h"
 
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/skia/include/core/SkStream.h"
 
 namespace {
@@ -28,10 +28,10 @@
   if (tf_stream && tf_stream->getMemoryBase()) {
     const void* tf_memory = tf_stream->getMemoryBase();
     size_t tf_size = tf_stream->getLength();
-    HbScoped<hb_blob_t> face_blob(
-        hb_blob_create(reinterpret_cast<const char*>(tf_memory),
-                       SafeCast<unsigned int>(tf_size), HB_MEMORY_MODE_READONLY,
-                       tf_stream.release(), DeleteTypefaceStream));
+    HbScoped<hb_blob_t> face_blob(hb_blob_create(
+        reinterpret_cast<const char*>(tf_memory),
+        base::checked_cast<unsigned int>(tf_size), HB_MEMORY_MODE_READONLY,
+        tf_stream.release(), DeleteTypefaceStream));
     // hb_face_create always succeeds.
     // Use hb_face_count to retrieve the number of recognized faces in the blob.
     // hb_face_create_for_tables may still create a working hb_face.
diff --git a/third_party/blink/renderer/platform/fonts/web_font_decoder.cc b/third_party/blink/renderer/platform/fonts/web_font_decoder.cc
index 6e388c9..6d3459a 100644
--- a/third_party/blink/renderer/platform/fonts/web_font_decoder.cc
+++ b/third_party/blink/renderer/platform/fonts/web_font_decoder.cc
@@ -30,19 +30,19 @@
 
 #include "third_party/blink/renderer/platform/fonts/web_font_decoder.h"
 
+#include <hb.h>
+#include <stdarg.h>
+
+#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
 #include "third_party/blink/renderer/platform/fonts/web_font_typeface_factory.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-
 #include "third_party/ots/src/include/ots-memory-stream.h"
 #include "third_party/skia/include/core/SkStream.h"
 
-#include <hb.h>
-#include <stdarg.h>
-
 namespace blink {
 
 namespace {
@@ -175,7 +175,7 @@
     return nullptr;
   }
 
-  const size_t decoded_length = SafeCast<size_t>(output.Tell());
+  const size_t decoded_length = base::checked_cast<size_t>(output.Tell());
   sk_sp<SkData> sk_data = SkData::MakeWithCopy(output.get(), decoded_length);
 
   sk_sp<SkTypeface> new_typeface;
diff --git a/third_party/blink/renderer/platform/geometry/layout_point.h b/third_party/blink/renderer/platform/geometry/layout_point.h
index 04f3de4..573f1680 100644
--- a/third_party/blink/renderer/platform/geometry/layout_point.h
+++ b/third_party/blink/renderer/platform/geometry/layout_point.h
@@ -59,6 +59,11 @@
     return gfx::PointF(x_.ToFloat(), y_.ToFloat());
   }
 
+  // This is deleted to avoid unwanted lossy conversion from float or double to
+  // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter
+  // instead.
+  LayoutPoint(double, double) = delete;
+
   static constexpr LayoutPoint Zero() { return LayoutPoint(); }
 
   constexpr LayoutUnit X() const { return x_; }
diff --git a/third_party/blink/renderer/platform/geometry/layout_rect.h b/third_party/blink/renderer/platform/geometry/layout_rect.h
index 53908bc1..2c10952 100644
--- a/third_party/blink/renderer/platform/geometry/layout_rect.h
+++ b/third_party/blink/renderer/platform/geometry/layout_rect.h
@@ -73,6 +73,11 @@
     return gfx::RectF(X(), Y(), Width(), Height());
   }
 
+  // This is deleted to avoid unwanted lossy conversion from float or double to
+  // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter
+  // instead.
+  LayoutRect(double, double, double, double) = delete;
+
   constexpr LayoutPoint Location() const { return location_; }
   constexpr LayoutSize Size() const { return size_; }
 
diff --git a/third_party/blink/renderer/platform/geometry/layout_size.h b/third_party/blink/renderer/platform/geometry/layout_size.h
index 35b01b7..71f5e47 100644
--- a/third_party/blink/renderer/platform/geometry/layout_size.h
+++ b/third_party/blink/renderer/platform/geometry/layout_size.h
@@ -53,8 +53,6 @@
       : width_(width), height_(height) {}
   constexpr LayoutSize(int width, int height)
       : width_(LayoutUnit(width)), height_(LayoutUnit(height)) {}
-  constexpr LayoutSize(float width, float height)
-      : width_(LayoutUnit(width)), height_(LayoutUnit(height)) {}
 
   constexpr explicit LayoutSize(const gfx::SizeF& size)
       : width_(size.width()), height_(size.height()) {}
@@ -64,13 +62,15 @@
   constexpr explicit operator gfx::SizeF() const {
     return gfx::SizeF(width_.ToFloat(), height_.ToFloat());
   }
-  constexpr explicit operator gfx::PointF() const {
-    return gfx::PointF(width_.ToFloat(), height_.ToFloat());
-  }
   constexpr explicit operator gfx::Vector2dF() const {
     return gfx::Vector2dF(width_.ToFloat(), height_.ToFloat());
   }
 
+  // This is deleted to avoid unwanted lossy conversion from float or double to
+  // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter
+  // instead.
+  LayoutSize(double, double) = delete;
+
   constexpr LayoutUnit Width() const { return width_; }
   constexpr LayoutUnit Height() const { return height_; }
 
@@ -176,7 +176,8 @@
 }
 
 inline LayoutSize operator*(const LayoutSize& a, const float scale) {
-  return LayoutSize(a.Width() * scale, a.Height() * scale);
+  return LayoutSize(LayoutUnit(a.Width() * scale),
+                    LayoutUnit(a.Height() * scale));
 }
 
 constexpr bool operator==(const LayoutSize& a, const LayoutSize& b) {
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc b/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
index 03a311e..4b3d56b 100644
--- a/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
+++ b/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
@@ -32,6 +32,7 @@
 
 #include "base/bind.h"
 #include "base/feature_list.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/time/time.h"
@@ -50,7 +51,6 @@
 #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "ui/gfx/geometry/rect_f.h"
@@ -130,7 +130,8 @@
 
     void DecodedSizeChangedTo(const Image*, size_t new_size) override {
       last_decoded_size_changed_delta_ =
-          SafeCast<int>(new_size) - SafeCast<int>(last_decoded_size_);
+          base::checked_cast<int>(new_size) -
+          base::checked_cast<int>(last_decoded_size_);
       last_decoded_size_ = new_size;
     }
     bool ShouldPauseAnimation(const Image*) override { return false; }
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc b/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
index 8566692..67ba997 100644
--- a/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
+++ b/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
@@ -27,6 +27,7 @@
 #include <memory>
 
 #include "base/numerics/checked_math.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/stl_util.h"
 #include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
@@ -113,7 +114,7 @@
   uint64_t kernel_area = kernel_size_.Area64();
   if (!base::CheckedNumeric<int>(kernel_area).IsValid())
     return false;
-  if (SafeCast<size_t>(kernel_area) != kernel_matrix_.size())
+  if (base::checked_cast<size_t>(kernel_area) != kernel_matrix_.size())
     return false;
   if (target_offset_.x() < 0 || target_offset_.x() >= kernel_size_.width())
     return false;
@@ -133,7 +134,7 @@
   SkISize kernel_size(
       SkISize::Make(kernel_size_.width(), kernel_size_.height()));
   // parametersValid() above checks that the kernel area fits in int.
-  int num_elements = SafeCast<int>(kernel_size_.Area64());
+  int num_elements = base::checked_cast<int>(kernel_size_.Area64());
   SkScalar gain = SkFloatToScalar(1.0f / divisor_);
   SkScalar bias = SkFloatToScalar(bias_ * 255);
   SkIPoint target = SkIPoint::Make(target_offset_.x(), target_offset_.y());
diff --git a/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc b/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
index 1906130..32ce347 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
@@ -18,9 +18,17 @@
   auto dawn_control_client_holder =
       base::MakeRefCounted<DawnControlClientHolder>(std::move(context_provider),
                                                     std::move(task_runner));
+  // The context lost callback occurs when the client receives
+  // OnGpuControlLostContext. This can happen on fatal errors when the GPU
+  // channel is disconnected: the GPU process crashes, the GPU process fails to
+  // deserialize a message, etc. We mark the context lost, but NOT destroy the
+  // entire WebGraphicsContext3DProvider as that would free services for mapping
+  // shared memory. There may still be outstanding mapped GPUBuffers pointing to
+  // this memory.
   dawn_control_client_holder->context_provider_->ContextProvider()
       ->SetLostContextCallback(WTF::BindRepeating(
-          &DawnControlClientHolder::Destroy, dawn_control_client_holder));
+          &DawnControlClientHolder::MarkContextLost,
+          dawn_control_client_holder->weak_ptr_factory_.GetWeakPtr()));
   return dawn_control_client_holder;
 }
 
@@ -39,7 +47,7 @@
 DawnControlClientHolder::~DawnControlClientHolder() = default;
 
 void DawnControlClientHolder::Destroy() {
-  api_channel_->Disconnect();
+  MarkContextLost();
 
   // Destroy the WebGPU context.
   // This ensures that GPU resources are eagerly reclaimed.
@@ -73,8 +81,16 @@
   return api_channel_->GetWGPUInstance();
 }
 
+void DawnControlClientHolder::MarkContextLost() {
+  if (context_lost_) {
+    return;
+  }
+  api_channel_->Disconnect();
+  context_lost_ = true;
+}
+
 bool DawnControlClientHolder::IsContextLost() const {
-  return !context_provider_;
+  return context_lost_;
 }
 
 std::unique_ptr<RecyclableCanvasResource>
diff --git a/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h b/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
index 372ad93..c8ed046 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
@@ -48,6 +48,7 @@
       const;
   const DawnProcTable& GetProcs() const { return procs_; }
   WGPUInstance GetWGPUInstance() const;
+  void MarkContextLost();
   bool IsContextLost() const;
   std::unique_ptr<RecyclableCanvasResource> GetOrCreateCanvasResource(
       const SkImageInfo& info,
@@ -62,11 +63,14 @@
   friend class RefCounted<DawnControlClientHolder>;
   ~DawnControlClientHolder();
 
+  bool context_lost_ = false;
   std::unique_ptr<WebGraphicsContext3DProviderWrapper> context_provider_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   scoped_refptr<gpu::webgpu::APIChannel> api_channel_;
   DawnProcTable procs_;
   WebGPURecyclableResourceCache recyclable_resource_cache_;
+
+  base::WeakPtrFactory<DawnControlClientHolder> weak_ptr_factory_{this};
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
index d48c9f2..910be166 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
@@ -318,7 +318,7 @@
   }
 
   static void MoveRect(LayoutRect& rect, const gfx::Vector2dF& delta) {
-    rect.Move(LayoutSize(delta.x(), delta.y()));
+    rect.Move(LayoutSize(delta));
   }
 
   static void MoveRect(gfx::Rect& rect, const gfx::Vector2dF& delta) {
diff --git a/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc b/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
index 99fdabef..93c3d5d 100644
--- a/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
+++ b/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
@@ -6,13 +6,13 @@
 
 #include <initializer_list>
 
+#include "base/numerics/safe_conversions.h"
 #include "services/network/public/mojom/cors.mojom-blink.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -79,8 +79,9 @@
       "fetch the resource with CORS disabled.";
 
   using CorsError = network::mojom::CorsError;
-  const StringView hint(status.failed_parameter.data(),
-                        SafeCast<wtf_size_t>(status.failed_parameter.size()));
+  const StringView hint(
+      status.failed_parameter.data(),
+      base::checked_cast<wtf_size_t>(status.failed_parameter.size()));
 
   const char* resource_kind_raw =
       Resource::ResourceTypeToString(resource_type, initiator_name);
diff --git a/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc b/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc
index 8f25b47..0d7f186e 100644
--- a/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer.cc
@@ -6,8 +6,8 @@
 
 #include "base/feature_list.h"
 #include "base/metrics/field_trial_params.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -198,7 +198,7 @@
       return;
     if (result == Result::kOk) {
       auto* chunk = MakeGarbageCollected<HeapVector<char>>();
-      chunk->Append(p, SafeCast<wtf_size_t>(available));
+      chunk->Append(p, base::checked_cast<wtf_size_t>(available));
       buffer_.push_back(chunk);
       result = bytes_consumer_->EndRead(available);
     }
diff --git a/third_party/blink/renderer/platform/loader/fetch/cached_metadata.h b/third_party/blink/renderer/platform/loader/fetch/cached_metadata.h
index a7238d15..adcf75f4 100644
--- a/third_party/blink/renderer/platform/loader/fetch/cached_metadata.h
+++ b/third_party/blink/renderer/platform/loader/fetch/cached_metadata.h
@@ -35,6 +35,7 @@
 
 #include "base/check_op.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/numerics/safe_conversions.h"
 #include "mojo/public/cpp/base/big_buffer.h"
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
@@ -61,8 +62,8 @@
   static scoped_refptr<CachedMetadata> Create(uint32_t data_type_id,
                                               const uint8_t* data,
                                               size_t size) {
-    return base::AdoptRef(
-        new CachedMetadata(data_type_id, data, SafeCast<wtf_size_t>(size)));
+    return base::AdoptRef(new CachedMetadata(
+        data_type_id, data, base::checked_cast<wtf_size_t>(size)));
   }
 
   // Returns a Vector containing the header of serialized metadata.
@@ -120,7 +121,8 @@
     return buffer_.size() ? buffer_.data() : vector_.data();
   }
   uint32_t RawSize() const {
-    return buffer_.size() ? SafeCast<uint32_t>(buffer_.size()) : vector_.size();
+    return buffer_.size() ? base::checked_cast<uint32_t>(buffer_.size())
+                          : vector_.size();
   }
 
   // Since the serialization format supports random access, storing it in
diff --git a/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.cc b/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.cc
index d5bcdbf..2c44424 100644
--- a/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.cc
@@ -7,11 +7,11 @@
 #include <algorithm>
 
 #include "base/location.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/task/single_thread_task_runner.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -106,7 +106,7 @@
   DCHECK(is_in_two_phase_read_);
   is_in_two_phase_read_ = false;
   DCHECK(IsReadableOrWaiting());
-  MojoResult rv = data_pipe_->EndReadData(SafeCast<uint32_t>(read));
+  MojoResult rv = data_pipe_->EndReadData(base::checked_cast<uint32_t>(read));
   if (rv != MOJO_RESULT_OK) {
     SetError(Error("error"));
     return Result::kError;
diff --git a/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc b/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
index 9b0999b..61fb50e 100644
--- a/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
@@ -31,6 +31,8 @@
 #include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
 
 #include <memory>
+
+#include "base/numerics/safe_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url.h"
@@ -48,7 +50,6 @@
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -108,7 +109,7 @@
   String DebugName() const override { return "DummyClient"; }
 
   void DataReceived(Resource*, const char* data, size_t length) override {
-    data_.Append(data, SafeCast<wtf_size_t>(length));
+    data_.Append(data, base::checked_cast<wtf_size_t>(length));
   }
 
   bool RedirectReceived(Resource*,
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index dd6c2bb..d1a1159 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -36,6 +36,7 @@
 #include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/metrics/public/cpp/metrics_utils.h"
 #include "services/metrics/public/cpp/mojo_ukm_recorder.h"
@@ -90,7 +91,6 @@
 #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 #include "url/url_constants.h"
 
@@ -1437,7 +1437,7 @@
   if (data_out.size()) {
     data_out.ForEachSegment([this](const char* segment, size_t segment_size,
                                    size_t segment_offset) {
-      DidReceiveData(segment, SafeCast<int>(segment_size));
+      DidReceiveData(segment, base::checked_cast<int>(segment_size));
       return true;
     });
   }
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/source_keyed_cached_metadata_handler_test.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/source_keyed_cached_metadata_handler_test.cc
index bbab78d..4da9b01b 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/source_keyed_cached_metadata_handler_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/source_keyed_cached_metadata_handler_test.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -13,7 +14,6 @@
 #include "third_party/blink/renderer/platform/crypto.h"
 #include "third_party/blink/renderer/platform/loader/fetch/code_cache_host.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -64,7 +64,7 @@
                      const uint8_t* data,
                      size_t data_size) {
     cache_entries_.emplace_back(url, response_time, data,
-                                SafeCast<wtf_size_t>(data_size));
+                                base::checked_cast<wtf_size_t>(data_size));
   }
 
  private:
diff --git a/third_party/blink/renderer/platform/media/buffered_data_source_host_impl.cc b/third_party/blink/renderer/platform/media/buffered_data_source_host_impl.cc
index e67cdbf7..734c67d6 100644
--- a/third_party/blink/renderer/platform/media/buffered_data_source_host_impl.cc
+++ b/third_party/blink/renderer/platform/media/buffered_data_source_host_impl.cc
@@ -135,7 +135,8 @@
   // data point that has the lowest download rate, we avoid over-estimating.
   const double kVeryLargeRate = 1.0E20;
   double download_rate = kVeryLargeRate;
-  for (int i = 0; i < std::min<int>(20, download_history_.size() - 3); i++) {
+  for (size_t i = 0; i < std::min<size_t>(20, download_history_.size() - 3);
+       i++) {
     int64_t downloaded_bytes =
         download_history_.back().second - download_history_[i].second;
     base::TimeTicks now = tick_clock_->NowTicks();
diff --git a/third_party/blink/renderer/platform/media/multi_buffer.cc b/third_party/blink/renderer/platform/media/multi_buffer.cc
index 958d59d..7d8440d 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer.cc
+++ b/third_party/blink/renderer/platform/media/multi_buffer.cc
@@ -418,7 +418,7 @@
     Interval<BlockId> expanded_range = present_.find(start_pos).interval();
     NotifyAvailableRange(expanded_range, expanded_range);
     lru_->IncrementDataSize(blocks_added);
-    Prune(blocks_added * kMaxFreesPerAdd + 1);
+    Prune(static_cast<size_t>(blocks_added) * kMaxFreesPerAdd + 1);
   } else {
     // Make sure to give progress reports even when there
     // aren't any new blocks yet.
@@ -560,7 +560,7 @@
   }
 }
 
-void MultiBuffer::IncrementMaxSize(int32_t size) {
+void MultiBuffer::IncrementMaxSize(int64_t size) {
   max_size_ += size;
   lru_->IncrementMaxSize(size);
   DCHECK_GE(max_size_, 0);
diff --git a/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc b/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
index 58256037..2879fec7 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
+++ b/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
@@ -412,7 +412,7 @@
     // muxing as soon as possible. This works because TryReadAt is
     // thread-safe.
     if (reader_) {
-      int bytes_read = reader_->TryReadAt(position, data, size);
+      int64_t bytes_read = reader_->TryReadAt(position, data, size);
       if (bytes_read > 0) {
         bytes_read_ += bytes_read;
         seek_positions_.push_back(position + bytes_read);
@@ -424,7 +424,7 @@
               kSeekDelay);
         }
 
-        std::move(read_cb).Run(bytes_read);
+        std::move(read_cb).Run(static_cast<int>(bytes_read));
         return;
       }
     }
@@ -457,7 +457,6 @@
   DCHECK(render_task_runner_->BelongsToCurrentThread());
 
   base::AutoLock auto_lock(lock_);
-  int bytes_read = 0;
   if (stop_signal_received_ || !read_op_)
     return;
   DCHECK(read_op_->size());
@@ -472,8 +471,7 @@
     return;
   }
   if (available) {
-    bytes_read =
-        static_cast<int>(std::min<int64_t>(available, read_op_->size()));
+    int64_t bytes_read = std::min<int64_t>(available, read_op_->size());
     bytes_read =
         reader_->TryReadAt(read_op_->position(), read_op_->data(), bytes_read);
 
@@ -489,7 +487,7 @@
         host_->SetTotalBytes(total_bytes_);
     }
 
-    ReadOperation::Run(std::move(read_op_), bytes_read);
+    ReadOperation::Run(std::move(read_op_), static_cast<int>(bytes_read));
 
     SeekTask_Locked();
   } else {
diff --git a/third_party/blink/renderer/platform/media/multi_buffer_data_source_unittest.cc b/third_party/blink/renderer/platform/media/multi_buffer_data_source_unittest.cc
index 4a3b9cc..f807881 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer_data_source_unittest.cc
+++ b/third_party/blink/renderer/platform/media/multi_buffer_data_source_unittest.cc
@@ -360,7 +360,7 @@
 
   MOCK_METHOD1(ReadCallback, void(int size));
 
-  void ReadAt(int64_t position, int64_t howmuch = kDataSize) {
+  void ReadAt(int64_t position, int howmuch = kDataSize) {
     data_source_->Read(position, howmuch, buffer_,
                        base::BindOnce(&MultiBufferDataSourceTest::ReadCallback,
                                       base::Unretained(this)));
diff --git a/third_party/blink/renderer/platform/media/multi_buffer_reader.cc b/third_party/blink/renderer/platform/media/multi_buffer_reader.cc
index 6733a95..7fbda8f 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer_reader.cc
+++ b/third_party/blink/renderer/platform/media/multi_buffer_reader.cc
@@ -94,12 +94,11 @@
   for (auto& buffer : buffers) {
     if (buffer->end_of_stream())
       break;
-    size_t offset = pos & ((1LL << multibuffer_->block_size_shift()) - 1);
-    if (offset > static_cast<size_t>(buffer->data_size()))
+    int64_t offset = pos & ((1LL << multibuffer_->block_size_shift()) - 1);
+    if (offset > static_cast<int64_t>(buffer->data_size()))
       break;
-    size_t tocopy =
-        std::min<size_t>(len - bytes_read, buffer->data_size() - offset);
-    memcpy(data, buffer->data() + offset, tocopy);
+    int64_t tocopy = std::min(len - bytes_read, buffer->data_size() - offset);
+    memcpy(data, buffer->data() + offset, static_cast<size_t>(tocopy));
     data += tocopy;
     bytes_read += tocopy;
     if (bytes_read == len)
diff --git a/third_party/blink/renderer/platform/media/multi_buffer_reader.h b/third_party/blink/renderer/platform/media/multi_buffer_reader.h
index aacc162d..a6d8c40 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer_reader.h
+++ b/third_party/blink/renderer/platform/media/multi_buffer_reader.h
@@ -114,7 +114,8 @@
 
   // Returns the block for a particular byte position.
   MultiBufferBlockId block(int64_t byte_pos) const {
-    return byte_pos >> multibuffer_->block_size_shift();
+    return static_cast<MultiBufferBlockId>(byte_pos >>
+                                           multibuffer_->block_size_shift());
   }
 
   // Returns the block for a particular byte position, rounding up.
diff --git a/third_party/blink/renderer/platform/media/multi_buffer_unittest.cc b/third_party/blink/renderer/platform/media/multi_buffer_unittest.cc
index ca7cb55f..39295ba 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer_unittest.cc
+++ b/third_party/blink/renderer/platform/media/multi_buffer_unittest.cc
@@ -97,7 +97,8 @@
     --blocks_until_deferred_;
 
     bool ret = true;
-    auto block = base::MakeRefCounted<media::DataBuffer>(kBlockSize);
+    auto block =
+        base::MakeRefCounted<media::DataBuffer>(static_cast<int>(kBlockSize));
     size_t x = 0;
     size_t byte_pos = (fifo_.size() + pos_) * kBlockSize;
     for (x = 0; x < kBlockSize; x++, byte_pos++) {
diff --git a/third_party/blink/renderer/platform/media/power_status_helper.cc b/third_party/blink/renderer/platform/media/power_status_helper.cc
index b8b59f4..df286d2d 100644
--- a/third_party/blink/renderer/platform/media/power_status_helper.cc
+++ b/third_party/blink/renderer/platform/media/power_status_helper.cc
@@ -247,7 +247,7 @@
   // converted to int.  We can only record ints in UMA.
   const int delta_int = static_cast<int>(delta);
   const base::TimeDelta elapsed = now - last_update_;
-  const int elapsed_msec = elapsed.InMilliseconds();
+  const int64_t elapsed_msec = elapsed.InMilliseconds();
   if (delta_int > 0 && elapsed_msec > 0) {
     // Record that we consumed |delta_int| battery percent in |elapsed_msec|.
     base::LinearHistogram::FactoryGet(
@@ -258,7 +258,7 @@
     base::LinearHistogram::FactoryGet(
         ElapsedTimeHistogram(), kMinUmaValue, kMaxUmaValue, kNumUmaBuckets,
         base::HistogramBase::kUmaTargetedHistogramFlag)
-        ->AddCount(*current_bucket_, elapsed_msec);
+        ->AddCount(*current_bucket_, static_cast<int>(elapsed_msec));
 
     // Update the baseline to |current_level|, but include any fractional
     // unrecorded amount so that we can record it later.
diff --git a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
index a2f0948e..09a126f 100644
--- a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
+++ b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
@@ -389,15 +389,17 @@
 
   while (data_length) {
     if (fifo_.empty() || fifo_.back()->data_size() == block_size()) {
-      fifo_.push_back(new media::DataBuffer(block_size()));
+      fifo_.push_back(new media::DataBuffer(static_cast<int>(block_size())));
       fifo_.back()->set_data_size(0);
     }
     int last_block_size = fifo_.back()->data_size();
-    int to_append = std::min<int>(data_length, block_size() - last_block_size);
+    auto to_append =
+        std::min<int64_t>(data_length, block_size() - last_block_size);
     DCHECK_GT(to_append, 0);
-    memcpy(fifo_.back()->writable_data() + last_block_size, data, to_append);
+    memcpy(fifo_.back()->writable_data() + last_block_size, data,
+           static_cast<size_t>(to_append));
     data += to_append;
-    fifo_.back()->set_data_size(last_block_size + to_append);
+    fifo_.back()->set_data_size(static_cast<int>(last_block_size + to_append));
     data_length -= to_append;
   }
 
diff --git a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
index fa36c71..0c0ea737 100644
--- a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
+++ b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
@@ -208,7 +208,7 @@
 
   base::test::SingleThreadTaskEnvironment task_environment_;
   GURL gurl_;
-  int64_t first_position_;
+  int32_t first_position_;
 
   NiceMock<MockResourceFetchContext> fetch_context_;
   UrlIndex url_index_{&fetch_context_, 0,
diff --git a/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc b/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
index ff3f3895..710559f8 100644
--- a/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
+++ b/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
@@ -31,8 +31,10 @@
 #include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
 
 #include <stddef.h>
+
 #include "base/containers/contains.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
 #include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink.h"
@@ -391,14 +393,16 @@
                        static_cast<wtf_size_t>(utf8_string.length()));
 
   if (!strcmp(content_encoding, kBinary)) {
-    for (const auto& span : *resource.data)
-      output_buffer.Append(span.data(), SafeCast<wtf_size_t>(span.size()));
+    for (const auto& span : *resource.data) {
+      output_buffer.Append(span.data(),
+                           base::checked_cast<wtf_size_t>(span.size()));
+    }
   } else {
     // FIXME: ideally we would encode the content as a stream without having to
     // fetch it all.
     const SharedBuffer::DeprecatedFlatData flat_data(resource.data);
     const char* data = flat_data.Data();
-    wtf_size_t data_length = SafeCast<wtf_size_t>(flat_data.size());
+    wtf_size_t data_length = base::checked_cast<wtf_size_t>(flat_data.size());
     Vector<char> encoded_data;
     if (!strcmp(content_encoding, kQuotedPrintable)) {
       QuotedPrintableEncode(data, data_length, false /* is_header */,
diff --git a/third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.cc b/third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.cc
index 99a14a9..01deb23 100644
--- a/third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.cc
+++ b/third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.cc
@@ -31,8 +31,8 @@
 #include "third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.h"
 
 #include "base/notreached.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
 namespace blink {
 
@@ -67,7 +67,8 @@
 
 void SharedBufferChunkReader::SetSeparator(const char* separator) {
   separator_.clear();
-  separator_.Append(separator, SafeCast<wtf_size_t>(strlen(separator)));
+  separator_.Append(separator,
+                    base::checked_cast<wtf_size_t>(strlen(separator)));
 }
 
 bool SharedBufferChunkReader::NextChunk(Vector<char>& chunk,
@@ -110,7 +111,7 @@
       return !chunk.IsEmpty();
     }
     segment_ = it->data();
-    segment_length_ = SafeCast<uint32_t>(it->size());
+    segment_length_ = base::checked_cast<uint32_t>(it->size());
   }
   NOTREACHED();
   return false;
@@ -145,7 +146,7 @@
       read_bytes_count += (requested_size - read_bytes_count);
       break;
     }
-    data.Append(it->data(), SafeCast<wtf_size_t>(it->size()));
+    data.Append(it->data(), base::checked_cast<wtf_size_t>(it->size()));
     read_bytes_count += it->size();
   }
   return read_bytes_count;
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc b/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
index e3e211b..9cdabbf 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
@@ -10,6 +10,7 @@
 
 #include "base/check_op.h"
 #include "base/containers/cxx20_erase.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/time/time.h"
@@ -118,7 +119,7 @@
 
 template <typename T>
 Vector<T> ToWTFVector(const std::vector<T>& vector) {
-  Vector<T> wtf_vector(SafeCast<WTF::wtf_size_t>(vector.size()));
+  Vector<T> wtf_vector(base::checked_cast<WTF::wtf_size_t>(vector.size()));
   std::move(vector.begin(), vector.end(), wtf_vector.begin());
   return wtf_vector;
 }
@@ -320,7 +321,7 @@
       *member_
            ->cast_to<webrtc::RTCStatsMember<std::map<std::string, uint64_t>>>();
   HashMap<String, uint64_t> wtf_map;
-  wtf_map.ReserveCapacityForSize(SafeCast<unsigned>(map.size()));
+  wtf_map.ReserveCapacityForSize(base::checked_cast<unsigned>(map.size()));
   for (auto& elem : map) {
     wtf_map.insert(String::FromUTF8(elem.first), elem.second);
   }
@@ -333,7 +334,7 @@
       *member_
            ->cast_to<webrtc::RTCStatsMember<std::map<std::string, double>>>();
   HashMap<String, double> wtf_map;
-  wtf_map.ReserveCapacityForSize(SafeCast<unsigned>(map.size()));
+  wtf_map.ReserveCapacityForSize(base::checked_cast<unsigned>(map.size()));
   for (auto& elem : map) {
     wtf_map.insert(String::FromUTF8(elem.first), elem.second);
   }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 3917be4f..dee3a006 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1974,6 +1974,9 @@
       status: "experimental",
     },
     {
+      name: "QuickIntensiveWakeUpThrottlingAfterLoading",
+    },
+    {
       name: "QuotaChange",
       status: "experimental",
     },
@@ -2297,6 +2300,15 @@
       status: "experimental",
     },
     {
+      // When a Web application calls getDisplayMedia() and asks for audio,
+      // allow a hint to be provided as to whether the Web application is
+      // interested in system-audio being among the options offered to the user.
+      //
+      // https://github.com/w3c/mediacapture-screen-share/pull/222/files
+      name: "SystemAudioConstraint",
+      status: "stable",
+    },
+    {
       name: "SystemWakeLock",
       status: "experimental",
     },
diff --git a/third_party/blink/renderer/platform/scheduler/common/features.cc b/third_party/blink/renderer/platform/scheduler/common/features.cc
index 24eef30..dc076049 100644
--- a/third_party/blink/renderer/platform/scheduler/common/features.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/features.cc
@@ -77,7 +77,7 @@
       PolicyOverride::kNoOverride) {
     seconds = kIntensiveWakeUpThrottling_GracePeriodSeconds.Get();
     if (!loading && base::FeatureList::IsEnabled(
-                        kQuickIntensiveWakeUpThrottlingAfterLoading))
+                        features::kQuickIntensiveWakeUpThrottlingAfterLoading))
       seconds = kIntensiveWakeUpThrottling_GracePeriodSeconds_Loaded;
   }
   return base::Seconds(seconds);
diff --git a/third_party/blink/renderer/platform/scheduler/common/features.h b/third_party/blink/renderer/platform/scheduler/common/features.h
index 86c3d39f..b0d392a 100644
--- a/third_party/blink/renderer/platform/scheduler/common/features.h
+++ b/third_party/blink/renderer/platform/scheduler/common/features.h
@@ -134,13 +134,6 @@
 constexpr int kIntensiveWakeUpThrottling_GracePeriodSeconds_Default = 5 * 60;
 constexpr int kIntensiveWakeUpThrottling_GracePeriodSeconds_Loaded = 10;
 
-// If enabled, the grace period of features::kIntensiveWakeUpThrottling will be
-// |kIntensiveWakeUpThrottling_GracePeriodSeconds_Loaded| when a background page
-// is loaded.
-const base::Feature kQuickIntensiveWakeUpThrottlingAfterLoading{
-    "QuickIntensiveWakeUpThrottlingAfterLoading",
-    base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Exposed so that multiple tests can tinker with the policy override.
 PLATFORM_EXPORT void
 ClearIntensiveWakeUpThrottlingPolicyOverrideCacheForTesting();
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
index 053686f..1e190be 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -3676,8 +3676,9 @@
     : public FrameSchedulerImplTest {
  public:
   FrameSchedulerImplTestQuickIntensiveWakeUpThrottlingEnabled()
-      : FrameSchedulerImplTest({kQuickIntensiveWakeUpThrottlingAfterLoading},
-                               {}) {}
+      : FrameSchedulerImplTest(
+            {features::kQuickIntensiveWakeUpThrottlingAfterLoading},
+            {}) {}
 };
 
 TEST_F(FrameSchedulerImplTestQuickIntensiveWakeUpThrottlingEnabled,
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
index 4708335..d0dbdb7 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
@@ -171,10 +171,10 @@
           base::FeatureList::IsEnabled(features::kThrottleForegroundTimers)),
       foreground_timers_throttled_wake_up_interval_(
           GetForegroundTimersThrottledWakeUpInterval()) {
-  page_lifecycle_state_tracker_ = std::make_unique<PageLifecycleStateTracker>(
-      kDefaultPageVisibility == PageVisibilityState::kVisible
-          ? PageLifecycleState::kActive
-          : PageLifecycleState::kHiddenBackgrounded);
+  current_lifecycle_state_ =
+      (kDefaultPageVisibility == PageVisibilityState::kVisible
+           ? PageLifecycleState::kActive
+           : PageLifecycleState::kHiddenBackgrounded);
   do_throttle_cpu_time_callback_.Reset(base::BindRepeating(
       &PageSchedulerImpl::DoThrottleCPUTime, base::Unretained(this)));
   do_intensively_throttle_wake_ups_callback_.Reset(
@@ -215,13 +215,12 @@
 
   switch (page_visibility_) {
     case PageVisibilityState::kVisible:
-      page_lifecycle_state_tracker_->SetPageLifecycleState(
-          PageLifecycleState::kActive);
+      SetPageLifecycleState(PageLifecycleState::kActive);
       break;
     case PageVisibilityState::kHidden:
-      page_lifecycle_state_tracker_->SetPageLifecycleState(
-          IsBackgrounded() ? PageLifecycleState::kHiddenBackgrounded
-                           : PageLifecycleState::kHiddenForegrounded);
+      SetPageLifecycleState(IsBackgrounded()
+                                ? PageLifecycleState::kHiddenBackgrounded
+                                : PageLifecycleState::kHiddenForegrounded);
       break;
   }
 
@@ -271,21 +270,17 @@
       PageSchedulerImpl::NotificationPolicy::kNotifyFrames)
     NotifyFrames();
   if (frozen) {
-    page_lifecycle_state_tracker_->SetPageLifecycleState(
-        PageLifecycleState::kFrozen);
+    SetPageLifecycleState(PageLifecycleState::kFrozen);
     main_thread_scheduler_->OnPageFrozen();
   } else {
     // The new state may have already been set if unfreezing through the
     // renderer, but that's okay - duplicate state changes won't be recorded.
     if (IsPageVisible()) {
-      page_lifecycle_state_tracker_->SetPageLifecycleState(
-          PageLifecycleState::kActive);
+      SetPageLifecycleState(PageLifecycleState::kActive);
     } else if (IsBackgrounded()) {
-      page_lifecycle_state_tracker_->SetPageLifecycleState(
-          PageLifecycleState::kHiddenBackgrounded);
+      SetPageLifecycleState(PageLifecycleState::kHiddenBackgrounded);
     } else {
-      page_lifecycle_state_tracker_->SetPageLifecycleState(
-          PageLifecycleState::kHiddenForegrounded);
+      SetPageLifecycleState(PageLifecycleState::kHiddenForegrounded);
     }
     // Since the page is no longer frozen, detach the handler that watches for
     // IPCs posted to frozen pages (or cancel setting up the handler).
@@ -392,8 +387,7 @@
     audio_state_ = AudioState::kAudible;
     on_audio_silent_closure_.Cancel();
     if (!IsPageVisible()) {
-      page_lifecycle_state_tracker_->SetPageLifecycleState(
-          PageLifecycleState::kHiddenForegrounded);
+      SetPageLifecycleState(PageLifecycleState::kHiddenForegrounded);
     }
     // Pages with audio playing should not be frozen.
     SetPageFrozenImpl(false, NotificationPolicy::kDoNotNotifyFrames);
@@ -420,8 +414,7 @@
   NotifyFrames();
   main_thread_scheduler_->OnAudioStateChanged();
   if (IsBackgrounded()) {
-    page_lifecycle_state_tracker_->SetPageLifecycleState(
-        PageLifecycleState::kHiddenBackgrounded);
+    SetPageLifecycleState(PageLifecycleState::kHiddenBackgrounded);
     MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate();
   }
   if (ShouldFreezePage()) {
@@ -486,8 +479,7 @@
 
 void PageSchedulerImpl::OnVirtualTimeEnabled() {
   if (page_visibility_ == PageVisibilityState::kHidden) {
-    page_lifecycle_state_tracker_->SetPageLifecycleState(
-        PageLifecycleState::kHiddenForegrounded);
+    SetPageLifecycleState(PageLifecycleState::kHiddenForegrounded);
   }
   UpdatePolicyOnVisibilityChange(NotificationPolicy::kNotifyFrames);
 }
@@ -837,92 +829,13 @@
 }
 
 PageLifecycleState PageSchedulerImpl::GetPageLifecycleState() const {
-  return page_lifecycle_state_tracker_->GetPageLifecycleState();
+  return current_lifecycle_state_;
 }
 
-PageSchedulerImpl::PageLifecycleStateTracker::PageLifecycleStateTracker(
-    PageLifecycleState state)
-    : current_state_(kDefaultPageLifecycleState) {
-  SetPageLifecycleState(state);
-}
-
-void PageSchedulerImpl::PageLifecycleStateTracker::SetPageLifecycleState(
-    PageLifecycleState new_state) {
-  if (new_state == current_state_)
+void PageSchedulerImpl::SetPageLifecycleState(PageLifecycleState new_state) {
+  if (new_state == current_lifecycle_state_)
     return;
-  absl::optional<PageLifecycleStateTransition> transition =
-      ComputePageLifecycleStateTransition(current_state_, new_state);
-  if (transition) {
-    UMA_HISTOGRAM_ENUMERATION(
-        kHistogramPageLifecycleStateTransition,
-        static_cast<PageLifecycleStateTransition>(transition.value()));
-  }
-  current_state_ = new_state;
-}
-
-PageLifecycleState
-PageSchedulerImpl::PageLifecycleStateTracker::GetPageLifecycleState() const {
-  return current_state_;
-}
-
-// static
-absl::optional<PageSchedulerImpl::PageLifecycleStateTransition>
-PageSchedulerImpl::PageLifecycleStateTracker::
-    ComputePageLifecycleStateTransition(PageLifecycleState old_state,
-                                        PageLifecycleState new_state) {
-  switch (old_state) {
-    case PageLifecycleState::kUnknown:
-      // We don't track the initial transition.
-      return absl::nullopt;
-    case PageLifecycleState::kActive:
-      switch (new_state) {
-        case PageLifecycleState::kHiddenForegrounded:
-          return PageLifecycleStateTransition::kActiveToHiddenForegrounded;
-        case PageLifecycleState::kHiddenBackgrounded:
-          return PageLifecycleStateTransition::kActiveToHiddenBackgrounded;
-        default:
-          NOTREACHED();
-          return absl::nullopt;
-      }
-    case PageLifecycleState::kHiddenForegrounded:
-      switch (new_state) {
-        case PageLifecycleState::kActive:
-          return PageLifecycleStateTransition::kHiddenForegroundedToActive;
-        case PageLifecycleState::kHiddenBackgrounded:
-          return PageLifecycleStateTransition::
-              kHiddenForegroundedToHiddenBackgrounded;
-        case PageLifecycleState::kFrozen:
-          return PageLifecycleStateTransition::kHiddenForegroundedToFrozen;
-        default:
-          NOTREACHED();
-          return absl::nullopt;
-      }
-    case PageLifecycleState::kHiddenBackgrounded:
-      switch (new_state) {
-        case PageLifecycleState::kActive:
-          return PageLifecycleStateTransition::kHiddenBackgroundedToActive;
-        case PageLifecycleState::kHiddenForegrounded:
-          return PageLifecycleStateTransition::
-              kHiddenBackgroundedToHiddenForegrounded;
-        case PageLifecycleState::kFrozen:
-          return PageLifecycleStateTransition::kHiddenBackgroundedToFrozen;
-        default:
-          NOTREACHED();
-          return absl::nullopt;
-      }
-    case PageLifecycleState::kFrozen:
-      switch (new_state) {
-        case PageLifecycleState::kActive:
-          return PageLifecycleStateTransition::kFrozenToActive;
-        case PageLifecycleState::kHiddenForegrounded:
-          return PageLifecycleStateTransition::kFrozenToHiddenForegrounded;
-        case PageLifecycleState::kHiddenBackgrounded:
-          return PageLifecycleStateTransition::kFrozenToHiddenBackgrounded;
-        default:
-          NOTREACHED();
-          return absl::nullopt;
-      }
-  }
+  current_lifecycle_state_ = new_state;
 }
 
 FrameSchedulerImpl* PageSchedulerImpl::SelectFrameForUkmAttribution() {
@@ -964,9 +877,5 @@
           cross_origin_intensive_wake_up_budget_pool_.get()};
 }
 
-// static
-const char PageSchedulerImpl::kHistogramPageLifecycleStateTransition[] =
-    "PageScheduler.PageLifecycleStateTransition";
-
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
index d95b1cb4..17be455 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
@@ -183,30 +183,6 @@
     kMaxValue = kFrozenToHiddenBackgrounded,
   };
 
-  class PageLifecycleStateTracker {
-    USING_FAST_MALLOC(PageLifecycleStateTracker);
-
-   public:
-    explicit PageLifecycleStateTracker(PageLifecycleState);
-    PageLifecycleStateTracker(const PageLifecycleStateTracker&) = delete;
-    PageLifecycleStateTracker& operator=(const PageLifecycleStateTracker&) =
-        delete;
-    ~PageLifecycleStateTracker() = default;
-
-    void SetPageLifecycleState(PageLifecycleState);
-    PageLifecycleState GetPageLifecycleState() const;
-
-   private:
-    static absl::optional<PageLifecycleStateTransition>
-    ComputePageLifecycleStateTransition(PageLifecycleState old_state,
-                                        PageLifecycleState new_state);
-
-    static void RecordPageLifecycleStateTransition(
-        PageLifecycleStateTransition);
-
-    PageLifecycleState current_state_;
-  };
-
   void RegisterFrameSchedulerImpl(FrameSchedulerImpl* frame_scheduler);
 
   // A page cannot be throttled or frozen 30 seconds after playing audio.
@@ -217,12 +193,12 @@
   // can be increased to 30 seconds without significantly affecting performance.
   static constexpr base::TimeDelta kRecentAudioDelay = base::Seconds(30);
 
-  static const char kHistogramPageLifecycleStateTransition[];
-
   // Support not issuing a notification to frames when we disable freezing as
   // a part of foregrounding the page.
   void SetPageFrozenImpl(bool frozen, NotificationPolicy notification_policy);
 
+  void SetPageLifecycleState(PageLifecycleState state);
+
   // Adds or removes a |task_queue| from the WakeUpBudgetPool. When the
   // FrameOriginType or visibility of a FrameScheduler changes, it should remove
   // all its TaskQueues from their current WakeUpBudgetPool and add them back to
@@ -371,7 +347,7 @@
   TaskHandle set_ipc_posted_handler_task_;
   base::TimeTicks stored_in_back_forward_cache_timestamp_;
 
-  std::unique_ptr<PageLifecycleStateTracker> page_lifecycle_state_tracker_;
+  PageLifecycleState current_lifecycle_state_ = kDefaultPageLifecycleState;
   base::WeakPtrFactory<PageSchedulerImpl> weak_factory_{this};
 };
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
index 4d177b7..b9917b0 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
@@ -1475,178 +1475,6 @@
   EXPECT_FALSE(page_scheduler_->IsFrozen());
 }
 
-class PageSchedulerImplPageTransitionTest : public PageSchedulerImplTest {
- public:
-  typedef PageSchedulerImpl::PageLifecycleStateTransition Transition;
-
-  PageSchedulerImplPageTransitionTest() {
-    for (int i = 0; i <= static_cast<int>(Transition::kMaxValue); i++)
-      transition_counts_.push_back(0);
-  }
-
-  ~PageSchedulerImplPageTransitionTest() override = default;
-
-  void IncrementPageTransition(Transition transition) {
-    transition_counts_[static_cast<int>(transition)] += 1;
-  }
-
-  Vector<Bucket> GetExpectedBuckets() {
-    Vector<Bucket> buckets;
-    for (int i = 0; i <= static_cast<int>(Transition::kMaxValue); i++) {
-      if (transition_counts_[i] > 0)
-        buckets.push_back(Bucket(i, transition_counts_[i]));
-    }
-    return buckets;
-  }
-
-  void WaitForFreezingDelay() {
-    test_task_runner_->FastForwardBy(delay_for_background_tab_freezing() +
-                                     base::Milliseconds(100));
-  }
-
-  void DisableAudioAndWaitForSilent() {
-    page_scheduler_->AudioStateChanged(false);
-    test_task_runner_->FastForwardBy(recent_audio_delay() +
-                                     base::Milliseconds(100));
-  }
-
- protected:
-  Vector<int> transition_counts_;
-};
-
-TEST_F(PageSchedulerImplPageTransitionTest,
-       PageLifecycleStateTransitionMetric) {
-  typedef PageSchedulerImpl::PageLifecycleStateTransition Transition;
-
-  base::HistogramTester histogram_tester_;
-
-  if (kDefaultPageVisibility == PageVisibilityState::kHidden) {
-    page_scheduler_->SetPageVisible(true);
-    IncrementPageTransition(Transition::kHiddenBackgroundedToActive);
-    EXPECT_THAT(histogram_tester_.GetAllSamples(
-                    PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-                UnorderedElementsAreArray(GetExpectedBuckets()));
-  }
-
-  // Visible w/o audio -> hidden/backgrounded -> frozen.
-  page_scheduler_->SetPageVisible(false);
-  IncrementPageTransition(Transition::kActiveToHiddenBackgrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  WaitForFreezingDelay();
-  IncrementPageTransition(Transition::kHiddenBackgroundedToFrozen);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-
-  // Visible w/ audio -> hidden/not backgrouneded -> hidden/backgrounded ->
-  // frozen.
-  page_scheduler_->SetPageVisible(true);
-  IncrementPageTransition(Transition::kFrozenToActive);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  page_scheduler_->AudioStateChanged(true);
-  // No transition when audio state changes in the foreground.
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  page_scheduler_->SetPageVisible(false);
-  IncrementPageTransition(Transition::kActiveToHiddenForegrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  DisableAudioAndWaitForSilent();
-  IncrementPageTransition(Transition::kHiddenForegroundedToHiddenBackgrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  WaitForFreezingDelay();
-  IncrementPageTransition(Transition::kHiddenBackgroundedToFrozen);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-
-  // When freezing from outside the renderer, it's possible to have transitions
-  // to frozen from hidden/foregrounded and hidden/backgrounded.
-  //
-  // Visible w/o audio -> hidden/backgrounded -> frozen from outside the
-  // renderer.
-  page_scheduler_->SetPageVisible(true);
-  IncrementPageTransition(Transition::kFrozenToActive);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  page_scheduler_->SetPageVisible(false);
-  IncrementPageTransition(Transition::kActiveToHiddenBackgrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  page_scheduler_->SetPageFrozen(true);
-  IncrementPageTransition(Transition::kHiddenBackgroundedToFrozen);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  // Unfreezing from outside the renderer should return to hidden/backgrounded.
-  page_scheduler_->SetPageFrozen(false);
-  IncrementPageTransition(Transition::kFrozenToHiddenBackgrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-
-  // Hidden/backgrounded -> hidden/not backgrouneded -> frozen from outside the
-  // renderer.
-  page_scheduler_->AudioStateChanged(true);
-  IncrementPageTransition(Transition::kHiddenBackgroundedToHiddenForegrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  page_scheduler_->SetPageFrozen(true);
-  IncrementPageTransition(Transition::kHiddenForegroundedToFrozen);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  // Unfreezing from outside the renderer should return to hidden/foregrounded.
-  page_scheduler_->SetPageFrozen(false);
-  IncrementPageTransition(Transition::kFrozenToHiddenForegrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-
-  // Visible -> hidden* -> hidden* -> visible.
-  page_scheduler_->SetPageVisible(true);
-  IncrementPageTransition(Transition::kHiddenForegroundedToActive);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  page_scheduler_->SetPageVisible(false);
-  IncrementPageTransition(Transition::kActiveToHiddenForegrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  DisableAudioAndWaitForSilent();
-  IncrementPageTransition(Transition::kHiddenForegroundedToHiddenBackgrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  page_scheduler_->AudioStateChanged(true);
-  IncrementPageTransition(Transition::kHiddenBackgroundedToHiddenForegrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  DisableAudioAndWaitForSilent();
-  IncrementPageTransition(Transition::kHiddenForegroundedToHiddenBackgrounded);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-  page_scheduler_->SetPageVisible(true);
-  IncrementPageTransition(Transition::kHiddenBackgroundedToActive);
-  EXPECT_THAT(histogram_tester_.GetAllSamples(
-                  PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
-              UnorderedElementsAreArray(GetExpectedBuckets()));
-}
-
 }  // namespace page_scheduler_impl_unittest
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc b/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
index 45360c8..0b0cabc 100644
--- a/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
+++ b/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
@@ -619,6 +619,8 @@
   VideoCaptureStateUpdateCB state_update_cb;
 
   VideoCaptureDeliverFrameCB deliver_frame_cb;
+
+  VideoCaptureCropVersionCB crop_version_cb;
 };
 
 VideoCaptureImpl::VideoCaptureImpl(
@@ -685,7 +687,8 @@
     int client_id,
     const media::VideoCaptureParams& params,
     const VideoCaptureStateUpdateCB& state_update_cb,
-    const VideoCaptureDeliverFrameCB& deliver_frame_cb) {
+    const VideoCaptureDeliverFrameCB& deliver_frame_cb,
+    const VideoCaptureCropVersionCB& crop_version_cb) {
   DVLOG(1) << __func__ << " |device_id_| = " << device_id_;
   DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
   OnLog("VideoCaptureImpl got request to start capture.");
@@ -694,6 +697,7 @@
   client_info.params = params;
   client_info.state_update_cb = state_update_cb;
   client_info.deliver_frame_cb = deliver_frame_cb;
+  client_info.crop_version_cb = crop_version_cb;
 
   switch (state_) {
     case VIDEO_CAPTURE_STATE_STARTING:
@@ -1074,6 +1078,14 @@
   }
 }
 
+void VideoCaptureImpl::OnNewCropVersion(uint32_t crop_version) {
+  DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+
+  for (const auto& client : clients_) {
+    client.second.crop_version_cb.Run(crop_version);
+  }
+}
+
 constexpr base::TimeDelta VideoCaptureImpl::kCaptureStartTimeout;
 
 void VideoCaptureImpl::OnAllClientsFinishedConsumingFrame(
diff --git a/third_party/blink/renderer/platform/video_capture/video_capture_impl.h b/third_party/blink/renderer/platform/video_capture/video_capture_impl.h
index c7b0f63..cc56c7a8 100644
--- a/third_party/blink/renderer/platform/video_capture/video_capture_impl.h
+++ b/third_party/blink/renderer/platform/video_capture/video_capture_impl.h
@@ -76,10 +76,14 @@
   // used later to stop receiving video frames.
   // |state_update_cb| will be called when state changes.
   // |deliver_frame_cb| will be called when a frame is ready.
+  // |crop_version_cb| will be called when it is guaranteed that all
+  // subsequent frames |deliver_frame_cb| is called for, have a crop version
+  // that is equal-to-or-greater-than the given crop version.
   void StartCapture(int client_id,
                     const media::VideoCaptureParams& params,
                     const VideoCaptureStateUpdateCB& state_update_cb,
-                    const VideoCaptureDeliverFrameCB& deliver_frame_cb);
+                    const VideoCaptureDeliverFrameCB& deliver_frame_cb,
+                    const VideoCaptureCropVersionCB& crop_version_cb);
 
   // Stop capturing. |client_id| is the identifier used to call StartCapture.
   void StopCapture(int client_id);
@@ -121,6 +125,7 @@
       media::mojom::blink::ReadyBufferPtr buffer,
       Vector<media::mojom::blink::ReadyBufferPtr> scaled_buffers) override;
   void OnBufferDestroyed(int32_t buffer_id) override;
+  void OnNewCropVersion(uint32_t crop_version) override;
 
   void ProcessFeedback(const media::VideoCaptureFeedback& feedback);
 
diff --git a/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc b/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
index ea5aa8a..f2b01aaa 100644
--- a/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
+++ b/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
@@ -200,7 +200,8 @@
         &VideoCaptureImplTest::OnFrameReady, base::Unretained(this));
 
     video_capture_impl_->StartCapture(client_id, params, state_update_callback,
-                                      frame_ready_callback);
+                                      frame_ready_callback,
+                                      /*crop_version_cb=*/base::DoNothing());
   }
 
   void StopCapture(int client_id) {
diff --git a/third_party/blink/renderer/platform/video_capture/video_capturer_source.h b/third_party/blink/renderer/platform/video_capture/video_capturer_source.h
index 2c0cb6d4..6974fa1a 100644
--- a/third_party/blink/renderer/platform/video_capture/video_capturer_source.h
+++ b/third_party/blink/renderer/platform/video_capture/video_capturer_source.h
@@ -40,17 +40,24 @@
 
   // Starts capturing frames using the capture |params|. |new_frame_callback| is
   // triggered when a new video frame is available.
+  //
   // If capturing is started successfully then |running_callback| will be
   // called with a parameter of true. Note that some implementations may
   // simply reject StartCapture (by calling running_callback with a false
   // argument) if called with the wrong task runner.
+  //
   // If capturing fails to start or stopped due to an external event then
   // |running_callback| will be called with a parameter of false.
   // |running_callback| will always be called on the same thread as the
   // StartCapture.
+  //
+  // |crop_version_callback| will be called when it is guaranteed that all
+  // subsequent frames |new_frame_callback| is called for, have a crop version
+  // that is equal-to-or-greater-than the given crop version.
   virtual void StartCapture(
       const media::VideoCaptureParams& params,
       const VideoCaptureDeliverFrameCB& new_frame_callback,
+      const VideoCaptureCropVersionCB& crop_version_callback,
       const RunningCallback& running_callback) = 0;
 
   // Returns a callback for providing the feedback from the consumer.
diff --git a/third_party/blink/renderer/platform/wtf/dtoa.cc b/third_party/blink/renderer/platform/wtf/dtoa.cc
index 8ac63b5..a5e8810d 100644
--- a/third_party/blink/renderer/platform/wtf/dtoa.cc
+++ b/third_party/blink/renderer/platform/wtf/dtoa.cc
@@ -37,7 +37,7 @@
 
 #include <string.h>
 
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace WTF {
@@ -138,7 +138,7 @@
 double ParseDoubleFromLongString(const UChar* string,
                                  size_t length,
                                  size_t& parsed_length) {
-  wtf_size_t conversion_length = SafeCast<wtf_size_t>(length);
+  wtf_size_t conversion_length = base::checked_cast<wtf_size_t>(length);
   Vector<LChar> conversion_buffer(conversion_length);
   for (wtf_size_t i = 0; i < conversion_length; ++i)
     conversion_buffer[i] = IsASCII(string[i]) ? string[i] : 0;
diff --git a/third_party/blink/renderer/platform/wtf/hash_map.h b/third_party/blink/renderer/platform/wtf/hash_map.h
index db9022ec..ba3a894 100644
--- a/third_party/blink/renderer/platform/wtf/hash_map.h
+++ b/third_party/blink/renderer/platform/wtf/hash_map.h
@@ -22,6 +22,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_MAP_H_
 
 #include <initializer_list>
+
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
 #include "third_party/blink/renderer/platform/wtf/construct_traits.h"
@@ -361,8 +363,10 @@
           typename X,
           typename Y>
 HashMap<T, U, V, W, X, Y>::HashMap(std::initializer_list<ValueType> elements) {
-  if (elements.size())
-    impl_.ReserveCapacityForSize(SafeCast<wtf_size_t>(elements.size()));
+  if (elements.size()) {
+    impl_.ReserveCapacityForSize(
+        base::checked_cast<wtf_size_t>(elements.size()));
+  }
   for (const ValueType& element : elements)
     insert(element.key, element.value);
 }
diff --git a/third_party/blink/renderer/platform/wtf/hash_set.h b/third_party/blink/renderer/platform/wtf/hash_set.h
index 6a6310a2..8cbfa36 100644
--- a/third_party/blink/renderer/platform/wtf/hash_set.h
+++ b/third_party/blink/renderer/platform/wtf/hash_set.h
@@ -22,6 +22,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_HASH_SET_H_
 
 #include <initializer_list>
+
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
 #include "third_party/blink/renderer/platform/wtf/hash_table.h"
@@ -189,8 +191,10 @@
           typename Allocator>
 HashSet<Value, HashFunctions, Traits, Allocator>::HashSet(
     std::initializer_list<ValueType> elements) {
-  if (elements.size())
-    impl_.ReserveCapacityForSize(SafeCast<wtf_size_t>(elements.size()));
+  if (elements.size()) {
+    impl_.ReserveCapacityForSize(
+        base::checked_cast<wtf_size_t>(elements.size()));
+  }
   for (const ValueType& element : elements)
     insert(element);
 }
diff --git a/third_party/blink/renderer/platform/wtf/shared_buffer.cc b/third_party/blink/renderer/platform/wtf/shared_buffer.cc
index fea64485..7c9018e 100644
--- a/third_party/blink/renderer/platform/wtf/shared_buffer.cc
+++ b/third_party/blink/renderer/platform/wtf/shared_buffer.cc
@@ -191,8 +191,9 @@
     return Iterator(position, this);
 
   return Iterator(
-      SafeCast<uint32_t>(SegmentIndex(position - buffer_.size())),
-      SafeCast<uint32_t>(OffsetInSegment(position - buffer_.size())), this);
+      base::checked_cast<uint32_t>(SegmentIndex(position - buffer_.size())),
+      base::checked_cast<uint32_t>(OffsetInSegment(position - buffer_.size())),
+      this);
 }
 
 bool SharedBuffer::GetBytesInternal(void* dest, size_t dest_size) const {
@@ -229,7 +230,8 @@
   }
 
   // Merge all segments.
-  flat_buffer_.ReserveInitialCapacity(SafeCast<wtf_size_t>(buffer_->size()));
+  flat_buffer_.ReserveInitialCapacity(
+      base::checked_cast<wtf_size_t>(buffer_->size()));
   for (const auto& span : *buffer_)
     flat_buffer_.Append(span.data(), static_cast<wtf_size_t>(span.size()));
 
diff --git a/third_party/blink/renderer/platform/wtf/shared_buffer.h b/third_party/blink/renderer/platform/wtf/shared_buffer.h
index 582cf61..df884b8e 100644
--- a/third_party/blink/renderer/platform/wtf/shared_buffer.h
+++ b/third_party/blink/renderer/platform/wtf/shared_buffer.h
@@ -33,6 +33,7 @@
 
 #include "base/check_op.h"
 #include "base/containers/span.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -102,21 +103,24 @@
   HAS_STRICTLY_TYPED_ARG
   static scoped_refptr<SharedBuffer> Create(STRICTLY_TYPED_ARG(size)) {
     ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t);
-    return base::AdoptRef(new SharedBuffer(SafeCast<wtf_size_t>(size)));
+    return base::AdoptRef(
+        new SharedBuffer(base::checked_cast<wtf_size_t>(size)));
   }
 
   HAS_STRICTLY_TYPED_ARG
   static scoped_refptr<SharedBuffer> Create(const char* data,
                                             STRICTLY_TYPED_ARG(size)) {
     ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t);
-    return base::AdoptRef(new SharedBuffer(data, SafeCast<wtf_size_t>(size)));
+    return base::AdoptRef(
+        new SharedBuffer(data, base::checked_cast<wtf_size_t>(size)));
   }
 
   HAS_STRICTLY_TYPED_ARG
   static scoped_refptr<SharedBuffer> Create(const unsigned char* data,
                                             STRICTLY_TYPED_ARG(size)) {
     ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t);
-    return base::AdoptRef(new SharedBuffer(data, SafeCast<wtf_size_t>(size)));
+    return base::AdoptRef(
+        new SharedBuffer(data, base::checked_cast<wtf_size_t>(size)));
   }
 
   static scoped_refptr<SharedBuffer> AdoptVector(Vector<char>&);
@@ -228,7 +232,7 @@
 template <>
 inline Vector<char> SharedBuffer::CopyAs() const {
   Vector<char> buffer;
-  buffer.ReserveInitialCapacity(SafeCast<wtf_size_t>(size_));
+  buffer.ReserveInitialCapacity(base::checked_cast<wtf_size_t>(size_));
 
   for (const auto& span : *this)
     buffer.Append(span.data(), static_cast<wtf_size_t>(span.size()));
@@ -240,7 +244,7 @@
 template <>
 inline Vector<uint8_t> SharedBuffer::CopyAs() const {
   Vector<uint8_t> buffer;
-  buffer.ReserveInitialCapacity(SafeCast<wtf_size_t>(size_));
+  buffer.ReserveInitialCapacity(base::checked_cast<wtf_size_t>(size_));
 
   for (const auto& span : *this) {
     buffer.Append(reinterpret_cast<const uint8_t*>(span.data()),
diff --git a/third_party/blink/renderer/platform/wtf/std_lib_extras.h b/third_party/blink/renderer/platform/wtf/std_lib_extras.h
index 83a432d1..2609649 100644
--- a/third_party/blink/renderer/platform/wtf/std_lib_extras.h
+++ b/third_party/blink/renderer/platform/wtf/std_lib_extras.h
@@ -30,7 +30,6 @@
 
 #include "base/check.h"
 #include "base/dcheck_is_on.h"
-#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/wtf/leak_annotations.h"
 #include "third_party/blink/renderer/platform/wtf/sanitizers.h"
@@ -218,11 +217,6 @@
 
 namespace WTF {
 
-template <typename To, typename From>
-inline To SafeCast(From value) {
-  return base::checked_cast<To>(value);
-}
-
 // Use the following macros to prevent errors caused by accidental
 // implicit casting of function arguments.  For example, this can
 // be used to prevent overflows from non-promoting conversions.
@@ -262,6 +256,4 @@
 
 }  // namespace WTF
 
-using WTF::SafeCast;
-
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_STD_LIB_EXTRAS_H_
diff --git a/third_party/blink/renderer/platform/wtf/text/atomic_string.cc b/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
index e80ae33..0b94246 100644
--- a/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
+++ b/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
@@ -23,6 +23,7 @@
 
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/dtoa.h"
 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string_table.h"
@@ -36,7 +37,7 @@
 
 #if defined(ARCH_CPU_64_BITS)
 AtomicString::AtomicString(const LChar* chars, size_t length)
-    : AtomicString(chars, SafeCast<unsigned>(length)) {}
+    : AtomicString(chars, base::checked_cast<unsigned>(length)) {}
 #endif  // defined(ARCH_CPU_64_BITS)
 
 AtomicString::AtomicString(const LChar* chars, unsigned length)
diff --git a/third_party/blink/renderer/platform/wtf/text/string_builder.h b/third_party/blink/renderer/platform/wtf/text/string_builder.h
index 214115c..b342dde 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_builder.h
+++ b/third_party/blink/renderer/platform/wtf/text/string_builder.h
@@ -29,6 +29,7 @@
 
 #include <unicode/utf16.h>
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 #include "third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_view.h"
@@ -303,8 +304,9 @@
 // EqualIgnoringUnicodeCase(). See crbug.com/627682
 inline bool DeprecatedEqualIgnoringCase(const StringBuilder& s,
                                         const char* string) {
-  return DeprecatedEqualIgnoringCase(s, reinterpret_cast<const LChar*>(string),
-                                     SafeCast<wtf_size_t>(strlen(string)));
+  return DeprecatedEqualIgnoringCase(
+      s, reinterpret_cast<const LChar*>(string),
+      base::checked_cast<wtf_size_t>(strlen(string)));
 }
 
 template <typename StringType>
diff --git a/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc b/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc
index f2f21914..36695da 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc
+++ b/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc
@@ -6,10 +6,11 @@
 
 #include "third_party/blink/renderer/platform/wtf/text/string_concatenate.h"
 
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
 
 WTF::StringTypeAdapter<char*>::StringTypeAdapter(char* buffer, size_t length)
-    : buffer_(buffer), length_(SafeCast<unsigned>(length)) {}
+    : buffer_(buffer), length_(base::checked_cast<unsigned>(length)) {}
 
 void WTF::StringTypeAdapter<char*>::WriteTo(LChar* destination) const {
   for (unsigned i = 0; i < length_; ++i)
@@ -25,7 +26,8 @@
 
 WTF::StringTypeAdapter<LChar*>::StringTypeAdapter(LChar* buffer)
     : buffer_(buffer),
-      length_(SafeCast<wtf_size_t>(strlen(reinterpret_cast<char*>(buffer)))) {}
+      length_(base::checked_cast<wtf_size_t>(
+          strlen(reinterpret_cast<char*>(buffer)))) {}
 
 void WTF::StringTypeAdapter<LChar*>::WriteTo(LChar* destination) const {
   memcpy(destination, buffer_, length_ * sizeof(LChar));
@@ -43,7 +45,8 @@
 }
 
 WTF::StringTypeAdapter<const char*>::StringTypeAdapter(const char* buffer)
-    : buffer_(buffer), length_(SafeCast<wtf_size_t>(strlen(buffer))) {}
+    : buffer_(buffer),
+      length_(base::checked_cast<wtf_size_t>(strlen(buffer))) {}
 
 void WTF::StringTypeAdapter<const char*>::WriteTo(LChar* destination) const {
   memcpy(destination, buffer_, static_cast<size_t>(length_) * sizeof(LChar));
@@ -58,9 +61,8 @@
 
 WTF::StringTypeAdapter<const LChar*>::StringTypeAdapter(const LChar* buffer)
     : buffer_(buffer),
-      length_(
-          SafeCast<wtf_size_t>(strlen(reinterpret_cast<const char*>(buffer)))) {
-}
+      length_(base::checked_cast<wtf_size_t>(
+          strlen(reinterpret_cast<const char*>(buffer)))) {}
 
 void WTF::StringTypeAdapter<const LChar*>::WriteTo(LChar* destination) const {
   memcpy(destination, buffer_, static_cast<size_t>(length_) * sizeof(LChar));
diff --git a/third_party/blink/renderer/platform/wtf/text/string_impl.cc b/third_party/blink/renderer/platform/wtf/text/string_impl.cc
index 9ac5ef7..374ddf6 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_impl.cc
+++ b/third_party/blink/renderer/platform/wtf/text/string_impl.cc
@@ -27,7 +27,9 @@
 
 #include <algorithm>
 #include <memory>
+
 #include "base/callback.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
 #include "third_party/blink/renderer/platform/wtf/dynamic_annotations.h"
 #include "third_party/blink/renderer/platform/wtf/leak_annotations.h"
@@ -294,7 +296,7 @@
   if (!string)
     return empty_;
   size_t length = strlen(reinterpret_cast<const char*>(string));
-  return Create(string, SafeCast<wtf_size_t>(length));
+  return Create(string, base::checked_cast<wtf_size_t>(length));
 }
 
 bool StringImpl::ContainsOnlyWhitespaceOrEmpty() {
diff --git a/third_party/blink/renderer/platform/wtf/text/string_impl.h b/third_party/blink/renderer/platform/wtf/text/string_impl.h
index 64206317..a756a15f9 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_impl.h
+++ b/third_party/blink/renderer/platform/wtf/text/string_impl.h
@@ -26,6 +26,7 @@
 
 #include <limits.h>
 #include <string.h>
+
 #include <atomic>
 
 #include "base/callback_forward.h"
@@ -34,6 +35,7 @@
 #include "base/dcheck_is_on.h"
 #include "base/memory/ref_counted.h"
 #include "base/numerics/checked_math.h"
+#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -851,7 +853,7 @@
   size_t length = 0;
   while (string[length] != UChar(0))
     ++length;
-  return SafeCast<wtf_size_t>(length);
+  return base::checked_cast<wtf_size_t>(length);
 }
 
 template <wtf_size_t inlineCapacity>
diff --git a/third_party/blink/renderer/platform/wtf/text/string_view.h b/third_party/blink/renderer/platform/wtf/text/string_view.h
index fd7ed08d..3230521b 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_view.h
+++ b/third_party/blink/renderer/platform/wtf/text/string_view.h
@@ -10,9 +10,9 @@
 
 #include "base/containers/span.h"
 #include "base/dcheck_is_on.h"
+#include "base/numerics/safe_conversions.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/get_ptr.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
 
 #if DCHECK_IS_ON()
@@ -125,7 +125,7 @@
       : StringView(reinterpret_cast<const LChar*>(chars), length) {}
   StringView(const LChar* chars)
       : StringView(chars,
-                   chars ? SafeCast<unsigned>(
+                   chars ? base::checked_cast<unsigned>(
                                strlen(reinterpret_cast<const char*>(chars)))
                          : 0) {}
   StringView(const char* chars)
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.cc b/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
index 8883211..96669195 100644
--- a/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
+++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
@@ -29,6 +29,7 @@
 
 #include "base/callback.h"
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/wtf/dtoa.h"
@@ -71,10 +72,10 @@
 
 #if defined(ARCH_CPU_64_BITS)
 String::String(const UChar* characters, size_t length)
-    : String(characters, SafeCast<unsigned>(length)) {}
+    : String(characters, base::checked_cast<unsigned>(length)) {}
 
 String::String(const char* characters, size_t length)
-    : String(characters, SafeCast<unsigned>(length)) {}
+    : String(characters, base::checked_cast<unsigned>(length)) {}
 #endif  // defined(ARCH_CPU_64_BITS)
 
 int CodeUnitCompare(const String& a, const String& b) {
@@ -488,7 +489,7 @@
 }
 
 String String::FromUTF8(const LChar* string_start, size_t string_length) {
-  wtf_size_t length = SafeCast<wtf_size_t>(string_length);
+  wtf_size_t length = base::checked_cast<wtf_size_t>(string_length);
 
   if (!string_start)
     return String();
@@ -530,7 +531,7 @@
 String String::FromUTF8WithLatin1Fallback(const LChar* string, size_t size) {
   String utf8 = FromUTF8(string, size);
   if (!utf8)
-    return String(string, SafeCast<wtf_size_t>(size));
+    return String(string, base::checked_cast<wtf_size_t>(size));
   return utf8;
 }
 
diff --git a/third_party/blink/renderer/platform/wtf/vector.h b/third_party/blink/renderer/platform/wtf/vector.h
index 6d2e442..960c13a 100644
--- a/third_party/blink/renderer/platform/wtf/vector.h
+++ b/third_party/blink/renderer/platform/wtf/vector.h
@@ -22,6 +22,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_VECTOR_H_
 
 #include <string.h>
+
 #include <algorithm>
 #include <initializer_list>
 #include <iterator>
@@ -30,6 +31,7 @@
 #include "base/check_op.h"
 #include "base/compiler_specific.h"
 #include "base/dcheck_is_on.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/template_util.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
@@ -1501,7 +1503,7 @@
 
 template <typename T, wtf_size_t inlineCapacity, typename Allocator>
 Vector<T, inlineCapacity, Allocator>::Vector(std::initializer_list<T> elements)
-    : Base(SafeCast<wtf_size_t>(elements.size())) {
+    : Base(base::checked_cast<wtf_size_t>(elements.size())) {
   ANNOTATE_NEW_BUFFER(begin(), capacity(), elements.size());
   size_ = static_cast<wtf_size_t>(elements.size());
   TypeOperations::UninitializedCopy(elements.begin(), elements.end(), begin());
@@ -1510,7 +1512,7 @@
 template <typename T, wtf_size_t inlineCapacity, typename Allocator>
 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::
 operator=(std::initializer_list<T> elements) {
-  wtf_size_t input_size = SafeCast<wtf_size_t>(elements.size());
+  wtf_size_t input_size = base::checked_cast<wtf_size_t>(elements.size());
   if (size() > input_size) {
     Shrink(input_size);
   } else if (input_size > capacity()) {
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py b/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
index 2d7cd6f..7219875 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
@@ -478,12 +478,14 @@
         """Returns (testharness_completed, testharness_failures)."""
         if not driver_output.text:
             return False, []
-        if expected_driver_output.text:
-            # Will compare text if there is expected text.
-            return False, []
         if not testharness_results.is_testharness_output(
                 self._convert_to_str(driver_output.text)):
             return False, []
+        if self._options.ignore_testharness_expected_txt:
+            expected_driver_output.text = b''
+        elif expected_driver_output.text:
+            # Will compare text if there is expected text.
+            return False, []
         if not testharness_results.is_testharness_output_passing(
                 self._convert_to_str(driver_output.text)):
             return True, [
diff --git a/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py b/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
index e48f88d..79e2364 100644
--- a/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
+++ b/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
@@ -633,6 +633,12 @@
                 help=(
                     'The Buildbucket ID of the bot running the test. This is '
                     'only used for an experimental Skia Gold dryrun.')),
+            optparse.make_option(
+                '--ignore-testharness-expected-txt',
+                action='store_true',
+                help=('Ignore *-expected.txt for all testharness tests. All '
+                      'testharness test failures will be shown, even if the '
+                      'failures are expected in *-expected.txt.')),
         ]))
 
     # FIXME: Move these into json_results_generator.py.
diff --git a/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py b/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py
index e71b165..0742eb55 100644
--- a/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py
@@ -2190,6 +2190,37 @@
         self.assertEqual(run_details.exit_code, 0)
         self.assertNotIn('Please remove', log_stream.getvalue())
 
+    def test_testharness_expected_txt(self):
+        host = MockHost()
+        test_name = '/failures/unexpected/testharness.html'
+        expected_txt = (test.WEB_TEST_DIR +
+                        '/failures/unexpected/testharness-expected.txt')
+        # The expected.txt contains the same content as the actual output.
+        host.filesystem.write_text_file(
+            expected_txt, 'This is a testharness.js-based test.\nFAIL: bah\n'
+            'Harness: the test ran to completion.')
+
+        # Run without --ignore-testharness-expected.txt. The test should pass.
+        run_details, _, _ = logging_run([test_name],
+                                        tests_included=True,
+                                        host=host)
+        self.assertEqual(run_details.exit_code, 0)
+
+        # Run with --ignore-testharness-expected.txt. The test should fail.
+        run_details, _, _ = logging_run(
+            ['--ignore-testharness-expected-txt', test_name],
+            tests_included=True,
+            host=host)
+        self.assertNotEqual(run_details.exit_code, 0)
+        self.assertEqual(run_details.initial_results.total, 1)
+        test_result = run_details.initial_results.all_results[0]
+        self.assertEqual(test_result.test_name, test_name)
+        self.assertEqual(len(test_result.failures), 1)
+        self.assertTrue(
+            test_failures.has_failure_type(
+                test_failures.FailureTestHarnessAssertion,
+                test_result.failures))
+
     def test_additional_platform_directory(self):
         self.assertTrue(
             passing_run([
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index d53ac11d..d4404d2 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -1796,6 +1796,7 @@
 
 crbug.com/1321217 virtual/document-transition/wpt_internal/document-transition/old-content-with-overflow.html [ Skip ]
 crbug.com/1321217 virtual/document-transition/wpt_internal/document-transition/new-content-with-overflow.html [ Skip ]
+crbug.com/1303102 virtual/document-transition/wpt_internal/document-transition/no-root-capture.html [ Skip ]
 
 # only NGHighlightPainter has the ability to paint decorations added by ::target-text
 crbug.com/1223918 wpt_internal/css/css-pseudo/target-text-001.html [ Failure ]
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
index 4a71030..daf0f4f7 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
+++ b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
@@ -37,6 +37,11 @@
 http/tests/inspector-protocol/target/message-to-detached-session.js [ Skip ]
 virtual/fenced-frame-mparch/http/tests/inspector-protocol/fenced-frame/fenced-frame-in-oopif-auto-attach.js [ Skip ]
 
+# Rely on OOPIF for an iframe to be a separate devtools target
+http/tests/inspector-protocol/timeline/auction-worklet-frame.js [ Skip ]
+virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-frame.js [ Skip ]
+
+
 # Fix to unblock wpt-importer
 crbug.com/1209223 external/wpt/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-security-check-multi-globals.sub.html [ Failure ]
 crbug.com/1209223 external/wpt/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-security-check-same-origin-domain.sub.html [ Failure ]
diff --git a/third_party/blink/web_tests/FlagSpecificConfig b/third_party/blink/web_tests/FlagSpecificConfig
index 07e8bd0b..197b6d0 100644
--- a/third_party/blink/web_tests/FlagSpecificConfig
+++ b/third_party/blink/web_tests/FlagSpecificConfig
@@ -4,6 +4,10 @@
     "args": ["--enable-features=BackForwardCache"]
   },
   {
+    "name": "back-forward-cache-embed",
+    "args": ["--enable-features=BackForwardCacheEnabledForNonPluginEmbed"]
+  },
+  {
     "name": "disable-layout-ng",
     "args": ["--disable-blink-features=LayoutNG,LayoutNGBlockFragmentation"]
   },
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index ae762a5..de4363d 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -156,9 +156,6 @@
 fast/scrolling/scrollbars/mouse-scrolling-on-div-scrollbar-thumb-scaled.html [ Skip ]
 virtual/threaded-prefer-compositing/fast/scrolling/scrollbars/mouse-scrolling-on-div-scrollbar-thumb-scaled.html [ Pass ]
 
-# Android doesn't support plugins
-virtual/android/fullscreen/rendering/backdrop-object.html [ Skip ]
-
 # Missing Chrome Mac support, will start working when we move to harfbuzz on mac.
 [ Mac ] virtual/text-antialias/international/zerowidthjoiner.html [ Skip ]
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index d3733d1..65288f7e 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -30,7 +30,6 @@
 crbug.com/1304217 http/tests/devtools/text-source-map.js [ Skip ]
 crbug.com/1304217 http/tests/devtools/runtime/runtime-getProperties.js [ Skip ] # Bug 1325812
 crbug.com/1304217 http/tests/devtools/runtime/runtime-localStorage-getProperties.js [ Skip ] # Bug 1325812
-crbug.com/1334930 http/tests/devtools/sources/debugger/debugger-disable-enable.js [ Skip ]
 
 # Expected to time out.
 external/wpt/infrastructure/expected-fail/timeout.html [ Timeout ]
@@ -394,6 +393,8 @@
 crbug.com/841567 [ Linux ] virtual/threaded-prefer-compositing/fast/scrolling/overflow-scrollability.html [ Failure Pass Timeout ]
 crbug.com/841567 [ Debug Mac11 ] virtual/threaded-prefer-compositing/fast/scrolling/same-page-navigate.html [ Failure Pass ]
 
+crbug.com/1335172 [ Mac11-arm64 ] virtual/threaded-prefer-compositing/fast/scrolling/inertial-scrolling-with-pointer-events-none-overlay.html [ Failure Pass ]
+
 crbug.com/915926 fast/events/touch/multi-touch-user-gesture.html [ Failure Pass ]
 
 crbug.com/736052 [ Mac ] compositing/overflow/composited-scroll-with-fractional-translation.html [ Failure Pass ]
@@ -1603,6 +1604,7 @@
 virtual/layout_ng_table_frag/external/wpt/css/css-break/table/break-before-table-cell.html [ Pass ]
 virtual/layout_ng_table_frag/external/wpt/css/css-break/table/break-before-table-cell-child.html [ Pass ]
 virtual/layout_ng_table_frag/external/wpt/css/css-break/table/repeated-section/abspos.tentative.html [ Pass ]
+virtual/layout_ng_table_frag/external/wpt/css/css-break/table/repeated-section/abspos-in-monolithic.tentative.html [ Pass ]
 virtual/layout_ng_table_frag/external/wpt/css/css-break/table/repeated-section/block-in-inline.tentative.html [ Pass ]
 virtual/layout_ng_table_frag/external/wpt/css/css-break/table/repeated-section/captions.tentative.html [ Pass ]
 virtual/layout_ng_table_frag/external/wpt/css/css-break/table/repeated-section/footer.tentative.html [ Pass ]
@@ -1811,6 +1813,7 @@
 crbug.com/753671 [ Mac12-arm64 ] external/wpt/css/css-content/quotes-020.html [ Failure ]
 crbug.com/753671 external/wpt/css/css-content/quotes-021.html [ Failure ]
 crbug.com/753671 external/wpt/css/css-content/quotes-022.html [ Failure ]
+crbug.com/753671 external/wpt/css/css-content/quotes-030.html [ Failure ]
 crbug.com/1067277 external/wpt/css/css-content/element-replacement-on-replaced-element.tentative.html [ Failure ]
 
 crbug.com/1335893 external/wpt/css/css-content/content-none-root-columns.html [ Failure ]
@@ -2040,8 +2043,6 @@
 crbug.com/1232504 [ Mac12 ] external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html [ Failure Timeout ]
 
 crbug.com/1292852 [ Mac ] external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-focus-shadow.html [ Failure Pass ]
-crbug.com/1301716 external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-replaced-renderer.html [ Failure ]
-crbug.com/1301716 external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-table-column.html [ Failure ]
 
 # XML nodes aren't match by .class selectors:
 crbug.com/649444 external/wpt/css/selectors/xml-class-selector.xml [ Failure ]
@@ -3360,6 +3361,10 @@
 crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Mac10.14 ] external/wpt/fetch/api/response/response-clone.any.serviceworker.html [ Timeout ]
+crbug.com/626703 [ Mac10.14 ] external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/broadcast-channel.html [ Timeout ]
+crbug.com/626703 [ Mac12 ] virtual/conversions-debug-mode/wpt_internal/attribution-reporting/navigation-source-trigger-data-cardinality-test.sub.https.html [ Timeout ]
+crbug.com/626703 [ Mac12 ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/registered-property-value-006.https.html [ Failure ]
 crbug.com/626703 [ Mac11 ] virtual/conversions-debug-mode/wpt_internal/attribution-reporting/simple-event-level-report-test.sub.https.html [ Timeout ]
 crbug.com/626703 [ Mac11 ] virtual/conversions-debug-mode/wpt_internal/attribution-reporting/simple-aggregatable-report-test.sub.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/WebCryptoAPI/derive_bits_keys/cfrg_curves_bits.https.any.worker.html [ Crash Failure ]
@@ -3927,6 +3932,7 @@
 crbug.com/1078927 external/wpt/css/css-break/table/break-before-table-cell.html [ Failure ]
 crbug.com/1078927 external/wpt/css/css-break/table/break-before-table-cell-child.html [ Failure ]
 crbug.com/1078927 external/wpt/css/css-break/table/repeated-section/abspos.tentative.html [ Failure ]
+crbug.com/1078927 external/wpt/css/css-break/table/repeated-section/abspos-in-monolithic.tentative.html [ Failure ]
 crbug.com/1078927 external/wpt/css/css-break/table/repeated-section/block-in-inline.tentative.html [ Failure ]
 crbug.com/1078927 external/wpt/css/css-break/table/repeated-section/captions.tentative.html [ Failure ]
 crbug.com/1078927 external/wpt/css/css-break/table/repeated-section/footer.tentative.html [ Failure ]
@@ -6777,11 +6783,6 @@
 crbug.com/1285275 virtual/fenced-frame-mparch/external/wpt/html/anonymous-iframe/cache-storage.tentative.https.window.html [ Pass Timeout ]
 crbug.com/1285275 virtual/fenced-frame-shadow-dom/external/wpt/html/anonymous-iframe/cache-storage.tentative.https.window.html [ Pass Timeout ]
 crbug.com/1285275 virtual/partitioned-cookies/external/wpt/html/anonymous-iframe/cache-storage.tentative.https.window.html [ Pass Timeout ]
-#
-# The PolicyContainer's anonymous bit is unintendedly inherited toward the
-# fenced frame with the MPArch implementation. It causes:
-# Check failed: parent_ || !IsAnonymous().
-crbug.com/1287458 virtual/fenced-frame-mparch/external/wpt/html/anonymous-iframe/fenced-frame.tentative.https.window.html [ Crash ]
 
 # Sheriff 2022-03-10
 crbug.com/1304956 storage/indexeddb/dont-wedge.html [ Failure Pass ]
@@ -7040,5 +7041,8 @@
 # Temporarily disable test to merge DevTools top layer support
 crbug.com/1313690 http/tests/devtools/elements/iframe-load-event.js [ Skip ]
 
-# Temporarily disable to land DOMStorage changes
-crbug.com/1337796 http/tests/devtools/debugger/stop-on-debugger-from-detached-iframe.js [ Skip ]
+# Sheriff 2022-06-22
+crbug.com/1338420 [ Linux ] external/wpt/event-timing/interactionid-tap.html [ Skip ]
+
+# Flaky on multiple platforms
+crbug.com/1338536 http/tests/devtools/oopif/oopif-elements-nesting.js [ Failure Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 2e02ce8..3fe2bce 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -705,6 +705,12 @@
     "args": ["--force-color-profile=color-spin-gamma24"]
   },
   {
+    "prefix": "wide-gamut",
+    "platforms": ["Linux", "Mac", "Win"],
+    "bases": [],
+    "args": ["--force-color-profile=display-p3-d65"]
+  },
+  {
     "prefix": "split-cache-by-include-credentials",
     "platforms": ["Linux", "Mac", "Win"],
     "bases": ["external/wpt/fetch/http-cache"],
@@ -1072,6 +1078,8 @@
     "bases": [
       "http/tests/inspector-protocol/target/auto-attach-auction-worklet.js",
       "http/tests/inspector-protocol/target/target-auction-worklet.js",
+      "http/tests/inspector-protocol/timeline/auction-worklet.js",
+      "http/tests/inspector-protocol/timeline/auction-worklet-frame.js",
       "http/tests/inspector-protocol/storage/interest-groups.js"
     ],
     "args": [
diff --git a/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations b/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations
index 00645f9d..cca4bdc 100644
--- a/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations
+++ b/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations
@@ -802,8 +802,6 @@
 crbug.com/1050754 external/wpt/focus/activeelement-after-focusing-different-site-iframe.html [ Pass ]
 crbug.com/1050754 external/wpt/focus/activeelement-after-focusing-same-site-iframe-contentwindow.html [ Pass ]
 crbug.com/1050754 external/wpt/focus/activeelement-after-focusing-same-site-iframe.html [ Pass ]
-crbug.com/1050754 external/wpt/focus/focus-event-after-focusing-iframes.html [ Crash Failure Pass ]
-crbug.com/1050754 external/wpt/focus/focus-event-after-iframe-gets-focus.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/focus/focus-restoration-in-different-site-iframes-window.html [ Pass ]
 crbug.com/1050754 external/wpt/focus/focus-restoration-in-different-site-iframes.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/focus/focus-restoration-in-same-site-iframes-window.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations b/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations
index e8166521..1e4972c 100644
--- a/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations
+++ b/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations
@@ -944,8 +944,6 @@
 crbug.com/1050754 external/wpt/focus/activeelement-after-focusing-same-site-iframe-contentwindow.html [ Pass ]
 crbug.com/1050754 external/wpt/focus/activeelement-after-focusing-same-site-iframe.html [ Pass ]
 crbug.com/1050754 external/wpt/focus/focus-already-focused-iframe-deep-different-site.html [ Pass ]
-crbug.com/1050754 external/wpt/focus/focus-event-after-focusing-iframes.html [ Pass ]
-crbug.com/1050754 external/wpt/focus/focus-event-after-iframe-gets-focus.html [ Pass ]
 crbug.com/1050754 external/wpt/focus/focus-restoration-in-different-site-iframes-window.html [ Pass ]
 crbug.com/1050754 external/wpt/focus/focus-restoration-in-different-site-iframes.html [ Pass ]
 crbug.com/1050754 external/wpt/focus/focus-restoration-in-same-site-iframes-window.html [ Pass ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index 61ec6f623..e2ff4ec 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: bd23d172241f5bdd356368a1ef05a649d8a79bad
+Version: cc4ca5bbe25751e48f46aeb4cc4232780732d3ea
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 7d824fd..4fd376d 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -381,6 +381,13 @@
        ]
       ]
      },
+     "gradient-wrong-interpolation-crash.html": [
+      "5aefb64297112feaa8fb314522e5a4406e6ea3bb",
+      [
+       null,
+       {}
+      ]
+     ],
      "linear-gradient-calc-crash.html": [
       "5ae6104a7941b836ab700ca50b5dbe20914afcf6",
       [
@@ -1073,6 +1080,20 @@
          null,
          {}
         ]
+       ],
+       "table-in-columns-004-crash.html": [
+        "daed42f00945ba98d8fbc7dae40e4a563832de3e",
+        [
+         null,
+         {}
+        ]
+       ],
+       "table-in-columns-005-crash.html": [
+        "60d6f9d3a1f7e04a417b3f06b08663ece6f2f7d3",
+        [
+         null,
+         {}
+        ]
        ]
       }
      },
@@ -1516,6 +1537,13 @@
        {}
       ]
      ],
+     "float-becomes-inflow-crash.html": [
+      "c820b093ce332abc2bce9c58456cb67fe268f637",
+      [
+       null,
+       {}
+      ]
+     ],
      "inline-002-crash.html": [
       "a10eee9907f3ca27b3265452aeb19e2b9710b55d",
       [
@@ -1903,6 +1931,13 @@
         {}
        ]
       ],
+      "nested-spanner-with-negative-margin.html": [
+       "3a9b2e354ce50332e2b6ad845e0cd071cd59a770",
+       [
+        null,
+        {}
+       ]
+      ],
       "nested-with-fragmented-oof-negative-top-offset.html": [
        "38f62888a6383d4045ae2c13f66e98c2657ad531",
        [
@@ -2850,6 +2885,13 @@
         null,
         {}
        ]
+      ],
+      "zero-perspective-001.html": [
+       "923794ed60cd5c25f93922eaa72b84e3a8357b84",
+       [
+        null,
+        {}
+       ]
       ]
      },
      "large-matrix-crash.html": [
@@ -15301,7 +15343,7 @@
    },
    "window-placement": {
     "fullscreen-companion-window-manual.tentative.https.html": [
-     "fe82916aa26cc488e23567d4a2ccfeff33884ed4",
+     "c2fa2f1ddde8faf3039842f0b451cc42d8a01f70",
      [
       null,
       {}
@@ -80273,6 +80315,19 @@
        {}
       ]
      ],
+     "abspos-inside-relpos-inside-monolithic.html": [
+      "879097f3fc2a7c933a1c2bea460beed1f6bc5e2b",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "avoid-border-break.html": [
       "56f47e83c57f0914b87910870d67d5490d9e4eb3",
       [
@@ -86883,6 +86938,19 @@
        ]
       ],
       "repeated-section": {
+       "abspos-in-monolithic.tentative.html": [
+        "6ec70d030d233a8183bbf281503235e2cb005b66",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
        "abspos.tentative.html": [
         "a7297f1dd559f5bb38a1143d0371d17d4ee29bba",
         [
@@ -96977,7 +97045,7 @@
       ]
      ],
      "contain-style-counters-002.html": [
-      "d585674dc29bab0ffe0702959a07126c7da3d75c",
+      "48494ce2be7f7e0039acc8327187417a3b64c495",
       [
        null,
        [
@@ -149073,6 +149141,32 @@
         {}
        ]
       ],
+      "position-sticky-fixed-ancestor-002.html": [
+       "dc3c383ea5e9c89498898ce9f53af273dbfbc51d",
+       [
+        null,
+        [
+         [
+          "/css/css-position/sticky/reference/position-sticky-fixed-ancestor-002-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "position-sticky-fixed-ancestor-003.html": [
+       "382112cae42f1391d7bb4f55c413f29f04b64c49",
+       [
+        null,
+        [
+         [
+          "/css/css-position/sticky/reference/position-sticky-fixed-ancestor-002-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "position-sticky-fixed-ancestor-iframe.html": [
        "e50f5c829b6bcee84385083648bca5cc145e1e37",
        [
@@ -149372,6 +149466,19 @@
         {}
        ]
       ],
+      "position-sticky-stacking-context-002.html": [
+       "1cc162880a37559fd2879912b4418cbba9cbe7cb",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "position-sticky-stacking-context.html": [
        "4e91dfbd9177b51ab231e0cf2634aa6425981236",
        [
@@ -162641,6 +162748,19 @@
        {}
       ]
      ],
+     "absolute-tables-016.html": [
+      "f8eb1516ae4d725c5c1bda4abbe67cea346737ca",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "anonymous-table-cell-margin-collapsing.html": [
       "23b467ebacc983122a632f4d5971c8daca569420",
       [
@@ -230505,6 +230625,36 @@
      ]
     ]
    },
+   "fullscreen": {
+    "rendering": {
+     "backdrop-iframe.html": [
+      "710d1b48f182d0fcb577298c72bbf6a7f7329dbf",
+      [
+       null,
+       [
+        [
+         "/fullscreen/rendering/backdrop-iframe-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "backdrop-object.html": [
+      "be285b76124def6099b9954d0125117ed65a4917",
+      [
+       null,
+       [
+        [
+         "/fullscreen/rendering/backdrop-object-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ]
+    }
+   },
    "html": {
     "browsers": {
      "sandboxing": {
@@ -237195,6 +237345,32 @@
          {}
         ]
        ],
+       "modal-dialog-in-iframe.html": [
+        "f6440583fb7c5546405d6440a740e9a4d64d9100",
+        [
+         null,
+         [
+          [
+           "/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-iframe-ref.html",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "modal-dialog-in-object.html": [
+        "728748a7ee38fb335ab1aeece3892054d02fd7d9",
+        [
+         null,
+         [
+          [
+           "/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-object-ref.html",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
        "modal-dialog-in-replaced-renderer.html": [
         "75727b42f0429e59ffa1940eef768060e706af8c",
         [
@@ -264292,7 +264468,7 @@
        []
       ],
       "quote-scoping-002-ref.html": [
-       "8b846e2a999b3d20f3729285084fc762f261e525",
+       "c7239e3f4857eb6fd206beee1c13bccc833d429e",
        []
       ],
       "quote-scoping-003-ref.html": [
@@ -281198,6 +281374,10 @@
         "253ca7eebedb1e8c4216a969854bf57f9f3a0d50",
         []
        ],
+       "position-sticky-fixed-ancestor-002-ref.html": [
+        "abdc1dbcfa7ea243cc0f86db1d061e1efc201e38",
+        []
+       ],
        "position-sticky-left-002-ref.html": [
         "75aa9a4c1f4dc9fd5a13ea4f96f77d44491b598f",
         []
@@ -297973,7 +298153,7 @@
       []
      ],
      "insertparagraph.js": [
-      "784678161243b4931a80e36bd302f73ed56aac63",
+      "24d16f873ab7952c778cc373a12df73b573a33b6",
       []
      ],
      "inserttext.js": [
@@ -300896,7 +301076,7 @@
        []
       ],
       "x-content-type-options.json": [
-       "0a8c490756e674bacd7d78e1ad20dc6752abee8d",
+       "080fc1990bf948e94733e8d231d738c8f4c6e1cd",
        []
       ]
      }
@@ -301141,11 +301321,11 @@
       []
      ],
      "activeelement-after-calling-window-focus-outer-different.sub.html": [
-      "0c2f8f792da46107b5dc98e6b69d9fc0f6bb9f06",
+      "2cddcf233dbd618b3ba42868c7b191f7d89ff8e9",
       []
      ],
      "activeelement-after-calling-window-focus-outer-same.sub.html": [
-      "cabdb26b347e0505f2bf131632b48cad008ca850",
+      "4833e94bc9414c461d6779e5a762e9d2833ceeea",
       []
      ],
      "activeelement-after-focusing-different-site-iframe-inner-contentwindow.html": [
@@ -301241,11 +301421,11 @@
       []
      ],
      "focus-event-after-different-site-iframe-gets-focus-outer.sub.html": [
-      "c59b2ce72f8dcbab5528e9ea0d1c2f39062503fd",
+      "da107ab8a27e739695bac72b7ec63e6cbbd4df4b",
       []
      ],
      "focus-event-after-focusing-different-site-iframes-outer.sub.html": [
-      "7d2fb504d661d5a919f4d8141444d2b626c3aaeb",
+      "7c02a6b6409a117087a3b1ba390bd5bf0bc0f212",
       []
      ],
      "focus-event-after-focusing-iframes-inner.html": [
@@ -301253,7 +301433,7 @@
       []
      ],
      "focus-event-after-focusing-same-site-iframes-outer.html": [
-      "08f2c3f7ae2b1205158d1ce1f4c70c6742e9c330",
+      "9147b681c2dbe784911ba1367bb525fe18080260",
       []
      ],
      "focus-event-after-iframe-gets-focus-inner.html": [
@@ -301265,11 +301445,11 @@
       []
      ],
      "focus-event-after-innermost-different-site-iframe-gets-focus-outer.sub.html": [
-      "12af71e8aaed38ea7227eba72a9a95368897388b",
+      "fc0fb50e432fccd3140d0b675128956a7548a130",
       []
      ],
      "focus-event-after-same-site-iframe-gets-focus-outer.html": [
-      "b191be580eae1862aef4bffa9d3f46b89af98140",
+      "c6799f0edb9a6be8a5223ba86c3051e043373b64",
       []
      ],
      "focus-restoration-in-different-site-iframes-inner-window.html": [
@@ -302541,6 +302721,16 @@
       ]
      }
     },
+    "rendering": {
+     "backdrop-iframe-ref.html": [
+      "3126fe194261f7ce7f6039885e4ec73e7a997468",
+      []
+     ],
+     "backdrop-object-ref.html": [
+      "6c7071a727dd27d182ae017e9f6dbc0834361ddc",
+      []
+     ]
+    },
     "trusted-click.js": [
      "7ee0669eece3e341ef76da4dd153e5ec05ccb288",
      []
@@ -302812,13 +303002,17 @@
          []
         ],
         "helper.sub.js": [
-         "ff446f5ee9d3c884f9867f05d2f736d3c752b100",
+         "4b42d91670252f929306fcda2e34dd4e61ea3265",
          []
         ],
         "inflight-fetch-helper.js": [
          "7832003b76b9518d5f3588bb5e9f6e0dbd8cea07",
          []
         ],
+        "service-worker.js": [
+         "60dceb0a6a6f5f2cf882610e3bd19e15e9533458",
+         []
+        ],
         "slow.py": [
          "01bb3309b103d5bba772bdbf1d0d0b8bc28c8e99",
          []
@@ -311896,7 +312090,7 @@
       "bfcache": {
        "resources": {
         "common.js": [
-         "9c852bbfb3ed1d607b69de96fb3717cb4725e23e",
+         "5bb9642a83abe07612b43f35fd87f7ca00f6932c",
          []
         ]
        }
@@ -313426,6 +313620,14 @@
         "10c9897c63b9fcc8137161880af3568c538f9d2b",
         []
        ],
+       "modal-dialog-in-iframe-ref.html": [
+        "b6c52b7d7df88c91fbf2111b9bdfcccbc22a56cc",
+        []
+       ],
+       "modal-dialog-in-object-ref.html": [
+        "38e15c1d79d65f75b04ba4501db3481c17980b7d",
+        []
+       ],
        "modal-dialog-in-replaced-renderer-ref.html": [
         "c837503cafbcdb56c995e9b93f49cabde14293b0",
         []
@@ -316746,7 +316948,7 @@
        []
       ],
       "structured-clone-battery-of-tests.js": [
-       "aefab049e63679065417d44b4364a2f0f9ee5dfe",
+       "580a81aaea6405cccc29f3651ce7c0ab19a6f3bd",
        []
       ]
      },
@@ -316873,6 +317075,10 @@
     ]
    },
    "images": {
+    "100px-green-rect.svg": [
+     "c391055bc27b96c166ec0a6a8e4ab8077597442e",
+     []
+    ],
     "DIR_METADATA": [
      "9b0121386d1d5435a8420caea934ef0d59a826aa",
      []
@@ -328572,7 +328778,7 @@
        []
       ],
       "update-max-aged-worker.py": [
-       "4f879069ef98ad7ff738cf144fe1fd75fdd1089e",
+       "221ef771d9bc8adb6bc3a42b11d95e8acae55f1c",
        []
       ],
       "update-missing-import-scripts-imported-worker.py": [
@@ -373333,7 +373539,7 @@
        ]
       ],
       "system-color-valid.html": [
-       "1174f496d6565fbc5a67416df5069b216667acf7",
+       "05447292b7843ae49b2e378911b987198bf13603",
        [
         null,
         {}
@@ -384157,7 +384363,7 @@
        ]
       ],
       "position-sticky-scrolled-remove-sibling.html": [
-       "f2cf8a98b30a2c19a986d31bc4da99f0bdd8df9d",
+       "845454e1b3d6c53b47412a7557a23ed5a87aa17a",
        [
         null,
         {}
@@ -399968,7 +400174,7 @@
       ]
      ],
      "has-error-recovery.html": [
-      "143638c9e325f13576a02e19151a42eec4684408",
+      "b435d8c8f350e0b7afb93585d860276bcc803c6f",
       [
        null,
        {}
@@ -400540,7 +400746,7 @@
        ]
       ],
       "target-pseudo-in-has.html": [
-       "7b51508c25ff9d3b1fbc2d3fa873cf1f9b585ec2",
+       "3f0ea16a1cb5d804e1a301dfd6c2c0ee3db7b3ac",
        [
         null,
         {}
@@ -400725,7 +400931,7 @@
         {}
        ]
       ],
-      "parse-has-disallow-nesting-has-inside-has.tentative.html": [
+      "parse-has-disallow-nesting-has-inside-has.html": [
        "0a30718df04f61a6aad451daad841147b616dc38",
        [
         null,
@@ -432930,7 +433136,7 @@
    },
    "focus": {
     "activeelement-after-calling-window-focus.sub.html": [
-     "f854ffb36ce462f0caaffc9996d2a0425e8e6356",
+     "34579fb2a6301bacdc5e069e214d833f59564c59",
      [
       null,
       {
@@ -433030,14 +433236,14 @@
      ]
     ],
     "focus-event-after-focusing-iframes.html": [
-     "b7076a2e480b85911193b3080905ca4d8e854a42",
+     "f2aa2233e560eb6e73b20fe753386ef74ac282e7",
      [
       null,
       {}
      ]
     ],
     "focus-event-after-iframe-gets-focus.html": [
-     "32c4d544b6ca9dfb6df752a7b62a6f4c836a8fe2",
+     "bb2e8954209ee99ad0a683f0ab9d57fd2d878f73",
      [
       null,
       {}
@@ -436151,6 +436357,42 @@
          }
         ]
        ],
+       "service-worker-clients-claim.https.html": [
+        "d9540c221bdf21e8e4256f30548aedbfee46e218",
+        [
+         null,
+         {
+          "timeout": "long"
+         }
+        ]
+       ],
+       "service-worker-clients-matchall.https.html": [
+        "069529dbe477c642e7396b0cd021d2f43d5e1e08",
+        [
+         null,
+         {
+          "timeout": "long"
+         }
+        ]
+       ],
+       "service-worker-controlled-after-restore.https.html": [
+        "a937eb85ac572d519bacfd265ac2f9bb7031b76b",
+        [
+         null,
+         {
+          "timeout": "long"
+         }
+        ]
+       ],
+       "service-worker-unregister.https.html": [
+        "1c3f81153c2a17a3dfc719d2cccca2079525b630",
+        [
+         null,
+         {
+          "timeout": "long"
+         }
+        ]
+       ],
        "storage-events.html": [
         "6957496c3077acd5e87fa3127febfbcbbfb80099",
         [
@@ -467055,42 +467297,42 @@
      },
      "embedded-content": {
       "bfcache": {
-       "embeded-html.html": [
+       "embedded-html.html": [
         "0808538337710337f9dc8705bf1c951266b027f8",
         [
          null,
          {}
         ]
        ],
-       "embeded-img.html": [
+       "embedded-img.html": [
         "7e9d713c0a79cb64d99cb2b27c32c60713453d59",
         [
          null,
          {}
         ]
        ],
-       "embeded-js.html": [
+       "embedded-js.html": [
         "c3b027563d32e55ada6d45bfddc43afe0640e87a",
         [
          null,
          {}
         ]
        ],
-       "embeded-mp4.html": [
+       "embedded-mp4.html": [
         "fde560e5be95dfb067cd54aa5bad303e59b32e6e",
         [
          null,
          {}
         ]
        ],
-       "embeded-not-found.html": [
+       "embedded-not-found.html": [
         "0b56b5eadc536b131f386ab2724637d024e8f204",
         [
          null,
          {}
         ]
        ],
-       "embeded-type-only.html": [
+       "embedded-type-only.html": [
         "90c9d3311c3096c646d628c75402106afeb54470",
         [
          null,
@@ -470405,7 +470647,7 @@
         ]
        ],
        "sandbox-inherit-to-blank-document-unsandboxed.html": [
-        "f60ab0da30ad82ff9a87d41af60fe68c96d29939",
+        "26b30cf72b73dab37535253c22a6aac3b53be364",
         [
          null,
          {}
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/default-src/default-src-strict_dynamic_and_unsafe_inline.html b/third_party/blink/web_tests/external/wpt/content-security-policy/default-src/default-src-strict_dynamic_and_unsafe_inline.html
new file mode 100644
index 0000000..bf45820
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/default-src/default-src-strict_dynamic_and_unsafe_inline.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+
+<head>
+    <title>`strict-dynamic` policy should discard `unsafe-inline` policy.</title>
+    <script src='/resources/testharness.js'></script>
+    <script src='/resources/testharnessreport.js'></script>
+    <script>
+      var t = async_test("Should fire a security policy violation for the inline block");
+      window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
+        assert_equals(e.blockedURI, 'inline');
+      }));
+    </script>
+    <meta http-equiv="Content-Security-Policy" content="default-src 'unsafe-inline' 'strict-dynamic'">
+</head>
+
+<body>
+  <script>
+      assert_unreached('Inline script shouldn\'t be run because of the `strict-dynamic` source expression.');
+  </script>
+</body>
+
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/gradient-wrong-interpolation-crash.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/gradient-wrong-interpolation-crash.html
new file mode 100644
index 0000000..5aefb64
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/gradient-wrong-interpolation-crash.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<link rel=help href="https://buzil.la/1772555">
+<style>
+  * {
+    background: center / cover border-box, currentcolor right 55882ch center / cover content-box radial-gradient(58ch 94% ellipse at left 28Q top 34%, hsl(60 71% 7% / 0.3204252445367216) -1610731402em, -31pt, hsla(2.9234077762890767rad, 58%, 56%, 0%) 26%) local repeat-x;
+  }
+</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/abspos-inside-relpos-inside-monolithic.html b/third_party/blink/web_tests/external/wpt/css/css-break/abspos-inside-relpos-inside-monolithic.html
new file mode 100644
index 0000000..879097f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/abspos-inside-relpos-inside-monolithic.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1336634">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="columns:1; width:100px; background:red;">
+  <div style="height:40px; background:green;"></div>
+  <div style="overflow:hidden;">
+    <div style="position:relative; height:60px;">
+      <div style="position:absolute; width:100%; height:60px; background:green;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/table/repeated-section/abspos-in-monolithic.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-break/table/repeated-section/abspos-in-monolithic.tentative.html
new file mode 100644
index 0000000..6ec70d0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/table/repeated-section/abspos-in-monolithic.tentative.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-tables-3/#repeated-headers">
+<link rel="match" href="../../../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="columns:2; column-fill:auto; gap:0; width:100px; height:100px; background:red;">
+  <div style="display:table; width:100%;">
+    <div style="display:table-header-group; break-inside:avoid;">
+      <div style="position:relative; top:-5px; left:-5px; contain:size; width:50px; height:20px;">
+        <div style="position:absolute; top:5px; left:5px; width:50px; height:20px; background:green;"></div>
+      </div>
+    </div>
+    <div style="height:160px; background:green;"></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/system-color-valid.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/system-color-valid.html
index 1174f49..0544729 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/system-color-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/system-color-valid.html
@@ -28,6 +28,8 @@
 test_valid_value("color", "VisitedText", "visitedtext");
 test_valid_value("color", "SelectedItem", "selecteditem");
 test_valid_value("color", "SelectedItemText", "selecteditemtext");
+test_valid_value("color", "AccentColor", "accentcolor");
+test_valid_value("color", "AccentColorText", "accentcolortext");
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/contain-style-counters-002.html b/third_party/blink/web_tests/external/wpt/css/css-contain/contain-style-counters-002.html
index d585674..48494ce2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-contain/contain-style-counters-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/contain-style-counters-002.html
@@ -5,6 +5,7 @@
   <title>CSS Containment Test: 'contain: style' and counter (with 'display: contents')</title>
 
   <link rel="help" href="https://www.w3.org/TR/css-contain-1/#containment-style">
+  <link rel=help href="https://github.com/w3c/csswg-drafts/issues/7392">
   <link rel="match" href="reference/contain-style-counters-001-ref.html">
 
   <meta content="This test checks that when an element has 'contain: style', then counters which may be affecting its subtree are reset to 0 for such scope. In this test, the div#test does not generate a principal box because of 'display: contents'. Despite that particular condition, 'contain: style' will have an effect on div#test." name="assert">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/crashtests/table-in-columns-004-crash.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/crashtests/table-in-columns-004-crash.html
new file mode 100644
index 0000000..daed42f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/crashtests/table-in-columns-004-crash.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>CSS Container Queries Crash Test</title>
+<link rel="help" href="https://crbug.com/1338055">
+<p>Pass if no crash</p>
+<div style="container-type:inline-size">
+  <span style="columns: 1">
+    <canvas>
+      <script>
+        document.body.offsetTop;
+      </script>
+      <div style="container-type:inline-size">
+        <span style="display:table-column-group"></span>
+      </div>
+    </canvas>
+  </span>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/crashtests/table-in-columns-005-crash.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/crashtests/table-in-columns-005-crash.html
new file mode 100644
index 0000000..60d6f9d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/crashtests/table-in-columns-005-crash.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>CSS Container Queries Crash Test</title>
+<link rel="help" href="https://crbug.com/1336334">
+<li style="container-type:inline-size">
+  <span style="columns:2">
+    <table></table>
+  </span>
+</li>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/reference/quote-scoping-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-contain/reference/quote-scoping-002-ref.html
index 8b846e2..c7239e3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-contain/reference/quote-scoping-002-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/reference/quote-scoping-002-ref.html
@@ -4,5 +4,5 @@
   <title>CSS-contain test reference</title>
   <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
 
-<p>Test passes if the text below is "A9Z" (not including the quotation marks).<p>
-<div>A9Z</span></div>
+<p>Test passes if the text below is "AZZ" (not including the quotation marks).<p>
+<div>AZZ</span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-content/quotes-030.html b/third_party/blink/web_tests/external/wpt/css/css-content/quotes-030.html
index 2c793ea..095c37fe 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-content/quotes-030.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-content/quotes-030.html
@@ -12,9 +12,6 @@
 body { font: 32px Arial, Helvetica, Noto Sans, DejaVu Sans, FreeSans, sans-serif; quotes: auto; }
 </style>
 <body>
-<p>Test passes if the quote marks in each pair of lines match:
+<p>Test passes if the quote marks in both lines match:
 <p>One <q>two <q lang="ja">three <q lang="fr">four</q></q></q>
 <p>One “two <span lang="ja">‘three <span lang="fr">『four』</span>’</span>”
-
-<p>One <q>two <q lang="ja">three <q>four</q></q></q>
-<p>One “two <span lang="ja">‘three 『four』’</span>”
diff --git a/third_party/blink/web_tests/external/wpt/css/css-content/reference/quotes-030-ref.html b/third_party/blink/web_tests/external/wpt/css/css-content/reference/quotes-030-ref.html
index 36608c3..c06d85b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-content/reference/quotes-030-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-content/reference/quotes-030-ref.html
@@ -7,9 +7,6 @@
 body { font: 32px Arial, Helvetica, Noto Sans, DejaVu Sans, FreeSans, sans-serif; quotes: auto; }
 </style>
 <body>
-<p>Test passes if the quote marks in each pair of lines match:
+<p>Test passes if the quote marks in both lines match:
 <p>One “two <span lang="ja">‘three <span lang="fr">『four』</span>’</span>”
 <p>One “two <span lang="ja">‘three <span lang="fr">『four』</span>’</span>”
-
-<p>One “two <span lang="ja">‘three 『four』’</span>”
-<p>One “two <span lang="ja">‘three 『four』’</span>”
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-fixed-ancestor-002.html b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-fixed-ancestor-002.html
new file mode 100644
index 0000000..dc3c383
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-fixed-ancestor-002.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Positioned Layout Test: a sticky element inside a fixed ancestor</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="match" href="reference/position-sticky-fixed-ancestor-002-ref.html">
+  <link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos">
+
+  <meta name="flags" content="">
+
+  <style>
+  html, body, div
+    {
+      height: 100%;
+      margin: 0;
+      width: 100%;
+    }
+
+  div#positioned-container
+    {
+      background-color: red;
+      color: yellow;
+      font-size: 40vh;
+      position: absolute;
+    }
+
+  div#sticky
+    {
+      background-color: green;
+      bottom: 0;
+      color: white;
+      position: sticky;
+    }
+  </style>
+
+  <script type="text/javascript">
+  function startTest()
+  {
+  document.getElementById("positioned-container").style.position = "fixed";
+  }
+  </script>
+
+ <body onload="startTest();">
+
+    <div id="positioned-container">
+
+      <div id="vertical-spacer">FAIL</div>
+
+      <div id="sticky">PASS</div>
+
+    </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-fixed-ancestor-003.html b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-fixed-ancestor-003.html
new file mode 100644
index 0000000..382112c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-fixed-ancestor-003.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Positioned Layout Test: a sticky element inside a fixed ancestor</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="match" href="reference/position-sticky-fixed-ancestor-002-ref.html">
+  <link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos">
+
+  <meta name="flags" content="">
+
+  <style>
+  html, body, div
+    {
+      height: 100%;
+      margin: 0;
+      width: 100%;
+    }
+
+  div#fixed-container
+    {
+      background-color: red;
+      color: yellow;
+      font-size: 40vh;
+      position: fixed;
+    }
+
+  div#sticky
+    {
+      background-color: green;
+      bottom: 0;
+      color: white;
+      position: sticky;
+    }
+  </style>
+
+    <div id="fixed-container">
+
+      <div id="vertical-spacer">FAIL</div>
+
+      <div id="sticky">PASS</div>
+
+    </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scrolled-remove-sibling.html b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scrolled-remove-sibling.html
index f2cf8a98..845454e1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scrolled-remove-sibling.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scrolled-remove-sibling.html
@@ -1,21 +1,99 @@
 <!DOCTYPE html>
-<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
-<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos">
-<p>Test passes if there is a filled green square, and no scrollbars</p>
-<div id="container" style="overflow:auto; width:100px; height:100px; background:red;">
-  <div style="position:sticky; top:0; height:100px; background:green;"></div>
-  <div id="bigItem" style="height:600px;"></div>
-</div>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-  container.scrollTop = 600;
-  requestAnimationFrame(()=>{
-    requestAnimationFrame(()=>{
-      bigItem.style.display = "none";
-      test(()=> {
-        assert_equals(container.scrollHeight, 100);
-      }, "Sticky position and its overflow contribution");
-    });
-  });
-</script>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Positioned Layout Test: element with 'position: sticky' and removing a sibling in the vertical axis and in the horizontal axis</title>
+
+  <link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos">
+
+  <meta name="flags" content="">
+
+  <style>
+  div#scrollingContainerVert
+    {
+      background-color: red;
+      height: 100px;
+      overflow: auto;
+      width: 200px;
+    }
+
+  div#scrollingContainerHoriz
+    {
+      background-color: red;
+      height: 100px;
+      overflow-x: auto;
+      overflow-y: hidden;
+      width: 200px;
+    }
+
+  div#elemStickyVert
+    {
+      background-color: green;
+      height: 100px;
+      position: sticky;
+      top: 0px;
+    }
+
+  div#scrollingContainerHoriz > div
+    {
+      display: inline-block;
+      height: 100%;
+    }
+
+  div#elemStickyHoriz
+    {
+      background-color: green;
+      left: 0px;
+      position: sticky;
+      width: 200px;
+    }
+
+  div#tallItem
+    {
+      height: 600px;
+    }
+
+  div#wideItem
+    {
+      width: 600px;
+    }
+  </style>
+
+
+  <script src="/resources/testharness.js"></script>
+
+  <script src="/resources/testharnessreport.js"></script>
+
+  <p>Test passes if there is a filled green square and <strong>no scrollbar</strong>.
+
+  <div id="scrollingContainerVert">
+
+    <div id="elemStickyVert"></div>
+
+    <div id="tallItem"></div>
+
+  </div>
+
+
+  <div id="scrollingContainerHoriz">
+
+    <div id="elemStickyHoriz"></div><div id="wideItem"></div>
+
+  </div>
+
+
+  <script>
+  test(()=> {
+  scrollingContainerVert.scrollTop = 600;
+  tallItem.style.display = "none";
+  assert_equals(scrollingContainerVert.scrollHeight, 100);
+  }, "Sticky position and its overflow contribution in the vertical axis");
+
+  test(()=> {
+  scrollingContainerHoriz.scrollLeft = 600;
+  wideItem.style.display = "none";
+  assert_equals(scrollingContainerHoriz.scrollWidth, 200);
+  }, "Sticky position and its overflow contribution in the horizontal axis");
+  </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-stacking-context-002.html b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-stacking-context-002.html
new file mode 100644
index 0000000..1cc16288
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-stacking-context-002.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Positioned Layout Test: an element with 'position: sticky' creates a stacking context</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+  <link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos">
+
+  <meta name="assert" content="This test checks that an element with 'position: sticky' creates a stacking context. In this test, the first 2 divs have the same 'auto' z-index value but since div#sticky is last in document tree order, then it must overlap div#overlapped-red. The final div#overlap-bottom-half-of-sticky exists to make sure that the div#sticky is squeezed, is 'sandwiched' between the other 2.">
+
+  <style>
+  div
+    {
+      height: 100px;
+      width: 100px;
+    }
+
+  div#overlapped-red
+    {
+      background-color: red;
+      position: absolute;
+    }
+
+  div#sticky
+    {
+      background: linear-gradient(to bottom, green 51%, red 49%);
+      position: sticky;
+    }
+
+  div#overlap-bottom-half-of-sticky
+    {
+      background-color: green;
+      bottom: 50px;
+      height: 50px;
+      position: relative;
+    }
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.
+
+  <div id="overlapped-red"></div>
+
+  <div id="sticky"></div>
+
+  <div id="overlap-bottom-half-of-sticky"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/reference/position-sticky-fixed-ancestor-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/reference/position-sticky-fixed-ancestor-002-ref.html
new file mode 100644
index 0000000..abdc1db
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/reference/position-sticky-fixed-ancestor-002-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+
+ <meta charset="UTF-8">
+
+ <title>CSS Reference File</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+
+  <style>
+  html, body, div
+    {
+      background-color: green;
+      color: white;
+      font-size: 40vh;
+      height: 100%;
+      margin: 0;
+    }
+  </style>
+
+  <div>PASS</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-016.html b/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-016.html
new file mode 100644
index 0000000..f8eb151
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-tables/absolute-tables-016.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test: Abspos table centered in both axes with auto margins</title>
+<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1480636">
+<link rel="help" href="https://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width">
+<meta name="assert" content="An absolutely-positioned fixed-size table should resolve auto margins the same way that a similarly-sized block would.">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<style>
+.container {
+  /* I've chosen this position/size so that a 100px child element that's
+     centered within us will be placed at our "normal" position (where our
+     top-left corner would be, in the absence of relative positioning), so we
+     can use the simple filled-green-100px-square reference case. */
+  position: relative;
+  left: -30px;
+  top: -30px;
+  width: 160px;
+  height: 160px;
+}
+.target {
+  display: block;
+  background: red;
+}
+.table {
+  display: table;
+  background: green;
+}
+.centered {
+  position: absolute;
+  width: 100px;
+  height: 100px;
+  inset: 0;
+  margin: auto; /* use auto margins for centering */
+}
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div class="container">
+  <!-- We're essentially just comparing the position of the block ("target")
+       and the table. We expect them to be placed at precisely the same spot,
+       so no red should be visible. -->
+  <div class="centered target"></div>
+  <div class="centered table"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/crashtests/zero-perspective-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/crashtests/zero-perspective-001.html
new file mode 100644
index 0000000..923794e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/crashtests/zero-perspective-001.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset="utf-8">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1772640">
+<div id="test">
+<style>
+* {
+  overflow-x: scroll;
+  perspective: 0px;
+}
+#a {
+  rotate: 1deg 0 1 0;
+}
+</style>
+<ul id="a">IjzXS</ul>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/target-pseudo-in-has.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/target-pseudo-in-has.html
index 7b51508c..3f0ea16 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/target-pseudo-in-has.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/target-pseudo-in-has.html
@@ -72,6 +72,8 @@
 
     // Wait for :target to be detected.
     await new Promise(r => requestAnimationFrame(r));
+    // Wait again to avoid flaky test result. (https://crbug.com/1334635)
+    await new Promise(r => requestAnimationFrame(r));
 
     assert_true(fragment2.matches(":target"));
     assert_equals(getComputedStyle(parent2).color, GREEN, "parent2 should be green after re-appending :target child");
diff --git a/third_party/blink/web_tests/external/wpt/editing/data/insertparagraph.js b/third_party/blink/web_tests/external/wpt/editing/data/insertparagraph.js
index 7846781..24d16f8 100644
--- a/third_party/blink/web_tests/external/wpt/editing/data/insertparagraph.js
+++ b/third_party/blink/web_tests/external/wpt/editing/data/insertparagraph.js
@@ -2095,4 +2095,201 @@
      "<div>a &nbsp;</div><div>&nbsp;&nbsp;b</div>"],
     [true,true],
     {"insertparagraph":[false,false,"",false,false,""]}],
+
+// insertparagraph with selecting all text in a <div> which is the only
+// block in the editing host.
+// In this case, the <div> should be unwrapped and a <br> element should be
+// put there, then, new paragraph should be created after it.
+["<div>[abc]</div>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<br><div><br></div>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<div>[abc]</div>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<br><p><br></p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+
+// insertparagraph with selecting all text in a <p> which is the only block in
+// the editing host.
+// In this case, the <p> element should become empty but stay here, and new <p>
+// element should be created.
+["<p>[abc]</p>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<p><br></p><p><br></p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<p>[abc]</p>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<p><br></p><p><br></p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+
+// insertparagraph with selecting all text in a paragraph which is not only
+// block in the editing host.
+// In this case, new same element should be created rather than respecting the
+// default paragraph separator, and caret should be moved to the new paragraph.
+["<div>abc</div><div>[def]</div>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<div>abc</div><div><br></div><div><br></div>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<div>abc</div><p>[def]</p>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<div>abc</div><p><br></p><p><br></p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<div>abc</div><div>[def]</div>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<div>abc</div><div><br></div><div><br></div>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<div>abc</div><p>[def]</p>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<div>abc</div><p><br></p><p><br></p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<div>abc</div><div>[def]</div>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]],
+    ["<div>abc</div><div><br></div><div>d</div>",
+     "<div>abc</div><div><br></div><div>d<br></div>"],
+    [true,true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<div>abc</div><p>[def]</p>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]],
+    ["<div>abc</div><p><br></p><p>d</p>",
+     "<div>abc</div><p><br></p><p>d<br></p>"],
+    [true,true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+
+// insertparagraph with selecting all text in a list-item which is only one of
+// the list.
+// In this case, the list and list-item elements should be unwrapped and create
+// a new paragraph whose type conforms to the default paragraph separator.
+["<ol><li>[abc]</li></ol>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<div><br></div>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<ol><li>[abc]</li></ol>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<p><br></p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<ol><li>[abc]</li></ol>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]],
+    ["<div>d</div>",
+     "<div>d<br></div>"],
+    [true,true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+
+// insertparagraph with selecting all text in a list-item which is the last
+// list item in the list.
+// In this case, the last list item should be deleted and new paragraph should
+// be created after the list element.
+["<ol><li>abc</li><li>[def]</li></ol>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<ol><li>abc</li></ol><div><br></div>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<ol><li>abc</li><li>[def]</li></ol>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<ol><li>abc</li></ol><p><br></p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<ol><li>abc</li><li>[def]</li></ol>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]],
+    ["<ol><li>abc</li></ol><div>d</div>",
+     "<ol><li>abc</li></ol><div>d<br></div>"],
+    [true,true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+
+// insertparagraph with selecting all text in a list-item which is not a middle
+// list item in the list.
+// In this case, the list should be split at the list item, and new paragraph
+// should be created between the list elements.
+["<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<ol><li>abc</li></ol><div><br></div><ol><li>ghi</li></ol>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<ol><li>abc</li></ol><p><br></p><ol><li>ghi</li></ol>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]],
+    ["<ol><li>abc</li></ol><div>d</div><ol><li>ghi</li></ol>",
+     "<ol><li>abc</li></ol><div>d<br></div><ol><li>ghi</li></ol>"],
+    [true,true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+
+// insertparagraph with selecting all text in a list-item which is the first
+// list item in the list.
+// In this case, the first list item should be deleted and new paragraph should
+// be created before the list element.
+["<ol><li>[abc]</li><li>def</li></ol>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<div><br></div><ol><li>def</li></ol>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<ol><li>[abc]</li><li>def</li></ol>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<p><br></p><ol><li>def</li></ol>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<ol><li>[abc]</li><li>def</li></ol>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]],
+    ["<div>a</div><ol><li>def</li></ol>",
+     "<div>a<br></div><ol><li>def</li></ol>"],
+    [true,true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+
+// insertparagraph with selecting all text in a heading element.
+// In this case, the heading element should become empty, but stay there, and
+// a new paragraph should be created after it.
+["<h3>[abc]</h3>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<h3><br></h3><div><br></div>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<h3>[abc]</h3>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<h3><br></h3><p><br></p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<h3>[abc]</h3>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]],
+    ["<h3><br></h3><div>a</div>",
+     "<h3><br></h3><div>a<br></div>"],
+    [true,true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+
+// insertparagraph with selecting all text in a heading element which is
+// followed by a paragraph.
+// In this case, the heading element should become empty, but stay there, and
+// insert a new paragraph immediately after the heading element.
+["<h3>[abc]</h3><div>def</div>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<h3><br></h3><div><br></div><div>def</div>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<h3>[abc]</h3><div>def</div>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<h3><br></h3><p><br></p><div>def</div>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<h3>[abc]</h3><p>def</p>",
+    [["defaultparagraphseparator","div"],["insertparagraph",""]],
+    "<h3><br></h3><div><br></div><p>def</p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+["<h3>[abc]</h3><p>def</p>",
+    [["defaultparagraphseparator","p"],["insertparagraph",""]],
+    "<h3><br></h3><p><br></p><p>def</p>",
+    [true,true],
+    {"insertparagraph":[false,false,"",false,false,""]}],
+
 ]
diff --git a/third_party/blink/web_tests/external/wpt/fetch/nosniff/resources/x-content-type-options.json b/third_party/blink/web_tests/external/wpt/fetch/nosniff/resources/x-content-type-options.json
index 0a8c490..080fc19 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/nosniff/resources/x-content-type-options.json
+++ b/third_party/blink/web_tests/external/wpt/fetch/nosniff/resources/x-content-type-options.json
@@ -28,6 +28,10 @@
     "nosniff": false
   },
   {
+    "input": "X-Content-Type-Options: nosniff\r\nX-Content-Type-Options: nosniff",
+    "nosniff": true
+  },
+  {
     "input": "X-Content-Type-Options: ,nosniff",
     "nosniff": false
   },
diff --git a/third_party/blink/web_tests/external/wpt/focus/activeelement-after-calling-window-focus.sub.html b/third_party/blink/web_tests/external/wpt/focus/activeelement-after-calling-window-focus.sub.html
index f854ffb3..34579fb 100644
--- a/third_party/blink/web_tests/external/wpt/focus/activeelement-after-calling-window-focus.sub.html
+++ b/third_party/blink/web_tests/external/wpt/focus/activeelement-after-calling-window-focus.sub.html
@@ -16,6 +16,10 @@
   });
 }
 
+function start(w) {
+  w.postMessage("start", "*");
+}
+
 function focusInnerInput(w) {
   w.postMessage("focusinnerinput", "*");
 }
@@ -51,6 +55,7 @@
   let w = window.open(url);
   t.add_cleanup(() => { w.close(); });
   await waitForEvent(window, "message", e => e.data === "ready");
+  start(w);
   // Calling input.focus() on inner iframe should move its document.activeElement to INPUT.
   focusInnerInput(w);
   assert_equals(await getLog(w), 'outerlog:windowblur,middlelog:innerlog:windowfocus,INPUT,');
diff --git a/third_party/blink/web_tests/external/wpt/focus/focus-event-after-focusing-iframes.html b/third_party/blink/web_tests/external/wpt/focus/focus-event-after-focusing-iframes.html
index b7076a2e..f2aa2233 100644
--- a/third_party/blink/web_tests/external/wpt/focus/focus-event-after-focusing-iframes.html
+++ b/third_party/blink/web_tests/external/wpt/focus/focus-event-after-focusing-iframes.html
@@ -15,6 +15,10 @@
   });
 }
 
+function start(w) {
+  w.postMessage("start", "*");
+}
+
 function focusIframe(w) {
   w.postMessage("focus", "*");
 }
@@ -38,6 +42,7 @@
   let w = window.open(url);
   t.add_cleanup(() => { w.close(); });
   await waitForEvent(window, "message", e => e.data === "ready");
+  start(w);
   focusIframe(w);
   assert_equals(await getLog(w), 'outerlog:willfocusiframe,windowblur,didfocusiframe,innerlog:windowfocus,');
   focusIframe(w);
diff --git a/third_party/blink/web_tests/external/wpt/focus/focus-event-after-iframe-gets-focus.html b/third_party/blink/web_tests/external/wpt/focus/focus-event-after-iframe-gets-focus.html
index 32c4d544..bb2e895 100644
--- a/third_party/blink/web_tests/external/wpt/focus/focus-event-after-iframe-gets-focus.html
+++ b/third_party/blink/web_tests/external/wpt/focus/focus-event-after-iframe-gets-focus.html
@@ -15,6 +15,10 @@
   });
 }
 
+function start(w) {
+  w.postMessage("start", "*");
+}
+
 function focusIframe(w) {
   w.postMessage("focus", "*");
 }
@@ -38,6 +42,7 @@
   let w = window.open(url);
   t.add_cleanup(() => { w.close(); });
   await waitForEvent(window, "message", e => e.data === "ready");
+  start(w);
   focusIframe(w);
   assert_equals(await getLog(w), expectResult);
 }
diff --git a/third_party/blink/web_tests/external/wpt/focus/support/activeelement-after-calling-window-focus-outer-different.sub.html b/third_party/blink/web_tests/external/wpt/focus/support/activeelement-after-calling-window-focus-outer-different.sub.html
index 0c2f8f79..2cddcf2 100644
--- a/third_party/blink/web_tests/external/wpt/focus/support/activeelement-after-calling-window-focus-outer-different.sub.html
+++ b/third_party/blink/web_tests/external/wpt/focus/support/activeelement-after-calling-window-focus-outer-different.sub.html
@@ -7,8 +7,12 @@
 
 let iframe = document.querySelector("iframe");
 window.onmessage = function(e) {
-   if (e.data == "ready") {
+  if (e.data == "ready") {
     opener.postMessage(e.data, "*");
+  } else if (e.data == "start") {
+    window.onfocus = function() {
+      outerlog += "windowfocus,";
+    };
   } else if (e.data == "focusinnerinput" || e.data == "focusinner" || e.data == "focusmiddle" || e.data == "getlog") {
     iframe.contentWindow.postMessage(e.data, "*");
   } else if (e.data == "focusouter") {
diff --git a/third_party/blink/web_tests/external/wpt/focus/support/activeelement-after-calling-window-focus-outer-same.sub.html b/third_party/blink/web_tests/external/wpt/focus/support/activeelement-after-calling-window-focus-outer-same.sub.html
index cabdb26..4833e94b 100644
--- a/third_party/blink/web_tests/external/wpt/focus/support/activeelement-after-calling-window-focus-outer-same.sub.html
+++ b/third_party/blink/web_tests/external/wpt/focus/support/activeelement-after-calling-window-focus-outer-same.sub.html
@@ -7,8 +7,12 @@
 
 let iframe = document.querySelector("iframe");
 window.onmessage = function(e) {
-   if (e.data == "ready") {
+  if (e.data == "ready") {
     opener.postMessage(e.data, "*");
+  } else if (e.data == "start") {
+    window.onfocus = function() {
+      outerlog += "windowfocus,";
+    };
   } else if (e.data == "focusinnerinput" || e.data == "focusinner" || e.data == "focusmiddle" || e.data == "getlog") {
     iframe.contentWindow.postMessage(e.data, "*");
   } else if (e.data == "focusouter") {
@@ -19,12 +23,6 @@
   }
 };
 
-window.onload = function() {
-  window.onfocus = function() {
-    outerlog += "windowfocus,";
-  };
-};
-
 window.onblur = function() {
   outerlog += "windowblur,";
 };
diff --git a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-different-site-iframe-gets-focus-outer.sub.html b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-different-site-iframe-gets-focus-outer.sub.html
index c59b2ce7..da107ab 100644
--- a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-different-site-iframe-gets-focus-outer.sub.html
+++ b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-different-site-iframe-gets-focus-outer.sub.html
@@ -7,7 +7,11 @@
 
 let iframe = document.querySelector("iframe");
 window.onmessage = function(e) {
-  if (e.data == "focus") {
+  if (e.data == "start") {
+    window.onfocus = function() {
+      outerlog += "windowfocus,";
+    };
+  } else if (e.data == "focus") {
     iframe.contentWindow.postMessage("focus", "*");
   } else if (e.data == "getlog") {
     iframe.contentWindow.postMessage("getlog", "*");
@@ -17,10 +21,6 @@
 };
 
 window.onload = function() {
-  window.onfocus = function() {
-    outerlog += "windowfocus,";
-  };
-
   window.onblur = function() {
     outerlog += "windowblur,";
   };
diff --git a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-focusing-different-site-iframes-outer.sub.html b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-focusing-different-site-iframes-outer.sub.html
index 7d2fb50..7c02a6b 100644
--- a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-focusing-different-site-iframes-outer.sub.html
+++ b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-focusing-different-site-iframes-outer.sub.html
@@ -7,7 +7,11 @@
 
 let iframe = document.querySelector("iframe");
 window.onmessage = function(e) {
-  if (e.data == "focus") {
+  if (e.data == "start") {
+    window.onfocus = function() {
+      outerlog += "windowfocus,";
+    };
+  } else if (e.data == "focus") {
     outerlog += "willfocusiframe,";
     iframe.focus();
     outerlog += "didfocusiframe,";
@@ -19,10 +23,6 @@
 };
 
 window.onload = function() {
-  window.onfocus = function() {
-    outerlog += "windowfocus,";
-  };
-
   window.onblur = function() {
     outerlog += "windowblur,";
   };
diff --git a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-focusing-same-site-iframes-outer.html b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-focusing-same-site-iframes-outer.html
index 08f2c3f..9147b681 100644
--- a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-focusing-same-site-iframes-outer.html
+++ b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-focusing-same-site-iframes-outer.html
@@ -7,7 +7,11 @@
 
 let iframe = document.querySelector("iframe");
 window.onmessage = function(e) {
-  if (e.data == "focus") {
+  if (e.data == "start") {
+    window.onfocus = function() {
+      outerlog += "windowfocus,";
+    };
+  } else if (e.data == "focus") {
     outerlog += "willfocusiframe,";
     document.querySelector("iframe").focus();
     outerlog += "didfocusiframe,";
@@ -19,10 +23,6 @@
 };
 
 window.onload = function() {
-  window.onfocus = function() {
-    outerlog += "windowfocus,";
-  };
-
   window.onblur = function() {
     outerlog += "windowblur,";
   };
diff --git a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-innermost-different-site-iframe-gets-focus-outer.sub.html b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-innermost-different-site-iframe-gets-focus-outer.sub.html
index 12af71e..fc0fb50 100644
--- a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-innermost-different-site-iframe-gets-focus-outer.sub.html
+++ b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-innermost-different-site-iframe-gets-focus-outer.sub.html
@@ -7,7 +7,11 @@
 
 let iframe = document.querySelector("iframe");
 window.onmessage = function(e) {
-  if (e.data == "focus") {
+  if (e.data == "start") {
+    window.onfocus = function() {
+      outerlog += "windowfocus,";
+    };
+  } else if (e.data == "focus") {
     iframe.contentWindow.postMessage("focus", "*");
   } else if (e.data == "getlog") {
     iframe.contentWindow.postMessage("getlog", "*");
@@ -17,10 +21,6 @@
 };
 
 window.onload = function() {
-  window.onfocus = function() {
-    outerlog += "windowfocus,";
-  };
-
   window.onblur = function() {
     outerlog += "windowblur,";
   };
diff --git a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-same-site-iframe-gets-focus-outer.html b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-same-site-iframe-gets-focus-outer.html
index b191be5..c6799f0 100644
--- a/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-same-site-iframe-gets-focus-outer.html
+++ b/third_party/blink/web_tests/external/wpt/focus/support/focus-event-after-same-site-iframe-gets-focus-outer.html
@@ -7,7 +7,11 @@
 
 let iframe = document.querySelector("iframe");
 window.onmessage = function(e) {
-  if (e.data == "focus") {
+  if (e.data == "start") {
+    window.onfocus = function() {
+      outerlog += "windowfocus,";
+    };
+  } else if (e.data == "focus") {
     iframe.contentWindow.postMessage("focus", "*");
   } else if (e.data == "getlog") {
     iframe.contentWindow.postMessage("getlog", "*");
@@ -17,10 +21,6 @@
 };
 
 window.onload = function() {
-  window.onfocus = function() {
-    outerlog += "windowfocus,";
-  };
-
   window.onblur = function() {
     outerlog += "windowblur,";
   };
diff --git a/third_party/blink/web_tests/fullscreen/rendering/backdrop-iframe-expected.html b/third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-iframe-ref.html
similarity index 100%
rename from third_party/blink/web_tests/fullscreen/rendering/backdrop-iframe-expected.html
rename to third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-iframe-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-iframe.html b/third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-iframe.html
new file mode 100644
index 0000000..710d1b48
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-iframe.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>::backdrop for a fullscreen iframe element</title>
+<link rel=match href="backdrop-iframe-ref.html">
+<link rel=help href="https://github.com/w3c/csswg-drafts/issues/6939">
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+iframe::backdrop {
+  background: green;
+}
+</style>
+<iframe></iframe>
+<script>
+document.addEventListener('fullscreenchange', () => {
+  document.documentElement.classList.remove('reftest-wait');
+});
+test_driver.bless('fullscreen', () => {
+  document.querySelector('iframe').requestFullscreen();
+});
+</script>
diff --git a/third_party/blink/web_tests/fullscreen/rendering/backdrop-object-expected.html b/third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-object-ref.html
similarity index 100%
rename from third_party/blink/web_tests/fullscreen/rendering/backdrop-object-expected.html
rename to third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-object-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-object.html b/third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-object.html
new file mode 100644
index 0000000..be285b7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fullscreen/rendering/backdrop-object.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>::backdrop for a fullscreen object element</title>
+<link rel=match href="backdrop-object-ref.html">
+<link rel=help href="https://github.com/w3c/csswg-drafts/issues/6939">
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+object::backdrop {
+  background: blue;
+}
+</style>
+<object width="200" type="image/svg+xml" data="../../images/100px-green-rect.svg"></object>
+<script>
+const object = document.querySelector("object");
+Promise.all([
+    new Promise((resolve, reject) => document.addEventListener("fullscreenchange", resolve)),
+    new Promise((resolve, reject) => object.addEventListener("load", resolve))
+]).then(() => document.documentElement.classList.remove('reftest-wait'));
+
+test_driver.bless('fullscreen', () => object.requestFullscreen());
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js
index ff446f5e..4b42d91 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js
@@ -187,3 +187,16 @@
     }
   }, description);
 }
+
+// Call clients.claim() on the service worker
+async function claim(t, worker) {
+  const channel = new MessageChannel();
+  const saw_message = new Promise(function(resolve) {
+    channel.port1.onmessage = t.step_func(function(e) {
+      assert_equals(e.data, 'PASS', 'Worker call to claim() should fulfill.');
+      resolve();
+    });
+  });
+  worker.postMessage({port: channel.port2}, [channel.port2]);
+  await saw_message;
+}
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/service-worker.js b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/service-worker.js
new file mode 100644
index 0000000..60dceb0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/service-worker.js
@@ -0,0 +1,31 @@
+self.addEventListener('message', function(event) {
+    self.clients.claim()
+      .then(function(result) {
+          if (result !== undefined) {
+              event.data.port.postMessage(
+                  'FAIL: claim() should be resolved with undefined');
+              return;
+          }
+          event.data.port.postMessage('PASS');
+        })
+      .catch(function(error) {
+          event.data.port.postMessage('FAIL: exception: ' + error.name);
+        });
+  });
+
+self.addEventListener('fetch', e => {
+    if (e.request.url.match(/\/is-controlled/)) {
+      e.respondWith(new Response('controlled'));
+    }
+    else if (e.request.url.match(/\/get-clients-matchall/)) {
+      const options = { includeUncontrolled: true, type: 'all' };
+      e.respondWith(
+        self.clients.matchAll(options)
+          .then(clients => {
+            const client_urls = [];
+            clients.forEach(client => client_urls.push(client.url));
+            return new Response(JSON.stringify(client_urls));
+          })
+      );
+    }
+  });
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-claim.https.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-claim.https.html
new file mode 100644
index 0000000..d9540c2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-claim.https.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="resources/helper.sub.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<script>
+// Calling Clients.claim() on the service worker when a controlled page is in
+// BFCache should evict the page from BFCache, as per
+// https://github.com/w3c/ServiceWorker/issues/1038#issuecomment-291028845.
+promise_test(async t => {
+  const pageA = new RemoteContext(token());
+  const pageB = new RemoteContext(token());
+
+  const urlA = location.origin + executorPath + pageA.context_id;
+  const urlB = originCrossSite + executorPath + pageB.context_id;
+
+  window.open(urlA, '_blank', 'noopener');
+  await pageA.execute_script(waitForPageShow);
+
+  // Register a service worker after `pageA` is loaded to make `pageA`
+  // uncontrolled at this time.
+  const workerUrl =
+      'resources/service-worker.js?pipe=header(Service-Worker-Allowed,../)';
+  const registration =
+      await service_worker_unregister_and_register(t, workerUrl, './');
+  t.add_cleanup(_ => registration.unregister());
+  await wait_for_state(t, registration.installing, 'activated');
+
+  // Navigate to `urlB`.
+  await pageA.execute_script(
+    (url) => {
+      prepareNavigation(() => { location.href = url; });
+    },
+    [urlB]);
+  await pageB.execute_script(waitForPageShow);
+
+  // Call Clients.claim() on the service worker when `pageA` is in BFCache.
+  const controllerChanged = new Promise(
+      resolve => navigator.serviceWorker.oncontrollerchange = resolve);
+  await claim(t, registration.active);
+  await controllerChanged;
+
+  // `pageA` doesn't appear in matchAll().
+  const clients1 = await (await fetch('/get-clients-matchall')).json();
+  assert_true(clients1.indexOf(urlA) < 0,
+              '1: matchAll() before back navigation');
+
+  // Back navigate and check that the page was evicted from BFCache.
+  await pageB.execute_script(
+    () => {
+      prepareNavigation(() => { history.back(); });
+    }
+  );
+  await pageA.execute_script(waitForPageShow);
+  await assert_not_bfcached(pageA);
+
+  // After back navigation, `pageA` appear in matchAll(), because it was newly
+  // loaded and controlled by the service worker.
+  const clients2 = await (await fetch('/get-clients-matchall')).json();
+  const controlled2 = await pageA.execute_script(
+    () => (navigator.serviceWorker.controller !== null));
+  assert_true(clients2.indexOf(urlA) >= 0,
+    '2: matchAll() just after back navigation');
+  assert_true(controlled2,
+    '2: pageA should be controlled just after back navigation');
+
+}, 'Clients.claim() evicts pages that would be affected from BFCache');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-matchall.https.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-matchall.https.html
new file mode 100644
index 0000000..069529db
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-clients-matchall.https.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="resources/helper.sub.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<script>
+promise_test(async t => {
+  // Register a service worker and make this page controlled.
+  const workerUrl =
+      'resources/service-worker.js?pipe=header(Service-Worker-Allowed,../)';
+  const registration =
+      await service_worker_unregister_and_register(t, workerUrl, './');
+  t.add_cleanup(_ => registration.unregister());
+  await wait_for_state(t, registration.installing, 'activated');
+  const controllerChanged = new Promise(
+      resolve => navigator.serviceWorker.oncontrollerchange = resolve);
+  await claim(t, registration.active);
+  await controllerChanged;
+
+  const pageA = new RemoteContext(token());
+  const pageB = new RemoteContext(token());
+
+  const urlA = location.origin + executorPath + pageA.context_id;
+  const urlB = originCrossSite + executorPath + pageB.context_id;
+
+  // Open `urlA`.
+  window.open(urlA, '_blank', 'noopener');
+  await pageA.execute_script(waitForPageShow);
+
+  // Get Clients.matchAll() and check whether `pageA` is controlled.
+  // Actual `assert_*()` is called after `assert_bfcached()` below.
+  const clients1 = await (await fetch('/get-clients-matchall')).json();
+  const controlled1 = await pageA.execute_script(
+      () => (navigator.serviceWorker.controller !== null));
+
+  // Navigate to `urlB` and get Clients.matchAll() when `urlA` is in BFCache.
+  await pageA.execute_script(
+    (url) => prepareNavigation(() => {
+      location.href = url;
+    }),
+    [urlB]);
+  await pageB.execute_script(waitForPageShow);
+  const clients2 = await (await fetch('/get-clients-matchall')).json();
+
+  // Back navigate and check whether the page is restored from BFCache.
+  await pageB.execute_script(
+    () => {
+      prepareNavigation(() => { history.back(); });
+    }
+  );
+  await pageA.execute_script(waitForPageShow);
+  await assert_bfcached(pageA);
+
+  // Get Clients.matchAll() and check whether `pageA` is controlled.
+  const clients3 = await (await fetch('/get-clients-matchall')).json();
+  const controlled3 = await pageA.execute_script(
+      () => (navigator.serviceWorker.controller !== null));
+
+  // Clients.matchAll() should not list `urlA` when it is in BFCache.
+  assert_true(clients1.indexOf(urlA) >= 0,
+      '1: matchAll() before navigation');
+  assert_true(clients2.indexOf(urlA) < 0,
+      '2: matchAll() before back navigation');
+  assert_true(clients3.indexOf(urlA) >= 0,
+      '3: matchAll() after back navigation');
+
+  // `pageA` should be controlled before/after BFCached.
+  assert_true(controlled1,
+    'pageA should be controlled before BFCached');
+  assert_true(controlled3,
+    'pageA should be controlled after restored');
+}, 'Clients.matchAll() should not list pages in BFCache');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-controlled-after-restore.https.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-controlled-after-restore.https.html
new file mode 100644
index 0000000..a937eb8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-controlled-after-restore.https.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="resources/helper.sub.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<script>
+promise_test(async t => {
+  const pageA = new RemoteContext(token());
+  const pageB = new RemoteContext(token());
+
+  const urlA = location.origin + executorPath + pageA.context_id;
+  const urlB = originCrossSite + executorPath + pageB.context_id;
+
+  // Register a service worker.
+  const workerUrl =
+      'resources/service-worker.js?pipe=header(Service-Worker-Allowed,../)';
+  const registration =
+      await service_worker_unregister_and_register(t, workerUrl, './');
+  t.add_cleanup(_ => registration.unregister());
+  await wait_for_state(t, registration.installing, 'activated');
+
+  window.open(urlA, '_blank', 'noopener');
+  await pageA.execute_script(waitForPageShow);
+
+  assert_true(
+    await pageA.execute_script(
+        () => (navigator.serviceWorker.controller !== null)),
+    'pageA should be controlled before navigation');
+
+  await navigateAndThenBack(pageA, pageB, urlB);
+  await assert_bfcached(pageA);
+
+  assert_true(
+    await pageA.execute_script(
+        () => (navigator.serviceWorker.controller !== null)),
+    'navigator.serviceWorker.controller should be non-null ' +
+    'after restored from BFCache');
+
+  const isControlled = await pageA.execute_script(
+      () => fetch('/is-controlled').then(r => r.text()));
+
+  assert_true(
+    await pageA.execute_script(
+        () => (navigator.serviceWorker.controller !== null)),
+    'navigator.serviceWorker.controller should be non-null ' +
+    'after restored from BFCache and after fetch');
+
+  assert_equals(isControlled, 'controlled',
+    'fetch should be intercepted after restored from BFCache');
+}, 'Pages should remain controlled after restored from BFCache');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-unregister.https.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-unregister.https.html
new file mode 100644
index 0000000..1c3f811
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-unregister.https.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="resources/helper.sub.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<script>
+// When a service worker is unregistered when a controlled page is in BFCache,
+// the page can be still restored from BFCache and remain controlled by the
+// service worker.
+promise_test(async t => {
+  // Register a service worker and make this page controlled.
+  const workerUrl =
+      'resources/service-worker.js?pipe=header(Service-Worker-Allowed,../)';
+  const registration =
+      await service_worker_unregister_and_register(t, workerUrl, './');
+  t.add_cleanup(_ => registration.unregister());
+  await wait_for_state(t, registration.installing, 'activated');
+  const controllerChanged = new Promise(
+      resolve => navigator.serviceWorker.oncontrollerchange = resolve);
+  await claim(t, registration.active);
+  await controllerChanged;
+
+  const pageA = new RemoteContext(token());
+  const pageB = new RemoteContext(token());
+
+  const urlA = location.origin + executorPath + pageA.context_id;
+  const urlB = originCrossSite + executorPath + pageB.context_id;
+
+  // Open `urlA`.
+  window.open(urlA, '_blank', 'noopener');
+  await pageA.execute_script(waitForPageShow);
+
+  assert_true(
+    await pageA.execute_script(
+        () => (navigator.serviceWorker.controller !== null)),
+    'pageA should be controlled before navigation');
+
+  // Navigate to `urlB`.
+  await pageA.execute_script(
+    (url) => prepareNavigation(() => {
+      location.href = url;
+    }),
+    [urlB]);
+  await pageB.execute_script(waitForPageShow);
+
+  // Unregister the service worker when the controlled `pageA` is in BFCache.
+  await registration.unregister();
+
+  // Back navigate and check whether the page is restored from BFCache.
+  await pageB.execute_script(
+    () => {
+      prepareNavigation(() => { history.back(); });
+    }
+  );
+  await pageA.execute_script(waitForPageShow);
+  await assert_not_bfcached(pageA);
+
+  assert_true(
+    await pageA.execute_script(
+        () => (navigator.serviceWorker.controller === null)),
+    'pageA should not be controlled');
+
+}, 'Unregister service worker while a controlled page is in BFCache');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-html.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-html.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-html.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-html.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-img.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-img.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-img.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-img.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-js.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-js.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-js.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-js.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-mp4.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-mp4.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-not-found.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-not-found.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-type-only.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embeded-type-only.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/resources/common.js b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/resources/common.js
index 9c852bb..5bb9642a 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/resources/common.js
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/bfcache/resources/common.js
@@ -28,8 +28,14 @@
           shouldBeCached: true,
           funcBeforeNavigation: (tag, attrs) => {
             let e = document.createElement(tag.name);
-            e.type = attrs.type;
-            e[tag.srcAttr] = attrs.src;
+            // Only sets defined attributes to match the intended test behavior
+            // like embedded-type-only.html test.
+            if ('type' in attrs) {
+              e.type = attrs.type;
+            }
+            if ('src' in attrs) {
+              e[tag.srcAttr] = attrs.src;
+            }
             document.body.append(e);
           },
           argsBeforeNavigation: [tag, testCase]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-inherit-to-blank-document-unsandboxed.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-inherit-to-blank-document-unsandboxed.html
index f60ab0da..26b30cf 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-inherit-to-blank-document-unsandboxed.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-inherit-to-blank-document-unsandboxed.html
@@ -41,7 +41,7 @@
 test(test => {
     // The navigation will be canceled (204 no content). As a result, the
     // document in the popup must still be the initial empty document.
-    const w = window.open("common/blank.html?pipe=status(204)")
+    const w = window.open("/common/blank.html?pipe=status(204)")
 
     // The about:blank document is sandboxed, because it inherited CSP from its
     // opener. However this is impossible to verify. There are cross-origin
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-iframe-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-iframe-ref.html
new file mode 100644
index 0000000..b6c52b7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-iframe-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe></iframe>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-iframe.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-iframe.html
new file mode 100644
index 0000000..f644058
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-iframe.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Modal dialog inside iframe should not generate box</title>
+<link rel=match href="modal-dialog-in-iframe-ref.html">
+<link rel=help href="https://github.com/w3c/csswg-drafts/issues/6939">
+<link rel=help href="https://fullscreen.spec.whatwg.org/#new-stacking-layer">
+<style>
+dialog {
+  background: red;
+  border-color: red;
+}
+</style>
+<iframe></iframe>
+<script>
+  const iframe = document.querySelector('iframe');
+  const dialog = document.createElement('dialog');
+  iframe.appendChild(dialog);
+  dialog.showModal();
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-object-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-object-ref.html
new file mode 100644
index 0000000..38e15c1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-object-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<object width="200" type="image/svg+xml" data="../../../../images/100px-green-rect.svg"></object>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-object.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-object.html
new file mode 100644
index 0000000..728748a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-object.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Modal dialog inside object should not generate box</title>
+<link rel=match href="modal-dialog-in-object-ref.html">
+<link rel=help href="https://github.com/w3c/csswg-drafts/issues/6939">
+<link rel=help href="https://fullscreen.spec.whatwg.org/#new-stacking-layer">
+<style>
+dialog {
+  background: green;
+  border-color: green;
+}
+</style>
+<object width="200" type="image/svg+xml" data="../../../../images/100px-green-rect.svg">
+  <dialog id="dialog"></dialog>
+</object>
+<script>
+document.getElementById('dialog').showModal();
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/structured-clone/structured-clone-battery-of-tests.js b/third_party/blink/web_tests/external/wpt/html/webappapis/structured-clone/structured-clone-battery-of-tests.js
index aefab049..580a81a 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/structured-clone/structured-clone-battery-of-tests.js
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/structured-clone/structured-clone-battery-of-tests.js
@@ -254,6 +254,27 @@
 check('Object RegExp object, RegExp slash', {'x':new RegExp('/')}, compare_Object(enumerate_props(compare_RegExp('\\/'))));
 check('Object RegExp object, RegExp new line', {'x':new RegExp('\n')}, compare_Object(enumerate_props(compare_RegExp('\\n'))));
 
+function compare_Error(actual, input) {
+  assert_true(actual instanceof Error, "Checking instanceof");
+  assert_equals(actual.constructor, input.constructor, "Checking constructor");
+  assert_equals(actual.name, input.name, "Checking name");
+  assert_equals(actual.hasOwnProperty("message"), input.hasOwnProperty("message"), "Checking message existence");
+  assert_equals(actual.message, input.message, "Checking message");
+  assert_equals(actual.foo, undefined, "Checking for absence of custom property");
+}
+
+check('Empty Error object', new Error, compare_Error);
+
+const errorConstructors = [Error, EvalError, RangeError, ReferenceError,
+                           SyntaxError, TypeError, URIError];
+for (const constructor of errorConstructors) {
+  check(`${constructor.name} object`, () => {
+    let error = new constructor("Error message here");
+    error.foo = "testing";
+    return error;
+  }, compare_Error);
+}
+
 async function compare_Blob(actual, input, expect_File) {
   if (typeof actual === 'string')
     assert_unreached(actual);
diff --git a/third_party/blink/web_tests/external/wpt/images/100px-green-rect.svg b/third_party/blink/web_tests/external/wpt/images/100px-green-rect.svg
new file mode 100644
index 0000000..c391055
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/images/100px-green-rect.svg
@@ -0,0 +1,3 @@
+<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <rect x="0" y="0" width="100px" height="100px" fill="green"/>
+</svg>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/update-max-aged-worker.py b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/update-max-aged-worker.py
index 4f87906..221ef77 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/update-max-aged-worker.py
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/update-max-aged-worker.py
@@ -13,7 +13,7 @@
     body = u'''
         const mainTime = {time:8f};
         const testName = {test};
-        importScripts('update-max-aged-worker-imported-script.py');
+        importScripts('update-max-aged-worker-imported-script.py?test={test}');
 
         addEventListener('message', event => {{
             event.source.postMessage({{
diff --git a/third_party/blink/web_tests/external/wpt/window-placement/fullscreen-companion-window-manual.tentative.https.html b/third_party/blink/web_tests/external/wpt/window-placement/fullscreen-companion-window-manual.tentative.https.html
index fe82916..c2fa2f1 100644
--- a/third_party/blink/web_tests/external/wpt/window-placement/fullscreen-companion-window-manual.tentative.https.html
+++ b/third_party/blink/web_tests/external/wpt/window-placement/fullscreen-companion-window-manual.tentative.https.html
@@ -8,7 +8,7 @@
 <link rel="help" href="https://w3c.github.io/window-placement">
 This test uses multi-screen details to request fullscreen and open a pop-up<br>
 (companion window) in the same user activation.<br>
-It runs automated or manually with `wpt serve` and a compatible browser.<br><br>
+It runs manually with `wpt serve` and a compatible browser.<br><br>
 <button id="setUpButton">Request screen details</button>
 <ul id="popupButtons"></ul>
 <button id="cleanUpButton">Close any open popups</button><br>
@@ -54,8 +54,6 @@
   for (const [i, fullscreenScreen] of screenDetails.screens.entries()) {
     const popupScreen =
       screenDetails.screens[(i + 1) % screenDetails.screens.length];
-    // Fullscreen and popup are the same in single screen environments.
-    if (popupScreen === undefined) popupScreen = fullscreenScreen;
     let testName =
       `Fullscreen on '${fullscreenScreen.label}' and open popup on '${popupScreen.label}'`;
     promise_test(async popupTest => {
@@ -76,7 +74,7 @@
         { screen: fullscreenScreen }
       );
       await testPopupOnScreen(popupTest, popupScreen,
-        /*expectPopup=*/fullscreenScreen !== popupScreen);
+                             /*expectPopup=*/fullscreenScreen !== popupScreen);
     }, testName);
   }
 }, 'Use multi-screen details to request fullscreen and open a pop-up in the same user activation.');
diff --git a/third_party/blink/web_tests/fast/css-generated-content/quotes-lang-expected.html b/third_party/blink/web_tests/fast/css-generated-content/quotes-lang-expected.html
index 0279fe9e..3417d15 100644
--- a/third_party/blink/web_tests/fast/css-generated-content/quotes-lang-expected.html
+++ b/third_party/blink/web_tests/fast/css-generated-content/quotes-lang-expected.html
@@ -160,152 +160,152 @@
 
 <!-- Custom quotes are inlined to make this test fail if you don't implement CSS quotes. -->
 <div lang="custom">ACcustomDB</div>
-<div><q><q>default</q></q></div>
-<div lang="af"><q><q>af</q></q></div>
-<div lang="agq"><q><q>agq</q></q></div>
-<div lang="ak"><q><q>ak</q></q></div>
-<div lang="am"><q><q>am</q></q></div>
-<div lang="ar"><q><q>ar</q></q></div>
-<div lang="asa"><q><q>asa</q></q></div>
-<div lang="az-Cyrl"><q><q>az-Cyrl</q></q></div>
-<div lang="bas"><q><q>bas</q></q></div>
-<div lang="bem"><q><q>bem</q></q></div>
-<div lang="bez"><q><q>bez</q></q></div>
-<div lang="bg"><q><q>bg</q></q></div>
-<div lang="bm"><q><q>bm</q></q></div>
-<div lang="bn"><q><q>bn</q></q></div>
-<div lang="br"><q><q>br</q></q></div>
-<div lang="brx"><q><q>brx</q></q></div>
-<div lang="bs-Cyrl"><q><q>bs-Cyrl</q></q></div>
-<div lang="ca"><q><q>ca</q></q></div>
-<div lang="cgg"><q><q>cgg</q></q></div>
-<div lang="chr"><q><q>chr</q></q></div>
-<div lang="cs"><q><q>cs</q></q></div>
-<div lang="da"><q><q>da</q></q></div>
-<div lang="dav"><q><q>dav</q></q></div>
-<div lang="de"><q><q>de</q></q></div>
-<div lang="de-CH"><q><q>de-CH</q></q></div>
-<div lang="dje"><q><q>dje</q></q></div>
-<div lang="dua"><q><q>dua</q></q></div>
-<div lang="dyo"><q><q>dyo</q></q></div>
-<div lang="dz"><q><q>dz</q></q></div>
-<div lang="ebu"><q><q>ebu</q></q></div>
-<div lang="ee"><q><q>ee</q></q></div>
-<div lang="el"><q><q>el</q></q></div>
-<div lang="en"><q><q>en</q></q></div>
-<div lang="en-GB"><q><q>en-GB</q></q></div>
-<div lang="es"><q><q>es</q></q></div>
-<div lang="et"><q><q>et</q></q></div>
-<div lang="eu"><q><q>eu</q></q></div>
-<div lang="ewo"><q><q>ewo</q></q></div>
-<div lang="fa"><q><q>fa</q></q></div>
-<div lang="ff"><q><q>ff</q></q></div>
-<div lang="fi"><q><q>fi</q></q></div>
-<div lang="fr"><q><q>fr</q></q></div>
-<div lang="fr-CA"><q><q>fr-CA</q></q></div>
-<div lang="fr-CH"><q><q>fr-CH</q></q></div>
-<div lang="gsw"><q><q>gsw</q></q></div>
-<div lang="gu"><q><q>gu</q></q></div>
-<div lang="guz"><q><q>guz</q></q></div>
-<div lang="ha"><q><q>ha</q></q></div>
-<div lang="he"><q><q>he</q></q></div>
-<div lang="hi"><q><q>hi</q></q></div>
-<div lang="hr"><q><q>hr</q></q></div>
-<div lang="hu"><q><q>hu</q></q></div>
-<div lang="id"><q><q>id</q></q></div>
-<div lang="ig"><q><q>ig</q></q></div>
-<div lang="it"><q><q>it</q></q></div>
-<div lang="ja"><q><q>ja</q></q></div>
-<div lang="jgo"><q><q>jgo</q></q></div>
-<div lang="jmc"><q><q>jmc</q></q></div>
-<div lang="kab"><q><q>kab</q></q></div>
-<div lang="kam"><q><q>kam</q></q></div>
-<div lang="kde"><q><q>kde</q></q></div>
-<div lang="kea"><q><q>kea</q></q></div>
-<div lang="khq"><q><q>khq</q></q></div>
-<div lang="ki"><q><q>ki</q></q></div>
-<div lang="kkj"><q><q>kkj</q></q></div>
-<div lang="kln"><q><q>kln</q></q></div>
-<div lang="km"><q><q>km</q></q></div>
-<div lang="kn"><q><q>kn</q></q></div>
-<div lang="ko"><q><q>ko</q></q></div>
-<div lang="ksb"><q><q>ksb</q></q></div>
-<div lang="ksf"><q><q>ksf</q></q></div>
-<div lang="lag"><q><q>lag</q></q></div>
-<div lang="lg"><q><q>lg</q></q></div>
-<div lang="ln"><q><q>ln</q></q></div>
-<div lang="lo"><q><q>lo</q></q></div>
-<div lang="lt"><q><q>lt</q></q></div>
-<div lang="lu"><q><q>lu</q></q></div>
-<div lang="luo"><q><q>luo</q></q></div>
-<div lang="luy"><q><q>luy</q></q></div>
-<div lang="lv"><q><q>lv</q></q></div>
-<div lang="mas"><q><q>mas</q></q></div>
-<div lang="mer"><q><q>mer</q></q></div>
-<div lang="mfe"><q><q>mfe</q></q></div>
-<div lang="mg"><q><q>mg</q></q></div>
-<div lang="mgo"><q><q>mgo</q></q></div>
-<div lang="mk"><q><q>mk</q></q></div>
-<div lang="ml"><q><q>ml</q></q></div>
-<div lang="mr"><q><q>mr</q></q></div>
-<div lang="ms"><q><q>ms</q></q></div>
-<div lang="mua"><q><q>mua</q></q></div>
-<div lang="my"><q><q>my</q></q></div>
-<div lang="naq"><q><q>naq</q></q></div>
-<div lang="nb"><q><q>nb</q></q></div>
-<div lang="nd"><q><q>nd</q></q></div>
-<div lang="nl"><q><q>nl</q></q></div>
-<div lang="nmg"><q><q>nmg</q></q></div>
-<div lang="nn"><q><q>nn</q></q></div>
-<div lang="nnh"><q><q>nnh</q></q></div>
-<div lang="nus"><q><q>nus</q></q></div>
-<div lang="nyn"><q><q>nyn</q></q></div>
-<div lang="pl"><q><q>pl</q></q></div>
-<div lang="pt"><q><q>pt</q></q></div>
-<div lang="pt-PT"><q><q>pt-PT</q></q></div>
-<div lang="rn"><q><q>rn</q></q></div>
-<div lang="ro"><q><q>ro</q></q></div>
-<div lang="rof"><q><q>rof</q></q></div>
-<div lang="ru"><q><q>ru</q></q></div>
-<div lang="rw"><q><q>rw</q></q></div>
-<div lang="rwk"><q><q>rwk</q></q></div>
-<div lang="saq"><q><q>saq</q></q></div>
-<div lang="sbp"><q><q>sbp</q></q></div>
-<div lang="seh"><q><q>seh</q></q></div>
-<div lang="ses"><q><q>ses</q></q></div>
-<div lang="sg"><q><q>sg</q></q></div>
-<div lang="shi"><q><q>shi</q></q></div>
-<div lang="shi-Tfng"><q><q>shi-Tfng</q></q></div>
-<div lang="si"><q><q>si</q></q></div>
-<div lang="sk"><q><q>sk</q></q></div>
-<div lang="sl"><q><q>sl</q></q></div>
-<div lang="sn"><q><q>sn</q></q></div>
-<div lang="so"><q><q>so</q></q></div>
-<div lang="sq"><q><q>sq</q></q></div>
-<div lang="sr"><q><q>sr</q></q></div>
-<div lang="sr-Latn"><q><q>sr-Latn</q></q></div>
-<div lang="sv"><q><q>sv</q></q></div>
-<div lang="sw"><q><q>sw</q></q></div>
-<div lang="swc"><q><q>swc</q></q></div>
-<div lang="ta"><q><q>ta</q></q></div>
-<div lang="te"><q><q>te</q></q></div>
-<div lang="teo"><q><q>teo</q></q></div>
-<div lang="th"><q><q>th</q></q></div>
-<div lang="ti-ER"><q><q>ti-ER</q></q></div>
-<div lang="to"><q><q>to</q></q></div>
-<div lang="tr"><q><q>tr</q></q></div>
-<div lang="twq"><q><q>twq</q></q></div>
-<div lang="tzm"><q><q>tzm</q></q></div>
-<div lang="uk"><q><q>uk</q></q></div>
-<div lang="ur"><q><q>ur</q></q></div>
-<div lang="vai"><q><q>vai</q></q></div>
-<div lang="vai-Latn"><q><q>vai-Latn</q></q></div>
-<div lang="vi"><q><q>vi</q></q></div>
-<div lang="vun"><q><q>vun</q></q></div>
-<div lang="xh"><q><q>xh</q></q></div>
-<div lang="xog"><q><q>xog</q></q></div>
-<div lang="yav"><q><q>yav</q></q></div>
-<div lang="yo"><q><q>yo</q></q></div>
-<div lang="zh"><q><q>zh</q></q></div>
-<div lang="zh-Hant"><q><q>zh-Hant</q></q></div>
-<div lang="zu"><q><q>zu</q></q></div>
+<q><q>default</q></q>
+<q lang="af"><q>af</q></q>
+<q lang="agq"><q>agq</q></q>
+<q lang="ak"><q>ak</q></q>
+<q lang="am"><q>am</q></q>
+<q lang="ar"><q>ar</q></q>
+<q lang="asa"><q>asa</q></q>
+<q lang="az-Cyrl"><q>az-Cyrl</q></q>
+<q lang="bas"><q>bas</q></q>
+<q lang="bem"><q>bem</q></q>
+<q lang="bez"><q>bez</q></q>
+<q lang="bg"><q>bg</q></q>
+<q lang="bm"><q>bm</q></q>
+<q lang="bn"><q>bn</q></q>
+<q lang="br"><q>br</q></q>
+<q lang="brx"><q>brx</q></q>
+<q lang="bs-Cyrl"><q>bs-Cyrl</q></q>
+<q lang="ca"><q>ca</q></q>
+<q lang="cgg"><q>cgg</q></q>
+<q lang="chr"><q>chr</q></q>
+<q lang="cs"><q>cs</q></q>
+<q lang="da"><q>da</q></q>
+<q lang="dav"><q>dav</q></q>
+<q lang="de"><q>de</q></q>
+<q lang="de-CH"><q>de-CH</q></q>
+<q lang="dje"><q>dje</q></q>
+<q lang="dua"><q>dua</q></q>
+<q lang="dyo"><q>dyo</q></q>
+<q lang="dz"><q>dz</q></q>
+<q lang="ebu"><q>ebu</q></q>
+<q lang="ee"><q>ee</q></q>
+<q lang="el"><q>el</q></q>
+<q lang="en"><q>en</q></q>
+<q lang="en-GB"><q>en-GB</q></q>
+<q lang="es"><q>es</q></q>
+<q lang="et"><q>et</q></q>
+<q lang="eu"><q>eu</q></q>
+<q lang="ewo"><q>ewo</q></q>
+<q lang="fa"><q>fa</q></q>
+<q lang="ff"><q>ff</q></q>
+<q lang="fi"><q>fi</q></q>
+<q lang="fr"><q>fr</q></q>
+<q lang="fr-CA"><q>fr-CA</q></q>
+<q lang="fr-CH"><q>fr-CH</q></q>
+<q lang="gsw"><q>gsw</q></q>
+<q lang="gu"><q>gu</q></q>
+<q lang="guz"><q>guz</q></q>
+<q lang="ha"><q>ha</q></q>
+<q lang="he"><q>he</q></q>
+<q lang="hi"><q>hi</q></q>
+<q lang="hr"><q>hr</q></q>
+<q lang="hu"><q>hu</q></q>
+<q lang="id"><q>id</q></q>
+<q lang="ig"><q>ig</q></q>
+<q lang="it"><q>it</q></q>
+<q lang="ja"><q>ja</q></q>
+<q lang="jgo"><q>jgo</q></q>
+<q lang="jmc"><q>jmc</q></q>
+<q lang="kab"><q>kab</q></q>
+<q lang="kam"><q>kam</q></q>
+<q lang="kde"><q>kde</q></q>
+<q lang="kea"><q>kea</q></q>
+<q lang="khq"><q>khq</q></q>
+<q lang="ki"><q>ki</q></q>
+<q lang="kkj"><q>kkj</q></q>
+<q lang="kln"><q>kln</q></q>
+<q lang="km"><q>km</q></q>
+<q lang="kn"><q>kn</q></q>
+<q lang="ko"><q>ko</q></q>
+<q lang="ksb"><q>ksb</q></q>
+<q lang="ksf"><q>ksf</q></q>
+<q lang="lag"><q>lag</q></q>
+<q lang="lg"><q>lg</q></q>
+<q lang="ln"><q>ln</q></q>
+<q lang="lo"><q>lo</q></q>
+<q lang="lt"><q>lt</q></q>
+<q lang="lu"><q>lu</q></q>
+<q lang="luo"><q>luo</q></q>
+<q lang="luy"><q>luy</q></q>
+<q lang="lv"><q>lv</q></q>
+<q lang="mas"><q>mas</q></q>
+<q lang="mer"><q>mer</q></q>
+<q lang="mfe"><q>mfe</q></q>
+<q lang="mg"><q>mg</q></q>
+<q lang="mgo"><q>mgo</q></q>
+<q lang="mk"><q>mk</q></q>
+<q lang="ml"><q>ml</q></q>
+<q lang="mr"><q>mr</q></q>
+<q lang="ms"><q>ms</q></q>
+<q lang="mua"><q>mua</q></q>
+<q lang="my"><q>my</q></q>
+<q lang="naq"><q>naq</q></q>
+<q lang="nb"><q>nb</q></q>
+<q lang="nd"><q>nd</q></q>
+<q lang="nl"><q>nl</q></q>
+<q lang="nmg"><q>nmg</q></q>
+<q lang="nn"><q>nn</q></q>
+<q lang="nnh"><q>nnh</q></q>
+<q lang="nus"><q>nus</q></q>
+<q lang="nyn"><q>nyn</q></q>
+<q lang="pl"><q>pl</q></q>
+<q lang="pt"><q>pt</q></q>
+<q lang="pt-PT"><q>pt-PT</q></q>
+<q lang="rn"><q>rn</q></q>
+<q lang="ro"><q>ro</q></q>
+<q lang="rof"><q>rof</q></q>
+<q lang="ru"><q>ru</q></q>
+<q lang="rw"><q>rw</q></q>
+<q lang="rwk"><q>rwk</q></q>
+<q lang="saq"><q>saq</q></q>
+<q lang="sbp"><q>sbp</q></q>
+<q lang="seh"><q>seh</q></q>
+<q lang="ses"><q>ses</q></q>
+<q lang="sg"><q>sg</q></q>
+<q lang="shi"><q>shi</q></q>
+<q lang="shi-Tfng"><q>shi-Tfng</q></q>
+<q lang="si"><q>si</q></q>
+<q lang="sk"><q>sk</q></q>
+<q lang="sl"><q>sl</q></q>
+<q lang="sn"><q>sn</q></q>
+<q lang="so"><q>so</q></q>
+<q lang="sq"><q>sq</q></q>
+<q lang="sr"><q>sr</q></q>
+<q lang="sr-Latn"><q>sr-Latn</q></q>
+<q lang="sv"><q>sv</q></q>
+<q lang="sw"><q>sw</q></q>
+<q lang="swc"><q>swc</q></q>
+<q lang="ta"><q>ta</q></q>
+<q lang="te"><q>te</q></q>
+<q lang="teo"><q>teo</q></q>
+<q lang="th"><q>th</q></q>
+<q lang="ti-ER"><q>ti-ER</q></q>
+<q lang="to"><q>to</q></q>
+<q lang="tr"><q>tr</q></q>
+<q lang="twq"><q>twq</q></q>
+<q lang="tzm"><q>tzm</q></q>
+<q lang="uk"><q>uk</q></q>
+<q lang="ur"><q>ur</q></q>
+<q lang="vai"><q>vai</q></q>
+<q lang="vai-Latn"><q>vai-Latn</q></q>
+<q lang="vi"><q>vi</q></q>
+<q lang="vun"><q>vun</q></q>
+<q lang="xh"><q>xh</q></q>
+<q lang="xog"><q>xog</q></q>
+<q lang="yav"><q>yav</q></q>
+<q lang="yo"><q>yo</q></q>
+<q lang="zh"><q>zh</q></q>
+<q lang="zh-Hant"><q>zh-Hant</q></q>
+<q lang="zu"><q>zu</q></q>
diff --git a/third_party/blink/web_tests/fast/css-generated-content/quotes-lang.html b/third_party/blink/web_tests/fast/css-generated-content/quotes-lang.html
index c9277942..4806c8e9 100644
--- a/third_party/blink/web_tests/fast/css-generated-content/quotes-lang.html
+++ b/third_party/blink/web_tests/fast/css-generated-content/quotes-lang.html
@@ -12,152 +12,152 @@
 </p>
 
 <div lang="custom"><q><q>custom</q></q></div>
-<div><q><q>default</q></q></div>
-<div lang="af"><q><q>af</q></q></div>
-<div lang="agq"><q><q>agq</q></q></div>
-<div lang="ak"><q><q>ak</q></q></div>
-<div lang="am"><q><q>am</q></q></div>
-<div lang="ar"><q><q>ar</q></q></div>
-<div lang="asa"><q><q>asa</q></q></div>
-<div lang="az-Cyrl"><q><q>az-Cyrl</q></q></div>
-<div lang="bas"><q><q>bas</q></q></div>
-<div lang="bem"><q><q>bem</q></q></div>
-<div lang="bez"><q><q>bez</q></q></div>
-<div lang="bg"><q><q>bg</q></q></div>
-<div lang="bm"><q><q>bm</q></q></div>
-<div lang="bn"><q><q>bn</q></q></div>
-<div lang="br"><q><q>br</q></q></div>
-<div lang="brx"><q><q>brx</q></q></div>
-<div lang="bs-Cyrl"><q><q>bs-Cyrl</q></q></div>
-<div lang="ca"><q><q>ca</q></q></div>
-<div lang="cgg"><q><q>cgg</q></q></div>
-<div lang="chr"><q><q>chr</q></q></div>
-<div lang="cs"><q><q>cs</q></q></div>
-<div lang="da"><q><q>da</q></q></div>
-<div lang="dav"><q><q>dav</q></q></div>
-<div lang="de"><q><q>de</q></q></div>
-<div lang="de-CH"><q><q>de-CH</q></q></div>
-<div lang="dje"><q><q>dje</q></q></div>
-<div lang="dua"><q><q>dua</q></q></div>
-<div lang="dyo"><q><q>dyo</q></q></div>
-<div lang="dz"><q><q>dz</q></q></div>
-<div lang="ebu"><q><q>ebu</q></q></div>
-<div lang="ee"><q><q>ee</q></q></div>
-<div lang="el"><q><q>el</q></q></div>
-<div lang="en"><q><q>en</q></q></div>
-<div lang="en-GB"><q><q>en-GB</q></q></div>
-<div lang="es"><q><q>es</q></q></div>
-<div lang="et"><q><q>et</q></q></div>
-<div lang="eu"><q><q>eu</q></q></div>
-<div lang="ewo"><q><q>ewo</q></q></div>
-<div lang="fa"><q><q>fa</q></q></div>
-<div lang="ff"><q><q>ff</q></q></div>
-<div lang="fi"><q><q>fi</q></q></div>
-<div lang="fr"><q><q>fr</q></q></div>
-<div lang="fr-CA"><q><q>fr-CA</q></q></div>
-<div lang="fr-CH"><q><q>fr-CH</q></q></div>
-<div lang="gsw"><q><q>gsw</q></q></div>
-<div lang="gu"><q><q>gu</q></q></div>
-<div lang="guz"><q><q>guz</q></q></div>
-<div lang="ha"><q><q>ha</q></q></div>
-<div lang="he"><q><q>he</q></q></div>
-<div lang="hi"><q><q>hi</q></q></div>
-<div lang="hr"><q><q>hr</q></q></div>
-<div lang="hu"><q><q>hu</q></q></div>
-<div lang="id"><q><q>id</q></q></div>
-<div lang="ig"><q><q>ig</q></q></div>
-<div lang="it"><q><q>it</q></q></div>
-<div lang="ja"><q><q>ja</q></q></div>
-<div lang="jgo"><q><q>jgo</q></q></div>
-<div lang="jmc"><q><q>jmc</q></q></div>
-<div lang="kab"><q><q>kab</q></q></div>
-<div lang="kam"><q><q>kam</q></q></div>
-<div lang="kde"><q><q>kde</q></q></div>
-<div lang="kea"><q><q>kea</q></q></div>
-<div lang="khq"><q><q>khq</q></q></div>
-<div lang="ki"><q><q>ki</q></q></div>
-<div lang="kkj"><q><q>kkj</q></q></div>
-<div lang="kln"><q><q>kln</q></q></div>
-<div lang="km"><q><q>km</q></q></div>
-<div lang="kn"><q><q>kn</q></q></div>
-<div lang="ko"><q><q>ko</q></q></div>
-<div lang="ksb"><q><q>ksb</q></q></div>
-<div lang="ksf"><q><q>ksf</q></q></div>
-<div lang="lag"><q><q>lag</q></q></div>
-<div lang="lg"><q><q>lg</q></q></div>
-<div lang="ln"><q><q>ln</q></q></div>
-<div lang="lo"><q><q>lo</q></q></div>
-<div lang="lt"><q><q>lt</q></q></div>
-<div lang="lu"><q><q>lu</q></q></div>
-<div lang="luo"><q><q>luo</q></q></div>
-<div lang="luy"><q><q>luy</q></q></div>
-<div lang="lv"><q><q>lv</q></q></div>
-<div lang="mas"><q><q>mas</q></q></div>
-<div lang="mer"><q><q>mer</q></q></div>
-<div lang="mfe"><q><q>mfe</q></q></div>
-<div lang="mg"><q><q>mg</q></q></div>
-<div lang="mgo"><q><q>mgo</q></q></div>
-<div lang="mk"><q><q>mk</q></q></div>
-<div lang="ml"><q><q>ml</q></q></div>
-<div lang="mr"><q><q>mr</q></q></div>
-<div lang="ms"><q><q>ms</q></q></div>
-<div lang="mua"><q><q>mua</q></q></div>
-<div lang="my"><q><q>my</q></q></div>
-<div lang="naq"><q><q>naq</q></q></div>
-<div lang="nb"><q><q>nb</q></q></div>
-<div lang="nd"><q><q>nd</q></q></div>
-<div lang="nl"><q><q>nl</q></q></div>
-<div lang="nmg"><q><q>nmg</q></q></div>
-<div lang="nn"><q><q>nn</q></q></div>
-<div lang="nnh"><q><q>nnh</q></q></div>
-<div lang="nus"><q><q>nus</q></q></div>
-<div lang="nyn"><q><q>nyn</q></q></div>
-<div lang="pl"><q><q>pl</q></q></div>
-<div lang="pt"><q><q>pt</q></q></div>
-<div lang="pt-PT"><q><q>pt-PT</q></q></div>
-<div lang="rn"><q><q>rn</q></q></div>
-<div lang="ro"><q><q>ro</q></q></div>
-<div lang="rof"><q><q>rof</q></q></div>
-<div lang="ru"><q><q>ru</q></q></div>
-<div lang="rw"><q><q>rw</q></q></div>
-<div lang="rwk"><q><q>rwk</q></q></div>
-<div lang="saq"><q><q>saq</q></q></div>
-<div lang="sbp"><q><q>sbp</q></q></div>
-<div lang="seh"><q><q>seh</q></q></div>
-<div lang="ses"><q><q>ses</q></q></div>
-<div lang="sg"><q><q>sg</q></q></div>
-<div lang="shi"><q><q>shi</q></q></div>
-<div lang="shi-Tfng"><q><q>shi-Tfng</q></q></div>
-<div lang="si"><q><q>si</q></q></div>
-<div lang="sk"><q><q>sk</q></q></div>
-<div lang="sl"><q><q>sl</q></q></div>
-<div lang="sn"><q><q>sn</q></q></div>
-<div lang="so"><q><q>so</q></q></div>
-<div lang="sq"><q><q>sq</q></q></div>
-<div lang="sr"><q><q>sr</q></q></div>
-<div lang="sr-Latn"><q><q>sr-Latn</q></q></div>
-<div lang="sv"><q><q>sv</q></q></div>
-<div lang="sw"><q><q>sw</q></q></div>
-<div lang="swc"><q><q>swc</q></q></div>
-<div lang="ta"><q><q>ta</q></q></div>
-<div lang="te"><q><q>te</q></q></div>
-<div lang="teo"><q><q>teo</q></q></div>
-<div lang="th"><q><q>th</q></q></div>
-<div lang="ti-ER"><q><q>ti-ER</q></q></div>
-<div lang="to"><q><q>to</q></q></div>
-<div lang="tr"><q><q>tr</q></q></div>
-<div lang="twq"><q><q>twq</q></q></div>
-<div lang="tzm"><q><q>tzm</q></q></div>
-<div lang="uk"><q><q>uk</q></q></div>
-<div lang="ur"><q><q>ur</q></q></div>
-<div lang="vai"><q><q>vai</q></q></div>
-<div lang="vai-Latn"><q><q>vai-Latn</q></q></div>
-<div lang="vi"><q><q>vi</q></q></div>
-<div lang="vun"><q><q>vun</q></q></div>
-<div lang="xh"><q><q>xh</q></q></div>
-<div lang="xog"><q><q>xog</q></q></div>
-<div lang="yav"><q><q>yav</q></q></div>
-<div lang="yo"><q><q>yo</q></q></div>
-<div lang="zh"><q><q>zh</q></q></div>
-<div lang="zh-Hant"><q><q>zh-Hant</q></q></div>
-<div lang="zu"><q><q>zu</q></q></div>
+<q><q>default</q></q>
+<q lang="af"><q>af</q></q>
+<q lang="agq"><q>agq</q></q>
+<q lang="ak"><q>ak</q></q>
+<q lang="am"><q>am</q></q>
+<q lang="ar"><q>ar</q></q>
+<q lang="asa"><q>asa</q></q>
+<q lang="az-Cyrl"><q>az-Cyrl</q></q>
+<q lang="bas"><q>bas</q></q>
+<q lang="bem"><q>bem</q></q>
+<q lang="bez"><q>bez</q></q>
+<q lang="bg"><q>bg</q></q>
+<q lang="bm"><q>bm</q></q>
+<q lang="bn"><q>bn</q></q>
+<q lang="br"><q>br</q></q>
+<q lang="brx"><q>brx</q></q>
+<q lang="bs-Cyrl"><q>bs-Cyrl</q></q>
+<q lang="ca"><q>ca</q></q>
+<q lang="cgg"><q>cgg</q></q>
+<q lang="chr"><q>chr</q></q>
+<q lang="cs"><q>cs</q></q>
+<q lang="da"><q>da</q></q>
+<q lang="dav"><q>dav</q></q>
+<q lang="de"><q>de</q></q>
+<q lang="de-CH"><q>de-CH</q></q>
+<q lang="dje"><q>dje</q></q>
+<q lang="dua"><q>dua</q></q>
+<q lang="dyo"><q>dyo</q></q>
+<q lang="dz"><q>dz</q></q>
+<q lang="ebu"><q>ebu</q></q>
+<q lang="ee"><q>ee</q></q>
+<q lang="el"><q>el</q></q>
+<q lang="en"><q>en</q></q>
+<q lang="en-GB"><q>en-GB</q></q>
+<q lang="es"><q>es</q></q>
+<q lang="et"><q>et</q></q>
+<q lang="eu"><q>eu</q></q>
+<q lang="ewo"><q>ewo</q></q>
+<q lang="fa"><q>fa</q></q>
+<q lang="ff"><q>ff</q></q>
+<q lang="fi"><q>fi</q></q>
+<q lang="fr"><q>fr</q></q>
+<q lang="fr-CA"><q>fr-CA</q></q>
+<q lang="fr-CH"><q>fr-CH</q></q>
+<q lang="gsw"><q>gsw</q></q>
+<q lang="gu"><q>gu</q></q>
+<q lang="guz"><q>guz</q></q>
+<q lang="ha"><q>ha</q></q>
+<q lang="he"><q>he</q></q>
+<q lang="hi"><q>hi</q></q>
+<q lang="hr"><q>hr</q></q>
+<q lang="hu"><q>hu</q></q>
+<q lang="id"><q>id</q></q>
+<q lang="ig"><q>ig</q></q>
+<q lang="it"><q>it</q></q>
+<q lang="ja"><q>ja</q></q>
+<q lang="jgo"><q>jgo</q></q>
+<q lang="jmc"><q>jmc</q></q>
+<q lang="kab"><q>kab</q></q>
+<q lang="kam"><q>kam</q></q>
+<q lang="kde"><q>kde</q></q>
+<q lang="kea"><q>kea</q></q>
+<q lang="khq"><q>khq</q></q>
+<q lang="ki"><q>ki</q></q>
+<q lang="kkj"><q>kkj</q></q>
+<q lang="kln"><q>kln</q></q>
+<q lang="km"><q>km</q></q>
+<q lang="kn"><q>kn</q></q>
+<q lang="ko"><q>ko</q></q>
+<q lang="ksb"><q>ksb</q></q>
+<q lang="ksf"><q>ksf</q></q>
+<q lang="lag"><q>lag</q></q>
+<q lang="lg"><q>lg</q></q>
+<q lang="ln"><q>ln</q></q>
+<q lang="lo"><q>lo</q></q>
+<q lang="lt"><q>lt</q></q>
+<q lang="lu"><q>lu</q></q>
+<q lang="luo"><q>luo</q></q>
+<q lang="luy"><q>luy</q></q>
+<q lang="lv"><q>lv</q></q>
+<q lang="mas"><q>mas</q></q>
+<q lang="mer"><q>mer</q></q>
+<q lang="mfe"><q>mfe</q></q>
+<q lang="mg"><q>mg</q></q>
+<q lang="mgo"><q>mgo</q></q>
+<q lang="mk"><q>mk</q></q>
+<q lang="ml"><q>ml</q></q>
+<q lang="mr"><q>mr</q></q>
+<q lang="ms"><q>ms</q></q>
+<q lang="mua"><q>mua</q></q>
+<q lang="my"><q>my</q></q>
+<q lang="naq"><q>naq</q></q>
+<q lang="nb"><q>nb</q></q>
+<q lang="nd"><q>nd</q></q>
+<q lang="nl"><q>nl</q></q>
+<q lang="nmg"><q>nmg</q></q>
+<q lang="nn"><q>nn</q></q>
+<q lang="nnh"><q>nnh</q></q>
+<q lang="nus"><q>nus</q></q>
+<q lang="nyn"><q>nyn</q></q>
+<q lang="pl"><q>pl</q></q>
+<q lang="pt"><q>pt</q></q>
+<q lang="pt-PT"><q>pt-PT</q></q>
+<q lang="rn"><q>rn</q></q>
+<q lang="ro"><q>ro</q></q>
+<q lang="rof"><q>rof</q></q>
+<q lang="ru"><q>ru</q></q>
+<q lang="rw"><q>rw</q></q>
+<q lang="rwk"><q>rwk</q></q>
+<q lang="saq"><q>saq</q></q>
+<q lang="sbp"><q>sbp</q></q>
+<q lang="seh"><q>seh</q></q>
+<q lang="ses"><q>ses</q></q>
+<q lang="sg"><q>sg</q></q>
+<q lang="shi"><q>shi</q></q>
+<q lang="shi-Tfng"><q>shi-Tfng</q></q>
+<q lang="si"><q>si</q></q>
+<q lang="sk"><q>sk</q></q>
+<q lang="sl"><q>sl</q></q>
+<q lang="sn"><q>sn</q></q>
+<q lang="so"><q>so</q></q>
+<q lang="sq"><q>sq</q></q>
+<q lang="sr"><q>sr</q></q>
+<q lang="sr-Latn"><q>sr-Latn</q></q>
+<q lang="sv"><q>sv</q></q>
+<q lang="sw"><q>sw</q></q>
+<q lang="swc"><q>swc</q></q>
+<q lang="ta"><q>ta</q></q>
+<q lang="te"><q>te</q></q>
+<q lang="teo"><q>teo</q></q>
+<q lang="th"><q>th</q></q>
+<q lang="ti-ER"><q>ti-ER</q></q>
+<q lang="to"><q>to</q></q>
+<q lang="tr"><q>tr</q></q>
+<q lang="twq"><q>twq</q></q>
+<q lang="tzm"><q>tzm</q></q>
+<q lang="uk"><q>uk</q></q>
+<q lang="ur"><q>ur</q></q>
+<q lang="vai"><q>vai</q></q>
+<q lang="vai-Latn"><q>vai-Latn</q></q>
+<q lang="vi"><q>vi</q></q>
+<q lang="vun"><q>vun</q></q>
+<q lang="xh"><q>xh</q></q>
+<q lang="xog"><q>xog</q></q>
+<q lang="yav"><q>yav</q></q>
+<q lang="yo"><q>yo</q></q>
+<q lang="zh"><q>zh</q></q>
+<q lang="zh-Hant"><q>zh-Hant</q></q>
+<q lang="zu"><q>zu</q></q>
diff --git a/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-html-expected.txt b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-html-expected.txt
new file mode 100644
index 0000000..8d2deb2
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-html-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS Page with <embed type=text/html src=/resources/blank.html>
+PASS Page with <object type=text/html data=/resources/blank.html>
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-img-expected.txt b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-img-expected.txt
new file mode 100644
index 0000000..c18a85d
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-img-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS Page with <embed type=image/png src=/images/blue.png>
+PASS Page with <object type=image/png data=/images/blue.png>
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-js-expected.txt b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-js-expected.txt
new file mode 100644
index 0000000..4f43e2e
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-js-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS Page with <embed type=application/javascript src=/resources/test-only-api.js>
+PASS Page with <object type=application/javascript data=/resources/test-only-api.js>
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4-expected.txt b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4-expected.txt
new file mode 100644
index 0000000..b6cd5200
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS Page with <embed type=undefined src=/media/white.mp4>
+PASS Page with <object type=undefined data=/media/white.mp4>
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found-expected.txt b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found-expected.txt
new file mode 100644
index 0000000..972e753
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS Page with <embed type=image/png src=/404.png>
+NOTRUN Page with <object type=image/png data=/404.png> Should be BFCached but actually wasn't
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only-expected.txt b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only-expected.txt
new file mode 100644
index 0000000..fd966e6
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/back-forward-cache-embed/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS Page with <embed type=text/html src=undefined>
+PASS Page with <object type=text/html data=undefined>
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/fullscreen/rendering/backdrop-iframe.html b/third_party/blink/web_tests/fullscreen/rendering/backdrop-iframe.html
deleted file mode 100644
index 94d0ad8..0000000
--- a/third_party/blink/web_tests/fullscreen/rendering/backdrop-iframe.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<title>::backdrop for a fullscreen iframe element</title>
-<script src="../trusted-click.js"></script>
-<style>
-iframe::backdrop {
-  background: green;
-}
-</style>
-<iframe></iframe>
-<script>
-testRunner.waitUntilDone();
-// TODO: "var t" is silly everywhere in this dir
-var t = { step_func: func => func() };
-trusted_request(t, document.querySelector("iframe"));
-document.addEventListener("fullscreenchange", function() {
-  testRunner.notifyDone();
-});
-</script>
diff --git a/third_party/blink/web_tests/fullscreen/rendering/backdrop-object.html b/third_party/blink/web_tests/fullscreen/rendering/backdrop-object.html
deleted file mode 100644
index 846eef4..0000000
--- a/third_party/blink/web_tests/fullscreen/rendering/backdrop-object.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<title>::backdrop for a fullscreen object element</title>
-<script src="../trusted-click.js"></script>
-<style>
-object::backdrop {
-  background: blue;
-}
-</style>
-<object width="200" type="image/svg+xml" data="../../svg/as-image/resources/100px-green-rect.svg"></object>
-<script>
-var object = document.querySelector("object");
-Promise.all([
-    new Promise((resolve, reject) => document.addEventListener("fullscreenchange", resolve)),
-    new Promise((resolve, reject) => object.addEventListener("load", resolve))
-]).then(() => testRunner.notifyDone());
-
-testRunner.waitUntilDone();
-var t = { step_func: func => func() };
-trusted_request(t, object);
-</script>
diff --git a/third_party/blink/web_tests/http/tests/cookies/resources/cookies-test-pre.js b/third_party/blink/web_tests/http/tests/cookies/resources/cookies-test-pre.js
index b7f5d9d..3cf1927 100644
--- a/third_party/blink/web_tests/http/tests/cookies/resources/cookies-test-pre.js
+++ b/third_party/blink/web_tests/http/tests/cookies/resources/cookies-test-pre.js
@@ -159,7 +159,7 @@
     try {
         var xhr = new XMLHttpRequest();
         xhr.open("GET", "resources/setCookies.cgi", false);
-        xhr.setRequestHeader("SET-COOKIE", cookie);
+        xhr.setRequestHeader("X-SET-COOKIE", cookie);
         xhr.send(null);
         if (xhr.status == 200) {
             // This is to clear them later.
diff --git a/third_party/blink/web_tests/http/tests/cookies/resources/setCookies.cgi b/third_party/blink/web_tests/http/tests/cookies/resources/setCookies.cgi
index 17dc34a..212d6d8 100755
--- a/third_party/blink/web_tests/http/tests/cookies/resources/setCookies.cgi
+++ b/third_party/blink/web_tests/http/tests/cookies/resources/setCookies.cgi
@@ -4,9 +4,9 @@
 print "Content-Type: text/plain\n";
 print "Access-Control-Allow-Origin: *\n";
 print "Access-Control-Allow-Credentials: true\n";
-print "Access-Control-Allow-Headers: SET-COOKIE\n";
+print "Access-Control-Allow-Headers: X-SET-COOKIE\n";
 print "Cache-Control: no-store\n";
 print 'Cache-Control: no-cache="set-cookie"' . "\n";
 
-# We only map the SET_COOKIE request header to "Set-Cookie"
-print "Set-Cookie: " . $ENV{"HTTP_SET_COOKIE"} . "\n\n";
+# We only map the X-SET-COOKIE request header to "Set-Cookie"
+print "Set-Cookie: " . $ENV{"HTTP_X_SET_COOKIE"} . "\n\n";
diff --git a/third_party/blink/web_tests/http/tests/devtools/debugger/stop-on-debugger-from-detached-iframe.js b/third_party/blink/web_tests/http/tests/devtools/debugger/stop-on-debugger-from-detached-iframe.js
index 3cfddf8..af91a7c8 100644
--- a/third_party/blink/web_tests/http/tests/devtools/debugger/stop-on-debugger-from-detached-iframe.js
+++ b/third_party/blink/web_tests/http/tests/devtools/debugger/stop-on-debugger-from-detached-iframe.js
@@ -16,6 +16,7 @@
     w.eval('debugger;window');
   `;
 
+  ProtocolClient.test.suppressRequestErrors = true;
   SourcesTestRunner.runDebuggerTestSuite([function (next) {
     SourcesTestRunner.waitUntilPaused(paused);
     TestRunner.evaluateInPage(script);
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger/debugger-disable-enable.js b/third_party/blink/web_tests/http/tests/devtools/sources/debugger/debugger-disable-enable.js
index ce4b6148..6f21430f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger/debugger-disable-enable.js
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger/debugger-disable-enable.js
@@ -34,18 +34,19 @@
   }
 
   function step4() {
-    TestRunner.addResult('function evaluated without a pause on the breakpoint.');
-    TestRunner.debuggerModel.addEventListener(SDK.DebuggerModel.Events.DebuggerWasEnabled, step5, this);
+    TestRunner.addResult('Function evaluated without a pause on the breakpoint.');
+    TestRunner.addSniffer(TestRunner.debuggerModel, "setBreakpointByURL", step5);
+    TestRunner.addResult('Enabling debugger.');
     TestRunner.debuggerModel.enableDebugger();
   }
 
   function step5() {
-    TestRunner.addResult('Debugger was enabled');
-    TestRunner.debuggerModel.removeEventListener(SDK.DebuggerModel.Events.DebuggerWasEnabled, step5, this);
+    TestRunner.addResult('Breakpoint was set after re-enabling.');
     SourcesTestRunner.runTestFunctionAndWaitUntilPaused(step6);
   }
 
   function step6() {
+    TestRunner.addResult('Function evaluated and paused on breakpoint.');
     SourcesTestRunner.completeDebuggerTest();
   }
 })();
diff --git a/third_party/blink/web_tests/http/tests/fetch/resources/fetch-test-helpers.js b/third_party/blink/web_tests/http/tests/fetch/resources/fetch-test-helpers.js
index abddaee..05ec392 100644
--- a/third_party/blink/web_tests/http/tests/fetch/resources/fetch-test-helpers.js
+++ b/third_party/blink/web_tests/http/tests/fetch/resources/fetch-test-helpers.js
@@ -94,8 +94,8 @@
   ['Accept-Charset', 'Accept-Encoding', 'Access-Control-Request-Headers',
    'Access-Control-Request-Method', 'Connection', 'Content-Length',
    'Cookie', 'Cookie2', 'Date', 'DNT', 'Expect', 'Host', 'Keep-Alive',
-   'Origin', 'Referer', 'TE', 'Trailer', 'Transfer-Encoding', 'Upgrade',
-   'User-Agent', 'Via', 'Proxy-', 'Sec-', 'Proxy-FooBar', 'Sec-FooBar'];
+   'Origin', 'Referer', 'Set-Cookie', 'TE', 'Trailer', 'Transfer-Encoding',
+   'Upgrade', 'User-Agent', 'Via', 'Proxy-', 'Sec-', 'Proxy-FooBar', 'Sec-FooBar'];
 var FORBIDDEN_RESPONSE_HEADER_NAMES =
   ['Set-Cookie', 'Set-Cookie2',
    'set-cookie', 'set-cookie2',
diff --git a/third_party/blink/web_tests/http/tests/fetch/script-tests/headers-guard.js b/third_party/blink/web_tests/http/tests/fetch/script-tests/headers-guard.js
index 9061647..e725428d 100644
--- a/third_party/blink/web_tests/http/tests/fetch/script-tests/headers-guard.js
+++ b/third_party/blink/web_tests/http/tests/fetch/script-tests/headers-guard.js
@@ -125,8 +125,15 @@
                 testIgnoreHeaderName(headers, header);
               });
 
+          // Take into account overlapping forbidden header names.
+          var lower = FORBIDDEN_HEADER_NAMES.map(header => {
+            return header.toLowerCase();
+          });
+          var non_overlapping_headers =
+              FORBIDDEN_RESPONSE_HEADER_NAMES.filter(x => !lower.includes(x.toLowerCase()));
+
           // Other header names must be accepted.
-          FORBIDDEN_RESPONSE_HEADER_NAMES
+          non_overlapping_headers
             .concat(SIMPLE_HEADER_NAMES)
             .concat([CONTENT_TYPE])
             .concat(NON_SIMPLE_HEADER_NAMES)
@@ -154,8 +161,15 @@
                             header + ' must be ignored (2)');
             });
 
+        // Take into account overlapping forbidden header names.
+        var lower = FORBIDDEN_HEADER_NAMES.map(header => {
+          return header.toLowerCase();
+        });
+        var non_overlapping_headers =
+            FORBIDDEN_RESPONSE_HEADER_NAMES.filter(x => !lower.includes(x.toLowerCase()));
+
         // Other header names must be accepted.
-        FORBIDDEN_RESPONSE_HEADER_NAMES
+        non_overlapping_headers
           .concat(SIMPLE_HEADER_NAMES)
           .concat([CONTENT_TYPE])
           .concat(NON_SIMPLE_HEADER_NAMES)
@@ -316,8 +330,15 @@
                 testIgnoreHeaderName(headers, header);
               });
 
+          // Take into account overlapping forbidden header names.
+          var lower = FORBIDDEN_RESPONSE_HEADER_NAMES.map(header => {
+            return header.toLowerCase();
+          });
+          var non_overlapping_headers =
+              FORBIDDEN_HEADER_NAMES.filter(x => !lower.includes(x.toLowerCase()));
+
           // Other header names must be accepted.
-          FORBIDDEN_HEADER_NAMES
+          non_overlapping_headers
             .concat(SIMPLE_HEADER_NAMES)
             .concat([CONTENT_TYPE])
             .concat(NON_SIMPLE_HEADER_NAMES)
@@ -343,8 +364,15 @@
                         header + ' must be ignored (2)');
         });
 
+    // Take into account overlapping forbidden header names.
+    var lower = FORBIDDEN_RESPONSE_HEADER_NAMES.map(header => {
+      return header.toLowerCase();
+    });
+    var non_overlapping_headers =
+        FORBIDDEN_HEADER_NAMES.filter(x => !lower.includes(x.toLowerCase()));
+
     // Other header names must be accepted.
-    FORBIDDEN_HEADER_NAMES
+    non_overlapping_headers
       .concat(SIMPLE_HEADER_NAMES)
       .concat([CONTENT_TYPE])
       .concat(NON_SIMPLE_HEADER_NAMES)
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/fledge_join.html b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/fledge_join.html
index 931b50ef..360937c 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/fledge_join.html
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/fledge_join.html
@@ -1,5 +1,8 @@
 <script>
-for (var i = 0; i < 2; ++i) {
+iterLimit = 2;
+if (location.search !== '')
+  iterLimit = parseInt(location.search.substr(1));
+for (var i = 0; i < iterLimit; ++i) {
   navigator.joinAdInterestGroup({
     name: i,
     owner: "https://a.test:8443/",
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-frame.js b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-frame.js
new file mode 100644
index 0000000..82f1e950
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-frame.js
@@ -0,0 +1,79 @@
+(async function(testRunner) {
+  const base = 'https://a.test:8443/inspector-protocol/resources/'
+  const bp = testRunner.browserP();
+  const {page, session, dp} = await testRunner.startBlank(
+      'Tracing of FLEDGE worklets in subframes.',
+      {url: base + 'fledge_join.html?40'});
+
+  const TracingHelper =
+      await testRunner.loadScript('../resources/tracing-test.js');
+  const tracingHelper = new TracingHelper(testRunner, session);
+  await tracingHelper.startTracing('fledge');
+
+  function handleUrn(input) {
+    if (typeof input === 'string' && input.startsWith('urn:uuid:'))
+      return 'urn:uuid:(randomized)';
+    return input;
+  }
+
+  const createChildFrame = function(url) {
+    return new Promise(resolve => {
+      const frame = document.createElement(`iframe`);
+      frame.id = 'frame';
+      frame.src = url;
+      frame.addEventListener('load', resolve);
+      document.body.appendChild(frame);
+    });
+  };
+
+  // Navigate away to a cross-site context compared to the eventual frame,
+  // now the join has completed.
+  await page.navigate(
+      'https://b.test:8443/inspector-protocol/resources/blank.html');
+
+  // Enable auto-attach so we can talk to the frame's target easily.
+  await dp.Target.setAutoAttach(
+      {autoAttach: true, waitForDebuggerOnStart: false, flatten: true});
+
+  const auctionJs = `
+    navigator.runAdAuction({
+      decisionLogicUrl: "${base}fledge_decision_logic.js.php",
+      seller: "https://a.test:8443",
+      interestGroupBuyers: ["https://a.test:8443"]})`;
+
+  const makeFrameJS = `
+    (${createChildFrame.toString()})('${base + 'iframe.html'}')
+  `;
+
+  const frameTargetPromise = dp.Target.onceAttachedToTarget();
+  await session.evaluateAsync(makeFrameJS);
+  const frameTarget = await frameTargetPromise;
+  const frameSession = session.createChild(frameTarget.params.sessionId);
+  const winner = await frameSession.evaluateAsync(auctionJs);
+  testRunner.log('Auction winner:' + handleUrn(winner));
+
+  const devtoolsEvents = await tracingHelper.stopTracing(/fledge/);
+
+  var sawBidders = 0;
+  var sawSellers = 0;
+  for (ev of devtoolsEvents) {
+    if (ev.name === 'generate_bid')
+      ++sawBidders;
+    if (ev.name === 'score_ad')
+      ++sawSellers;
+  }
+
+  if (sawBidders >= 30) {
+    testRunner.log('Saw enough bidders');
+  } else {
+    testRunner.log('Saw too few bidders:' + sawBidders);
+  }
+
+  if (sawSellers >= 30) {
+    testRunner.log('Saw enough sellers');
+  } else {
+    testRunner.log('Saw too few sellers:' + sawSellers);
+  }
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js
new file mode 100644
index 0000000..e588758
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js
@@ -0,0 +1,52 @@
+(async function(testRunner) {
+  const base = 'https://a.test:8443/inspector-protocol/resources/'
+  const bp = testRunner.browserP();
+  const {page, session, dp} = await testRunner.startBlank(
+      'Tracing of FLEDGE worklets.', {url: base + 'fledge_join.html?40'});
+
+  const TracingHelper =
+      await testRunner.loadScript('../resources/tracing-test.js');
+  const tracingHelper = new TracingHelper(testRunner, session);
+  await tracingHelper.startTracing('fledge');
+
+  function handleUrn(input) {
+    if (typeof input === 'string' && input.startsWith('urn:uuid:'))
+      return 'urn:uuid:(randomized)';
+    return input;
+  }
+
+  const auctionJs = `
+    navigator.runAdAuction({
+      decisionLogicUrl: "${base}fledge_decision_logic.js.php",
+      seller: "https://a.test:8443",
+      interestGroupBuyers: ["https://a.test:8443"]})`;
+
+
+  const winner = await session.evaluateAsync(auctionJs);
+  testRunner.log('Auction winner:' + handleUrn(winner));
+
+  const devtoolsEvents = await tracingHelper.stopTracing(/fledge/);
+
+  var sawBidders = 0;
+  var sawSellers = 0;
+  for (ev of devtoolsEvents) {
+    if (ev.name === 'generate_bid')
+      ++sawBidders;
+    if (ev.name === 'score_ad')
+      ++sawSellers;
+  }
+
+  if (sawBidders >= 30) {
+    testRunner.log('Saw enough bidders');
+  } else {
+    testRunner.log('Saw too few bidders:' + sawBidders);
+  }
+
+  if (sawSellers >= 30) {
+    testRunner.log('Saw enough sellers');
+  } else {
+    testRunner.log('Saw too few sellers:' + sawSellers);
+  }
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/media/media-controls-live-timeline.html b/third_party/blink/web_tests/http/tests/media/media-controls-live-timeline.html
index 7ee055b..37319a67 100644
--- a/third_party/blink/web_tests/http/tests/media/media-controls-live-timeline.html
+++ b/third_party/blink/web_tests/http/tests/media/media-controls-live-timeline.html
@@ -9,38 +9,49 @@
   const pause_delay = 1;  // 1 second.
 
   mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData){
-    mediaElement.play();
-    mediaSource.duration = +Infinity;
-    let timeline = timelineElement(mediaElement);
 
     // Append all media data for complete playback.
     test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer end update.');
     test.expectEvent(mediaElement, 'loadedmetadata', 'Reached HAVE_METADATA');
     test.expectEvent(mediaElement, 'playing', 'Playing media.');
     sourceBuffer.appendBuffer(mediaData);
+    let timeline = timelineElement(mediaElement);
 
-    test.waitForExpectedEvents(function() {
-      test.waitForCurrentTimeChange(mediaElement, function() {
-        assert_approx_equals(Number(timeline.value), Number(timeline.max),
-                             epsilon, "timline thumb should be near the end");
+    var playPromise = mediaElement.play();
+    assert_true(playPromise !== undefined, "Video element |play| method did not return a promise");
 
-        mediaElement.onpause = test.step_func(function() {
-          // Timeline value should be at least 1s away from end at some point
-          // after paused.
-          function waitForTimeline() {
-            if (Number(timeline.max) - Number(timeline.value) >= pause_delay) {
-              test.done();
-              return;
+
+    playPromise.then(_ => {
+      mediaSource.duration = +Infinity;
+      test.waitForExpectedEvents(function() {
+        test.waitForCurrentTimeChange(mediaElement, function() {
+          assert_approx_equals(Number(timeline.value), Number(timeline.max),
+                               epsilon, "timline thumb should be near the end");
+
+          mediaElement.onpause = test.step_func(function() {
+            // Timeline value should be at least 1s away from end at some point
+            // after paused.
+            function waitForTimeline() {
+              if (Number(timeline.max) - Number(timeline.value) >= pause_delay) {
+                test.done();
+                return;
+              }
+              test.step_timeout(waitForTimeline, 1000);
             }
-            test.step_timeout(waitForTimeline, 1000);
-          }
 
-          waitForTimeline();
+            waitForTimeline();
+          });
+
+          mediaElement.pause();
         });
-
-        mediaElement.pause();
       });
+    }).catch(err => {
+      // No autoplay, are you running the webtests?
+      assert_false(true, "autoplay policy is disabling this test");
     });
-  }, "Timeline work properly when playing live video");
+
+  }, "Timeline work properly when playing live video", {
+    "enable_controls": true
+  });
 
 </script>
diff --git a/third_party/blink/web_tests/http/tests/media/media-source/mediasource-util.js b/third_party/blink/web_tests/http/tests/media/media-source/mediasource-util.js
index 6858fa1c..df8b2f8 100644
--- a/third_party/blink/web_tests/http/tests/media/media-source/mediasource-util.js
+++ b/third_party/blink/web_tests/http/tests/media/media-source/mediasource-util.js
@@ -397,7 +397,9 @@
     };
 
     // In addition to test harness's async_test() properties parameter, this
-    // function recognizes the property allow_media_element_error.
+    // function recognizes a custom properties dict with custom entries:
+    //   - allow_media_element_error: don't immediately fail on media player error
+    //   - enable_controls: add the default chromium media controls (timeline, play, volume) to the player
     window['mediasource_testafterdataloaded'] = function(testFunction, description, properties)
     {
         mediasource_test(function(test, mediaElement, mediaSource)
@@ -412,6 +414,9 @@
             if (properties == null || properties.allow_media_element_error == null || !properties.allow_media_element_error)
                 test.failOnEvent(mediaElement, 'error');
 
+            if (properties !== undefined && properties.enable_controls !== undefined && properties.enable_controls)
+                mediaElement.setAttribute('controls', true);
+
             var sourceBuffer = mediaSource.addSourceBuffer(segmentInfo.type);
             MediaSourceUtil.loadBinaryData(test, segmentInfo.url, function(mediaData)
             {
diff --git a/third_party/blink/web_tests/http/tests/navigation/ping-cookie.html b/third_party/blink/web_tests/http/tests/navigation/ping-cookie.html
index e0a4dd5..96becc2 100644
--- a/third_party/blink/web_tests/http/tests/navigation/ping-cookie.html
+++ b/third_party/blink/web_tests/http/tests/navigation/ping-cookie.html
@@ -18,7 +18,7 @@
     try {
         var xhr = new XMLHttpRequest();
         xhr.open("GET", "../cookies/resources/setCookies.cgi", false);
-        xhr.setRequestHeader("SET-COOKIE", "hello=world;path=/");
+        xhr.setRequestHeader("X-SET-COOKIE", "hello=world;path=/");
         xhr.send(null);
         if (xhr.status != 200) {
             document.getElementsByTagName("body")[0].appendChild(document.createTextNode("FAILED: cookie not set"));
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/css/css-color/parsing/system-color-valid-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-color/parsing/system-color-valid-expected.txt
new file mode 100644
index 0000000..0ab1033
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-color/parsing/system-color-valid-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+PASS e.style['color'] = "ActiveText" should set the property value
+PASS e.style['color'] = "ButtonBorder" should set the property value
+PASS e.style['color'] = "ButtonFace" should set the property value
+PASS e.style['color'] = "ButtonText" should set the property value
+PASS e.style['color'] = "Canvas" should set the property value
+PASS e.style['color'] = "CanvasText" should set the property value
+PASS e.style['color'] = "Field" should set the property value
+PASS e.style['color'] = "FieldText" should set the property value
+PASS e.style['color'] = "GrayText" should set the property value
+PASS e.style['color'] = "Highlight" should set the property value
+PASS e.style['color'] = "HighlightText" should set the property value
+PASS e.style['color'] = "LinkText" should set the property value
+PASS e.style['color'] = "Mark" should set the property value
+PASS e.style['color'] = "MarkText" should set the property value
+PASS e.style['color'] = "VisitedText" should set the property value
+PASS e.style['color'] = "SelectedItem" should set the property value
+PASS e.style['color'] = "SelectedItemText" should set the property value
+FAIL e.style['color'] = "AccentColor" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['color'] = "AccentColorText" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/editing/run/insertparagraph_6001-last-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/editing/run/insertparagraph_6001-last-expected.txt
index 363db6e..b8b1751 100644
--- a/third_party/blink/web_tests/platform/generic/external/wpt/editing/run/insertparagraph_6001-last-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/editing/run/insertparagraph_6001-last-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 488 tests; 475 PASS, 13 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 785 tests; 772 PASS, 13 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div class=a id=x><div class=b id=y>[]foo</div></div>" queryCommandIndeterm("insertparagraph") before
 PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div class=a id=x><div class=b id=y>[]foo</div></div>" queryCommandState("insertparagraph") before
 PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div class=a id=x><div class=b id=y>[]foo</div></div>" queryCommandValue("insertparagraph") before
@@ -488,5 +488,302 @@
 PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>a &nbsp;[] &nbsp;b</div>" queryCommandIndeterm("insertparagraph") after
 PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>a &nbsp;[] &nbsp;b</div>" queryCommandState("insertparagraph") after
 PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>a &nbsp;[] &nbsp;b</div>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>[abc]</div>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<p>[abc]</p>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><div>[def]</div>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<div>abc</div><p>[def]</p>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>": execCommand("inserttext", false, "d") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><div>[def]</div>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>": execCommand("inserttext", false, "d") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<div>abc</div><p>[def]</p>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>": execCommand("inserttext", false, "d") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>[abc]</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>": execCommand("inserttext", false, "d") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>": execCommand("inserttext", false, "d") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","d"]] "<ol><li>abc</li><li>[def]</li><li>ghi</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>": execCommand("inserttext", false, "a") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<ol><li>[abc]</li><li>def</li></ol>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>": execCommand("inserttext", false, "a") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""],["inserttext","a"]] "<h3>[abc]</h3>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><div>def</div>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>": execCommand("defaultparagraphseparator", false, "div") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" compare innerHTML
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","div"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandValue("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>": execCommand("defaultparagraphseparator", false, "p") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>": execCommand("insertparagraph", false, "") return value
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" checks for modifications to non-editable content
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" compare innerHTML
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandIndeterm("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandState("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandValue("insertparagraph") before
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandIndeterm("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandState("insertparagraph") after
+PASS [["defaultparagraphseparator","p"],["insertparagraph",""]] "<h3>[abc]</h3><p>def</p>" queryCommandValue("insertparagraph") after
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/nosniff/parsing-nosniff.window-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/fetch/nosniff/parsing-nosniff.window-expected.txt
index f08e65ef..4af3e76 100644
--- a/third_party/blink/web_tests/platform/generic/external/wpt/fetch/nosniff/parsing-nosniff.window-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/fetch/nosniff/parsing-nosniff.window-expected.txt
@@ -7,6 +7,7 @@
 PASS X-Content-Type-Options%3A%20nosniff%0D%0AX-Content-Type-Options%3A%20no
 PASS X-Content-Type-Options%3A%20no%0D%0AX-Content-Type-Options%3A%20nosniff
 FAIL X-Content-Type-Options%3A%0D%0AX-Content-Type-Options%3A%20nosniff assert_unreached: Script should have loaded Reached unreachable code
+PASS X-Content-Type-Options%3A%20nosniff%0D%0AX-Content-Type-Options%3A%20nosniff
 FAIL X-Content-Type-Options%3A%20%2Cnosniff assert_unreached: Script should have loaded Reached unreachable code
 FAIL X-Content-Type-Options%3A%20nosniff%0C assert_unreached: Script should have loaded Reached unreachable code
 FAIL X-Content-Type-Options%3A%20nosniff%0B assert_unreached: Script should have loaded Reached unreachable code
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-unregister.https-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-unregister.https-expected.txt
new file mode 100644
index 0000000..4e4fb55
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/html/browsers/browsing-the-web/back-forward-cache/service-worker-unregister.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Unregister service worker while a controlled page is in BFCache assert_implements: Should not be BFCached but actually was undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-html-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-html-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-html-expected.txt
rename to third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-html-expected.txt
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-img-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-img-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-img-expected.txt
rename to third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-img-expected.txt
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-js-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-js-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-js-expected.txt
rename to third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-js-expected.txt
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-mp4-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-mp4-expected.txt
rename to third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-mp4-expected.txt
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-not-found-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-not-found-expected.txt
rename to third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-not-found-expected.txt
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-type-only-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embeded-type-only-expected.txt
rename to third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/bfcache/embedded-type-only-expected.txt
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/devtools/debugger/stop-on-debugger-from-detached-iframe-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/devtools/debugger/stop-on-debugger-from-detached-iframe-expected.txt
index 5a76cff..3293ae4 100644
--- a/third_party/blink/web_tests/platform/generic/http/tests/devtools/debugger/stop-on-debugger-from-detached-iframe-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/http/tests/devtools/debugger/stop-on-debugger-from-detached-iframe-expected.txt
@@ -5,6 +5,6 @@
 Script execution paused.
 Call stack:
     0)  (:1)
-    1)  (stop-on-debugger-from-detached-iframe.js:25)
+    1)  (stop-on-debugger-from-detached-iframe.js:26)
 Script execution resumed.
 
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/devtools/sources/debugger/debugger-disable-enable-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/devtools/sources/debugger/debugger-disable-enable-expected.txt
index 2e4b31f..5bccaf4 100644
--- a/third_party/blink/web_tests/platform/generic/http/tests/devtools/sources/debugger/debugger-disable-enable-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/http/tests/devtools/sources/debugger/debugger-disable-enable-expected.txt
@@ -3,9 +3,11 @@
 Main resource was shown.
 Debugger disabled.
 Evaluating test function.
-function evaluated without a pause on the breakpoint.
-Debugger was enabled
+Function evaluated without a pause on the breakpoint.
+Enabling debugger.
+Breakpoint was set after re-enabling.
 Set timer for test function.
 Script execution paused.
+Function evaluated and paused on breakpoint.
 Script execution resumed.
 
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
new file mode 100644
index 0000000..19a084af
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
@@ -0,0 +1,7 @@
+Tracing of FLEDGE worklets.
+Recording started
+Auction winner:undefined
+Tracing complete
+Saw too few bidders:0
+Saw too few sellers:0
+
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/timeline/auction-worklet-frame-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/timeline/auction-worklet-frame-expected.txt
new file mode 100644
index 0000000..b2616e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/timeline/auction-worklet-frame-expected.txt
@@ -0,0 +1,7 @@
+Tracing of FLEDGE worklets in subframes.
+Recording started
+Auction winner:undefined
+Tracing complete
+Saw too few bidders:0
+Saw too few sellers:0
+
diff --git a/third_party/blink/web_tests/platform/generic/virtual/document-transition/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/document-transition/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt
index 1213a3a..ac6ba65 100644
--- a/third_party/blink/web_tests/platform/generic/virtual/document-transition/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/virtual/document-transition/inspector-protocol/css/css-get-styles-for-document-transition-expected.txt
@@ -52,9 +52,8 @@
                                 value : block
                             }
                             [1] : {
-                                important : true
                                 name : page-transition-tag
-                                value : root !important
+                                value : root
                             }
                         ]
                         shorthandEntries : [
diff --git a/third_party/blink/web_tests/platform/generic/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
new file mode 100644
index 0000000..bcffecb9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
@@ -0,0 +1,7 @@
+Tracing of FLEDGE worklets.
+Recording started
+Auction winner:urn:uuid:(randomized)
+Tracing complete
+Saw enough bidders
+Saw enough sellers
+
diff --git a/third_party/blink/web_tests/platform/generic/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-frame-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-frame-expected.txt
new file mode 100644
index 0000000..aed1aad
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-frame-expected.txt
@@ -0,0 +1,7 @@
+Tracing of FLEDGE worklets in subframes.
+Recording started
+Auction winner:urn:uuid:(randomized)
+Tracing complete
+Saw enough bidders
+Saw enough sellers
+
diff --git a/third_party/blink/web_tests/platform/generic/virtual/wide-gamut/color-canvas-p3-primaries-expected.png b/third_party/blink/web_tests/platform/generic/virtual/wide-gamut/color-canvas-p3-primaries-expected.png
new file mode 100644
index 0000000..8250189
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/virtual/wide-gamut/color-canvas-p3-primaries-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/wide-gamut/README.md b/third_party/blink/web_tests/virtual/wide-gamut/README.md
new file mode 100644
index 0000000..0b4f082
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/wide-gamut/README.md
@@ -0,0 +1,4 @@
+# wide-gamut
+
+This directory contains tests that run with a wide gamut color profile, display p3.
+All tests in this directory run with the flag --force-color-profile=display-p3
diff --git a/third_party/blink/web_tests/virtual/wide-gamut/color-canvas-p3-primaries.html b/third_party/blink/web_tests/virtual/wide-gamut/color-canvas-p3-primaries.html
new file mode 100644
index 0000000..64cd9a8
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/wide-gamut/color-canvas-p3-primaries.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<canvas id='canvas_P3' width=300 height=50></canvas>
+<script>
+// Currently the only way to draw p3 content on canvas is with putImageData.
+// We use this helper function to create a patch of color to be put.
+function generateImageData(buffer, data, red, green, blue, width, height)
+{
+  for(var pos = 0; pos < width*height*4; pos = pos + 4)
+  {
+    buffer[pos    ] = red;
+    buffer[pos + 1] = green;
+    buffer[pos + 2] = blue;
+    buffer[pos + 3] = 255;
+  }
+  data.data.set(buffer);
+}
+
+var canvas_P3 = document.getElementById('canvas_P3');
+var ctx = canvas_P3.getContext('2d', {colorSpace: "display-p3"});
+var width = 50;
+var height = 50;
+var buffer = new Uint8ClampedArray(width * height * 4);
+var data = ctx.createImageData(width, height);
+// Every pair of colors should look slighty different if display-p3 is supported.
+generateImageData(buffer, data, 255, 0, 0, width, height);
+ctx.putImageData(data, 0, 0);
+generateImageData(buffer, data, 240, 0, 0, width, height);
+ctx.putImageData(data, 50, 0);
+
+generateImageData(buffer, data, 0, 255, 0, width, height);
+ctx.putImageData(data, 100, 0);
+generateImageData(buffer, data, 0, 240, 0, width, height);
+ctx.putImageData(data, 150, 0);
+
+generateImageData(buffer, data, 0, 0, 255, width, height);
+ctx.putImageData(data, 200, 0);
+generateImageData(buffer, data, 0, 0, 240, width, height);
+ctx.putImageData(data, 250, 0);
+</script>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/debug-key-test.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/debug-key-test.sub.https.html
new file mode 100644
index 0000000..99a8ffc
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/debug-key-test.sub.https.html
@@ -0,0 +1,96 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/helpers.js"></script>
+<script>
+const source_debug_key_promise_test = testCase =>
+  attribution_reporting_promise_test(async t => {
+    t.add_cleanup(() => clearCookie(testCase.cookie))
+
+    registerAttributionSrc('Attribution-Reporting-Register-Source', {
+      source_event_id :'1',
+      destination: `https://{{host}}`,
+      debug_key: '246',
+    }, testCase.cookie);
+
+    registerAttributionSrc('Attribution-Reporting-Register-Trigger', {
+      event_trigger_data: [{trigger_data: '0'}],
+    });
+
+    const payload = await pollEventLevelReports();
+    assert_equals(payload.reports.length, 1);
+    const report = JSON.parse(payload.reports[0].body);
+
+    if (testCase.keyExpected) {
+      assert_equals(report.source_debug_key, '246');
+    } else {
+      assert_not_own_property(report, 'source_debug_key');
+    }
+
+    assert_not_own_property(report, 'trigger_debug_key');
+  }, `Source: ${testCase.testName}`);
+
+const trigger_debug_key_promise_test = testCase =>
+  attribution_reporting_promise_test(async t => {
+    t.add_cleanup(() => clearCookie(testCase.cookie))
+
+    registerAttributionSrc('Attribution-Reporting-Register-Source', {
+      source_event_id :'1',
+      destination: `https://{{host}}`,
+    });
+
+    registerAttributionSrc('Attribution-Reporting-Register-Trigger', {
+      event_trigger_data: [{trigger_data: '0'}],
+      debug_key: '357',
+    }, testCase.cookie);
+
+    const payload = await pollEventLevelReports();
+    assert_equals(payload.reports.length, 1);
+    const report = JSON.parse(payload.reports[0].body);
+
+    if (testCase.keyExpected) {
+      assert_equals(report.trigger_debug_key, '357');
+    } else {
+      assert_not_own_property(report, 'trigger_debug_key');
+    }
+
+    assert_not_own_property(report, 'source_debug_key');
+  }, `Trigger: ${testCase.testName}`);
+
+const testCases = [
+  {
+    testName: 'Valid cookie propagates debug key.',
+    cookie: 'ar_debug=1;Secure;HttpOnly;SameSite=None;Path=/',
+    keyExpected: true,
+  },
+  {
+    testName: 'Missing cookie clears debug key.',
+    cookie: 'foo=1;Secure;HttpOnly;SameSite=None;Path=/',
+    keyExpected: false,
+  },
+  {
+    testName: 'Cookie without Secure clears debug key.',
+    cookie: 'ar_debug=1;HttpOnly;SameSite=None;Path=/',
+    keyExpected: false,
+  },
+  {
+    testName: 'Cookie without HttpOnly clears debug key.',
+    cookie: 'ar_debug=1;Secure;SameSite=None;Path=/',
+    keyExpected: false,
+  },
+  {
+    testName: 'Cookie without SameSite=None clears debug key.',
+    cookie: 'ar_debug=1;Secure;HttpOnly;Path=/',
+    keyExpected: false,
+  },
+  {
+    testName: 'Cookie with narrow Path clears debug key.',
+    cookie: 'ar_debug=1;Secure;HttpOnly;SameSite=None',
+    keyExpected: false,
+  },
+];
+
+testCases.forEach(source_debug_key_promise_test);
+testCases.forEach(trigger_debug_key_promise_test);
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/helpers.js b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/helpers.js
index f1ab48d..0efd4d9 100644
--- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/helpers.js
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/helpers.js
@@ -2,12 +2,15 @@
  * Helper functions for attribution reporting API tests.
  */
 
-attribution_reporting_promise_test = f => promise_test(async t => {
-  t.add_cleanup(() => internals.resetAttributionReporting());
-  t.add_cleanup(() => resetEventLevelReports());
-  t.add_cleanup(() => resetAggregatableReports());
-  return f(t);
-});
+const blankURL = () => new URL('/resources/blank.html', window.location);
+
+const attribution_reporting_promise_test = (f, name) =>
+    promise_test(async t => {
+      t.add_cleanup(() => internals.resetAttributionReporting());
+      t.add_cleanup(() => resetEventLevelReports());
+      t.add_cleanup(() => resetAggregatableReports());
+      return f(t);
+    }, name);
 
 const eventLevelReportsUrl =
     '/.well-known/attribution-reporting/report-event-attribution';
@@ -42,7 +45,7 @@
  * Registers either a source or trigger.
  */
 const registerAttributionSrc = (header, body, cookie = '') => {
-  const url = new URL('/resources/blank.html', window.location);
+  const url = blankURL();
   // , and ) in header values must be escaped with \
   const attributionHeader =
       `header(${header},${encodeForPipe(JSON.stringify(body))})`;
@@ -76,10 +79,18 @@
 const pollAggregatableReports = interval =>
     pollAttributionReports(aggregatableReportsUrl, interval);
 
-const validateReportHeaders = headers => {
-  assert_array_equals(headers['content-type'], ['application/json']);
-  assert_array_equals(headers['cache-control'], ['no-cache']);
-  assert_own_property(headers, 'user-agent');
-  assert_not_own_property(headers, 'cookie');
-  assert_not_own_property(headers, 'referer');
-}
+const validateReportHeaders =
+    headers => {
+      assert_array_equals(headers['content-type'], ['application/json']);
+      assert_array_equals(headers['cache-control'], ['no-cache']);
+      assert_own_property(headers, 'user-agent');
+      assert_not_own_property(headers, 'cookie');
+      assert_not_own_property(headers, 'referer');
+    }
+
+const clearCookie = name => {
+  const url = blankURL();
+  const cookieHeader = `header(Set-Cookie,${encodeForPipe(name)};Max-Age=0)`;
+  url.searchParams.set('pipe', cookieHeader);
+  return fetch(url);
+};
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/source-priority-test.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/source-priority-test.sub.https.html
new file mode 100644
index 0000000..fc0b2b8
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/source-priority-test.sub.https.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/helpers.js"></script>
+<script>
+attribution_reporting_promise_test(async t => {
+  registerAttributionSrc('Attribution-Reporting-Register-Source', {
+    source_event_id: '1',
+    destination: `https://{{host}}`,
+    priority: '11',
+  });
+  registerAttributionSrc('Attribution-Reporting-Register-Source', {
+    source_event_id: '2',
+    destination: `https://{{host}}`,
+    priority: '13',
+  });
+  registerAttributionSrc('Attribution-Reporting-Register-Source', {
+    source_event_id: '3',
+    destination: `https://{{host}}`,
+    priority: '12',
+  });
+
+  registerAttributionSrc('Attribution-Reporting-Register-Trigger', {
+    event_trigger_data: [{trigger_data: '0'}],
+  });
+
+  const payload = await pollEventLevelReports();
+  assert_equals(payload.reports.length, 1);
+  const report = JSON.parse(payload.reports[0].body);
+  assert_equals(report.source_event_id, '2');
+}, 'Trigger is attributed to highest priority source.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/no-root-capture-ref.html b/third_party/blink/web_tests/wpt_internal/document-transition/no-root-capture-ref.html
new file mode 100644
index 0000000..d1ebea8b
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/document-transition/no-root-capture-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Shared transitions: shared element with overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/shared-element-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<style>
+.target {
+  width: 100px;
+  height: 100px;
+  contain: paint;
+  background: blue;
+  overflow-clip-margin: 50px;
+  page-transition-tag: target;
+}
+.child {
+  width: 200px;
+  height: 200px;
+  position: relative;
+  top: 50px;
+  left: 50px;
+  background: green;
+}
+</style>
+
+This text should appear unmodified, since the root isn't captured.
+<div class=target>
+  <div class=child>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/no-root-capture.html b/third_party/blink/web_tests/wpt_internal/document-transition/no-root-capture.html
new file mode 100644
index 0000000..2b29c0d
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/document-transition/no-root-capture.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element with overflow</title>
+<link rel="help" href="https://github.com/WICG/shared-element-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="no-root-capture-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+:root { page-transition-tag: none; }
+.target {
+  width: 100px;
+  height: 100px;
+  contain: paint;
+  background: blue;
+  overflow-clip-margin: 50px;
+  page-transition-tag: target;
+}
+.child {
+  width: 200px;
+  height: 200px;
+  position: relative;
+  top: 50px;
+  left: 50px;
+  background: green;
+}
+
+html::page-transition-container(target) { animation-duration: 300s; }
+html::page-transition-incoming-image(target) { animation: unset; opacity: 0; }
+html::page-transition-outgoing-image(target) {
+  animation: unset;
+  opacity: 1;
+}
+
+/* None of these should apply, so make everything red if it does */
+html::page-transition-container(root) { animation: unset; opacity: 1; background: red; }
+html::page-transition-image-wrapper(root) { visibility: hidden }
+</style>
+
+This text should appear unmodified, since the root isn't captured.
+<div class=target>
+  <div class=child>
+  </div>
+</div>
+
+<script>
+async function runTest() {
+  document.createDocumentTransition().start(() =>
+    requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/nothing-captured-ref.html b/third_party/blink/web_tests/wpt_internal/document-transition/nothing-captured-ref.html
new file mode 100644
index 0000000..d1ebea8b
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/document-transition/nothing-captured-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Shared transitions: shared element with overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/shared-element-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<style>
+.target {
+  width: 100px;
+  height: 100px;
+  contain: paint;
+  background: blue;
+  overflow-clip-margin: 50px;
+  page-transition-tag: target;
+}
+.child {
+  width: 200px;
+  height: 200px;
+  position: relative;
+  top: 50px;
+  left: 50px;
+  background: green;
+}
+</style>
+
+This text should appear unmodified, since the root isn't captured.
+<div class=target>
+  <div class=child>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/nothing-captured.html b/third_party/blink/web_tests/wpt_internal/document-transition/nothing-captured.html
new file mode 100644
index 0000000..1cb72b5
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/document-transition/nothing-captured.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element with overflow</title>
+<link rel="help" href="https://github.com/WICG/shared-element-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="nothing-captured-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+:root { page-transition-tag: none; }
+.target {
+  width: 100px;
+  height: 100px;
+  contain: paint;
+  background: blue;
+  overflow-clip-margin: 50px;
+}
+.child {
+  width: 200px;
+  height: 200px;
+  position: relative;
+  top: 50px;
+  left: 50px;
+  background: green;
+}
+
+/* None of these should apply, so make everything red if it does */
+html::page-transition-container(*) { animation-duration: 300s; }
+html::page-transition-image-wrapper(*) { visibility: hidden }
+html::page-transition { background: red; }
+</style>
+
+This text should appear unmodified, since the root isn't captured.
+<div class=target>
+  <div class=child>
+  </div>
+</div>
+
+<script>
+async function runTest() {
+  document.createDocumentTransition().start(() =>
+    requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/root-captured-as-different-tag-ref.html b/third_party/blink/web_tests/wpt_internal/document-transition/root-captured-as-different-tag-ref.html
new file mode 100644
index 0000000..d0e020b
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/document-transition/root-captured-as-different-tag-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture root elements (ref)</title>
+<link rel="help" href="https://github.com/WICG/shared-element-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+  background: lightblue;
+  width: 100px;
+  height: 100px;
+  contain: paint;
+  position: absolute;
+  font-size: 30pt;
+}
+#e1 {
+  top: 20px;
+  left: 20px;
+}
+</style>
+<div id=e1 class=box></div>
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/root-captured-as-different-tag.html b/third_party/blink/web_tests/wpt_internal/document-transition/root-captured-as-different-tag.html
new file mode 100644
index 0000000..a8e7099c
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/document-transition/root-captured-as-different-tag.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture root elements</title>
+<link rel="help" href="https://github.com/WICG/shared-element-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-captures-root-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+:root { page-transition-tag: another-root; }
+.box {
+  background: lightblue;
+  width: 100px;
+  height: 100px;
+  contain: paint;
+  position: absolute;
+  font-size: 30pt;
+}
+#e1 {
+  top: 20px;
+  left: 20px;
+}
+#shared {
+  contain: paint;
+  width: 100px;
+  height: 100px;
+  background: red;
+  page-transition-tag: shared;
+}
+
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the old contents for 5 minutes.  */
+html::page-transition { background: pink; }
+html::page-transition-container(shared) { animation-duration: 300s; }
+html::page-transition-image-wrapper(shared) { visibility: hidden }
+html::page-transition-outgoing-image(another-root) { animation: unset; opacity: 1 }
+html::page-transition-incoming-image(another-root) { animation: unset; opacity: 0 }
+
+/* This shouldn't apply, so just make it red. */
+html::page-transition-container(root) { animation: unset; opacity: 1; background: red; }
+html::page-transition-image-wrapper(root) { visibility: hidden; }
+</style>
+<div id=e1 class=box></div>
+<div id=shared></div>
+<script>
+async function runTest() {
+  let t = document.createDocumentTransition();
+  t.start(() => {
+    e1.classList.add("dst");
+    document.body.style.background = "red";
+    requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+  });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js
index c3804b7d..9a269c4 100644
--- a/third_party/closure_compiler/externs/file_manager_private.js
+++ b/third_party/closure_compiler/externs/file_manager_private.js
@@ -319,8 +319,10 @@
 chrome.fileManagerPrivate.IOTaskType = {
   COPY: 'copy',
   DELETE: 'delete',
+  EMPTY_TRASH: 'empty_trash',
   EXTRACT: 'extract',
   MOVE: 'move',
+  RESTORE: 'restore',
   TRASH: 'trash',
   ZIP: 'zip',
 };
@@ -706,6 +708,7 @@
  * @typedef {{
  *   destinationFolder: (DirectoryEntry|undefined),
  *   password: (string|undefined),
+ *   restorePaths: (Array<string>|undefined),
  * }}
  */
 chrome.fileManagerPrivate.IOTaskParams;
@@ -954,9 +957,9 @@
  * Returns a list of files that are restricted by any Data Leak Prevention
  * (DLP) rule. |entries| list of source entries to be checked.
  * @param {!Array<!Entry>} entries
- * @param {function((!Array<!chrome.fileManagerPrivate.DlpMetadata>|undefined))} 
+ * @param {function((!Array<!chrome.fileManagerPrivate.DlpMetadata>|undefined))}
  * callback Callback with the list of chrome.fileManagerPrivate.DlpMetadata
- * containing DLP information about the entries.  
+ * containing DLP information about the entries.
  */
 chrome.fileManagerPrivate.getDlpMetadata = function(entries, callback) {};
 
diff --git a/third_party/flatbuffers/BUILD.gn b/third_party/flatbuffers/BUILD.gn
index f43f44b..0ea655b0 100644
--- a/third_party/flatbuffers/BUILD.gn
+++ b/third_party/flatbuffers/BUILD.gn
@@ -40,7 +40,6 @@
 source_set("compiler_files") {
   include_dirs = [ "src/grpc" ]
   sources = [
-    "src/grpc/src/compiler/config.h",
     "src/grpc/src/compiler/cpp_generator.cc",
     "src/grpc/src/compiler/cpp_generator.h",
     "src/grpc/src/compiler/go_generator.cc",
@@ -64,9 +63,13 @@
     "src/include/flatbuffers/reflection.h",
     "src/include/flatbuffers/reflection_generated.h",
     "src/include/flatbuffers/registry.h",
+    "src/src/annotated_binary_text_gen.cpp",
+    "src/src/annotated_binary_text_gen.h",
     "src/src/bfbs_gen.h",
     "src/src/bfbs_gen_lua.cpp",
     "src/src/bfbs_gen_lua.h",
+    "src/src/binary_annotator.cpp",
+    "src/src/binary_annotator.h",
     "src/src/code_generators.cpp",
     "src/src/flatc.cpp",
     "src/src/idl_gen_cpp.cpp",
diff --git a/third_party/flatbuffers/README.chromium b/third_party/flatbuffers/README.chromium
index b1b81af..d8f0b43 100644
--- a/third_party/flatbuffers/README.chromium
+++ b/third_party/flatbuffers/README.chromium
@@ -1,8 +1,8 @@
 Name: FlatBuffers
 Short Name: flatbuffers
 URL: https://github.com/google/flatbuffers
-Version: b8aaccee8248059b2af032cca0eb1d2ddbdb6cdc
-Date: 2021-12-16
+Version: 0fe13cb28ce5a3fb81f654b21cb37c9821194962
+Date: 2022-05-10
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index d5d8a99..5591931 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-12-1-32-g2848378be
-Revision: 2848378be56ea26376e3aff68b1b4b8aa8f8611b
+Version: VER-2-12-1-35-g117df36b4
+Revision: 117df36b4c3a5f7850a3789e92ce54d9341673ff
 CPEPrefix: cpe:/a:freetype:freetype:2.11.1
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/ipcz/src/BUILD.gn b/third_party/ipcz/src/BUILD.gn
index 71cc01e..90436cb 100644
--- a/third_party/ipcz/src/BUILD.gn
+++ b/third_party/ipcz/src/BUILD.gn
@@ -2,9 +2,17 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/buildflag_header.gni")
 import("//build_overrides/ipcz.gni")
 import("//testing/test.gni")
 
+enable_multiprocess_tests = is_linux
+
+buildflag_header("test_buildflags") {
+  header = "test_buildflags.h"
+  flags = [ "ENABLE_IPCZ_MULTIPROCESS_TESTS=$enable_multiprocess_tests" ]
+}
+
 shared_library("ipcz_shared") {
   output_name = "ipcz"
   sources = [
@@ -130,7 +138,7 @@
 
   public = [
     "reference_drivers/blob.h",
-    "reference_drivers/single_process_reference_driver.h",
+    "reference_drivers/sync_reference_driver.h",
   ]
 
   sources = [
@@ -139,19 +147,26 @@
     "reference_drivers/object.h",
     "reference_drivers/random.cc",
     "reference_drivers/random.h",
-    "reference_drivers/single_process_reference_driver.cc",
+    "reference_drivers/single_process_reference_driver_base.cc",
+    "reference_drivers/single_process_reference_driver_base.h",
+    "reference_drivers/sync_reference_driver.cc",
   ]
 
-  if (is_linux) {
+  if (enable_multiprocess_tests) {
     public += [
       "reference_drivers/file_descriptor.h",
+      "reference_drivers/handle_eintr.h",
       "reference_drivers/memfd_memory.h",
+      "reference_drivers/multiprocess_reference_driver.h",
       "reference_drivers/socket_transport.h",
+      "reference_drivers/wrapped_file_descriptor.h",
     ]
     sources += [
       "reference_drivers/file_descriptor.cc",
       "reference_drivers/memfd_memory.cc",
+      "reference_drivers/multiprocess_reference_driver.cc",
       "reference_drivers/socket_transport.cc",
+      "reference_drivers/wrapped_file_descriptor.cc",
     ]
   }
 
@@ -160,7 +175,7 @@
     ":util",
   ]
   public_deps = [ ":ipcz_header" ]
-  configs = [ ":ipcz_include_src_dir" ]
+  public_configs = [ ":ipcz_include_src_dir" ]
 
   deps = []
   if (is_fuchsia) {
@@ -314,7 +329,7 @@
     "ipcz/node_link_test.cc",
     "ipcz/parcel_queue_test.cc",
     "ipcz/sequenced_queue_test.cc",
-    "reference_drivers/single_process_reference_driver_test.cc",
+    "reference_drivers/sync_reference_driver_test.cc",
     "remote_portal_test.cc",
     "test/mock_driver.cc",
     "test/mock_driver.h",
@@ -330,10 +345,13 @@
     "util/stack_trace_test.cc",
   ]
 
-  if (is_linux) {
+  if (enable_multiprocess_tests) {
+    public = [ "test/test_child_launcher.h" ]
     sources += [
       "reference_drivers/memfd_memory_test.cc",
+      "reference_drivers/multiprocess_reference_driver_test.cc",
       "reference_drivers/socket_transport_test.cc",
+      "test/test_child_launcher.cc",
     ]
   }
 
@@ -342,12 +360,13 @@
     "//testing/gtest",
     "//third_party/abseil-cpp:absl",
   ]
+  public_deps = [ ":test_buildflags" ]
   ipcz_deps = [
     ":impl",
     ":ipcz",
-    ":reference_drivers",
     ":util",
   ]
+  ipcz_public_deps = [ ":reference_drivers" ]
 
   configs = [ ":ipcz_include_src_dir" ]
 }
@@ -360,6 +379,7 @@
   sources = [ "test/run_all_tests.cc" ]
   deps = [
     ":ipcz_tests_sources_standalone",
+    ":test_buildflags",
     "${ipcz_src_root}/standalone",
     "//testing/gtest",
   ]
diff --git a/third_party/ipcz/src/api_test.cc b/third_party/ipcz/src/api_test.cc
index 02407d1..ce83991 100644
--- a/third_party/ipcz/src/api_test.cc
+++ b/third_party/ipcz/src/api_test.cc
@@ -5,15 +5,14 @@
 #include <string>
 
 #include "ipcz/ipcz.h"
-#include "reference_drivers/single_process_reference_driver.h"
+#include "reference_drivers/sync_reference_driver.h"
 #include "test/test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ipcz {
 namespace {
 
-const IpczDriver& kDefaultDriver =
-    reference_drivers::kSingleProcessReferenceDriver;
+const IpczDriver& kDefaultDriver = reference_drivers::kSyncReferenceDriver;
 
 using APITest = test::Test;
 
diff --git a/third_party/ipcz/src/box_test.cc b/third_party/ipcz/src/box_test.cc
index bd39f3d..ec814f1 100644
--- a/third_party/ipcz/src/box_test.cc
+++ b/third_party/ipcz/src/box_test.cc
@@ -16,61 +16,21 @@
 
 using Blob = reference_drivers::Blob;
 
-class BoxTestNode : public test::TestNode {
- protected:
-  // Creates a test driver Blob object with an inlined data payload and a shared
-  // memory object with an embedded message.
-  IpczDriverHandle CreateTestBlob(std::string_view inline_message,
-                                  std::string_view shm_message) {
-    IpczDriverHandle memory;
-    EXPECT_EQ(IPCZ_RESULT_OK,
-              GetDriver().AllocateSharedMemory(
-                  shm_message.size(), IPCZ_NO_FLAGS, nullptr, &memory));
-
-    void* address;
-    IpczDriverHandle mapping;
-    EXPECT_EQ(IPCZ_RESULT_OK,
-              GetDriver().MapSharedMemory(memory, IPCZ_NO_FLAGS, nullptr,
-                                          &address, &mapping));
-    memcpy(address, shm_message.data(), shm_message.size());
-    EXPECT_EQ(IPCZ_RESULT_OK,
-              GetDriver().Close(mapping, IPCZ_NO_FLAGS, nullptr));
-
-    return Blob::ReleaseAsHandle(MakeRefCounted<Blob>(
-        GetDriver(), inline_message, absl::MakeSpan(&memory, 1)));
-  }
-
-  bool BlobContentsMatch(IpczDriverHandle blob_handle,
-                         std::string_view expected_inline_message,
-                         std::string_view expected_shm_message) {
-    Ref<Blob> blob = Blob::TakeFromHandle(blob_handle);
-    if (expected_inline_message != blob->message()) {
-      return false;
-    }
-
-    ABSL_ASSERT(blob->handles().size() == 1);
-    ABSL_ASSERT(blob->handles()[0] != IPCZ_INVALID_DRIVER_HANDLE);
-
-    void* address;
-    IpczDriverHandle mapping;
-    EXPECT_EQ(IPCZ_RESULT_OK,
-              GetDriver().MapSharedMemory(blob->handles()[0], IPCZ_NO_FLAGS,
-                                          nullptr, &address, &mapping));
-    std::string_view shm_message(static_cast<char*>(address),
-                                 expected_shm_message.size());
-    const bool matched = (shm_message == expected_shm_message);
-    EXPECT_EQ(IPCZ_RESULT_OK,
-              GetDriver().Close(mapping, IPCZ_NO_FLAGS, nullptr));
-    return matched;
-  }
-};
-
+using BoxTestNode = test::TestNode;
 using BoxTest = test::MultinodeTest<BoxTestNode>;
 
+IpczDriverHandle CreateTestBlob(std::string_view message) {
+  return Blob::ReleaseAsHandle(MakeRefCounted<Blob>(message));
+}
+
+std::string GetBlobContents(IpczDriverHandle handle) {
+  Ref<Blob> blob = Blob::TakeFromHandle(handle);
+  return std::string(blob->message());
+}
+
 TEST_P(BoxTest, BoxAndUnbox) {
   constexpr const char kMessage[] = "Hello, world?";
-  IpczDriverHandle blob_handle =
-      Blob::ReleaseAsHandle(MakeRefCounted<Blob>(GetDriver(), kMessage));
+  IpczDriverHandle blob_handle = CreateTestBlob(kMessage);
 
   IpczHandle box;
   EXPECT_EQ(IPCZ_RESULT_OK,
@@ -79,13 +39,11 @@
   blob_handle = IPCZ_INVALID_DRIVER_HANDLE;
   EXPECT_EQ(IPCZ_RESULT_OK,
             ipcz().Unbox(box, IPCZ_NO_FLAGS, nullptr, &blob_handle));
-
-  Ref<Blob> blob = Blob::TakeFromHandle(blob_handle);
-  EXPECT_EQ(kMessage, blob->message());
+  EXPECT_EQ(kMessage, GetBlobContents(blob_handle));
 }
 
 TEST_P(BoxTest, CloseBox) {
-  Ref<Blob> blob = MakeRefCounted<Blob>(GetDriver(), "meh");
+  Ref<Blob> blob = MakeRefCounted<Blob>("meh");
   Ref<Blob::RefCountedFlag> destroyed = blob->destruction_flag_for_testing();
   IpczDriverHandle blob_handle = Blob::ReleaseAsHandle(std::move(blob));
 
@@ -100,8 +58,7 @@
 
 TEST_P(BoxTest, Peek) {
   constexpr const char kMessage[] = "Hello, world?";
-  IpczDriverHandle blob_handle =
-      Blob::ReleaseAsHandle(MakeRefCounted<Blob>(GetDriver(), kMessage));
+  IpczDriverHandle blob_handle = CreateTestBlob(kMessage);
   IpczHandle box;
   EXPECT_EQ(IPCZ_RESULT_OK,
             ipcz().Box(node(), blob_handle, IPCZ_NO_FLAGS, nullptr, &box));
@@ -126,7 +83,6 @@
 
 constexpr const char kMessage1[] = "Hello, world?";
 constexpr const char kMessage2[] = "Hello, world!";
-constexpr const char kMessage3[] = "Hello! World!";
 
 MULTINODE_TEST_NODE(BoxTestNode, TransferBoxClient) {
   IpczHandle b = ConnectToBroker();
@@ -134,12 +90,12 @@
   std::string message;
   IpczHandle box;
   EXPECT_EQ(IPCZ_RESULT_OK, WaitToGet(b, &message, {&box, 1}));
-  EXPECT_EQ(kMessage3, message);
+  EXPECT_EQ(kMessage2, message);
 
   IpczDriverHandle blob_handle;
   EXPECT_EQ(IPCZ_RESULT_OK,
             ipcz().Unbox(box, IPCZ_NO_FLAGS, nullptr, &blob_handle));
-  EXPECT_TRUE(BlobContentsMatch(blob_handle, kMessage1, kMessage2));
+  EXPECT_EQ(kMessage1, GetBlobContents(blob_handle));
 
   Close(b);
 }
@@ -147,12 +103,12 @@
 TEST_P(BoxTest, TransferBox) {
   IpczHandle c = SpawnTestNode<TransferBoxClient>();
 
-  IpczDriverHandle blob_handle = CreateTestBlob(kMessage1, kMessage2);
+  IpczDriverHandle blob_handle = CreateTestBlob(kMessage1);
   IpczHandle box;
   EXPECT_EQ(IPCZ_RESULT_OK,
             ipcz().Box(node(), blob_handle, IPCZ_NO_FLAGS, nullptr, &box));
 
-  EXPECT_EQ(IPCZ_RESULT_OK, Put(c, kMessage3, {&box, 1}));
+  EXPECT_EQ(IPCZ_RESULT_OK, Put(c, kMessage2, {&box, 1}));
 
   Close(c);
 }
@@ -165,11 +121,11 @@
   EXPECT_EQ(IPCZ_RESULT_OK, WaitToGet(b, nullptr, {&q, 1}));
 
   for (size_t i = 0; i < TransferBoxBetweenNonBrokersNumIterations; ++i) {
-    IpczDriverHandle blob_handle = CreateTestBlob(kMessage1, kMessage2);
+    IpczDriverHandle blob_handle = CreateTestBlob(kMessage1);
     IpczHandle box;
     EXPECT_EQ(IPCZ_RESULT_OK,
               ipcz().Box(node(), blob_handle, IPCZ_NO_FLAGS, nullptr, &box));
-    EXPECT_EQ(IPCZ_RESULT_OK, Put(q, kMessage3, {&box, 1}));
+    EXPECT_EQ(IPCZ_RESULT_OK, Put(q, kMessage2, {&box, 1}));
     box = IPCZ_INVALID_DRIVER_HANDLE;
 
     std::string message;
@@ -177,7 +133,7 @@
     EXPECT_EQ(kMessage1, message);
     EXPECT_EQ(IPCZ_RESULT_OK,
               ipcz().Unbox(box, IPCZ_NO_FLAGS, nullptr, &blob_handle));
-    EXPECT_TRUE(BlobContentsMatch(blob_handle, kMessage2, kMessage3));
+    EXPECT_EQ(kMessage2, GetBlobContents(blob_handle));
   }
 
   CloseAll({q, b});
@@ -193,12 +149,12 @@
     IpczDriverHandle blob_handle;
     std::string message;
     EXPECT_EQ(IPCZ_RESULT_OK, WaitToGet(p, &message, {&box, 1}));
-    EXPECT_EQ(kMessage3, message);
+    EXPECT_EQ(kMessage2, message);
     EXPECT_EQ(IPCZ_RESULT_OK,
               ipcz().Unbox(box, IPCZ_NO_FLAGS, nullptr, &blob_handle));
-    EXPECT_TRUE(BlobContentsMatch(blob_handle, kMessage1, kMessage2));
+    EXPECT_EQ(kMessage1, GetBlobContents(blob_handle));
 
-    blob_handle = CreateTestBlob(kMessage2, kMessage3);
+    blob_handle = CreateTestBlob(kMessage2);
     EXPECT_EQ(IPCZ_RESULT_OK,
               ipcz().Box(node(), blob_handle, IPCZ_NO_FLAGS, nullptr, &box));
     EXPECT_EQ(IPCZ_RESULT_OK, Put(p, kMessage1, {&box, 1}));
diff --git a/third_party/ipcz/src/ipcz/buffer_pool_test.cc b/third_party/ipcz/src/ipcz/buffer_pool_test.cc
index ea5aadd..a82dd34d 100644
--- a/third_party/ipcz/src/ipcz/buffer_pool_test.cc
+++ b/third_party/ipcz/src/ipcz/buffer_pool_test.cc
@@ -10,7 +10,7 @@
 #include "ipcz/driver_memory.h"
 #include "ipcz/driver_memory_mapping.h"
 #include "ipcz/node.h"
-#include "reference_drivers/single_process_reference_driver.h"
+#include "reference_drivers/sync_reference_driver.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/span.h"
 #include "util/ref_counted.h"
@@ -27,7 +27,7 @@
  private:
   const Ref<Node> node_{
       MakeRefCounted<Node>(Node::Type::kBroker,
-                           reference_drivers::kSingleProcessReferenceDriver,
+                           reference_drivers::kSyncReferenceDriver,
                            IPCZ_INVALID_DRIVER_HANDLE)};
 };
 
diff --git a/third_party/ipcz/src/ipcz/node_connector_test.cc b/third_party/ipcz/src/ipcz/node_connector_test.cc
index ae9733b5..7bd3fe7 100644
--- a/third_party/ipcz/src/ipcz/node_connector_test.cc
+++ b/third_party/ipcz/src/ipcz/node_connector_test.cc
@@ -13,7 +13,7 @@
 #include "ipcz/node_messages.h"
 #include "ipcz/portal.h"
 #include "ipcz/router.h"
-#include "reference_drivers/single_process_reference_driver.h"
+#include "reference_drivers/sync_reference_driver.h"
 #include "test/test.h"
 #include "test/test_transport_listener.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -22,7 +22,7 @@
 namespace ipcz {
 namespace {
 
-const IpczDriver& kDriver = reference_drivers::kSingleProcessReferenceDriver;
+const IpczDriver& kDriver = reference_drivers::kSyncReferenceDriver;
 
 class NodeConnectorTest : public test::Test {
  protected:
diff --git a/third_party/ipcz/src/ipcz/node_link_test.cc b/third_party/ipcz/src/ipcz/node_link_test.cc
index 8e34c3e..8f26dd5 100644
--- a/third_party/ipcz/src/ipcz/node_link_test.cc
+++ b/third_party/ipcz/src/ipcz/node_link_test.cc
@@ -12,7 +12,7 @@
 #include "ipcz/remote_router_link.h"
 #include "ipcz/router.h"
 #include "ipcz/sublink_id.h"
-#include "reference_drivers/single_process_reference_driver.h"
+#include "reference_drivers/sync_reference_driver.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/base/macros.h"
 #include "util/ref_counted.h"
@@ -20,7 +20,7 @@
 namespace ipcz {
 namespace {
 
-const IpczDriver& kDriver = reference_drivers::kSingleProcessReferenceDriver;
+const IpczDriver& kDriver = reference_drivers::kSyncReferenceDriver;
 
 std::pair<Ref<NodeLink>, Ref<NodeLink>> LinkNodes(Ref<Node> broker,
                                                   Ref<Node> non_broker) {
@@ -74,6 +74,9 @@
   router0->CloseRoute();
   EXPECT_TRUE(router1->IsPeerClosed());
   router1->CloseRoute();
+
+  link0->Deactivate();
+  link1->Deactivate();
 }
 
 }  // namespace
diff --git a/third_party/ipcz/src/reference_drivers/blob.cc b/third_party/ipcz/src/reference_drivers/blob.cc
index 451ad6f..bbebebe9 100644
--- a/third_party/ipcz/src/reference_drivers/blob.cc
+++ b/third_party/ipcz/src/reference_drivers/blob.cc
@@ -14,19 +14,9 @@
 
 Blob::RefCountedFlag::~RefCountedFlag() = default;
 
-Blob::Blob(const IpczDriver& driver,
-           std::string_view message,
-           absl::Span<IpczDriverHandle> handles)
-    : driver_(driver),
-      message_(message),
-      handles_(std::move_iterator(handles.begin()),
-               std::move_iterator(handles.end())) {}
+Blob::Blob(std::string_view message) : message_(message) {}
 
-Blob::~Blob() {
-  for (IpczDriverHandle handle : handles_) {
-    driver_.Close(handle, IPCZ_NO_FLAGS, nullptr);
-  }
-}
+Blob::~Blob() = default;
 
 IpczResult Blob::Close() {
   destruction_flag_for_testing_->set(true);
diff --git a/third_party/ipcz/src/reference_drivers/blob.h b/third_party/ipcz/src/reference_drivers/blob.h
index ef9ad18..84be3788 100644
--- a/third_party/ipcz/src/reference_drivers/blob.h
+++ b/third_party/ipcz/src/reference_drivers/blob.h
@@ -5,19 +5,16 @@
 #ifndef IPCZ_SRC_REFERENCE_DRIVERS_BLOB_H_
 #define IPCZ_SRC_REFERENCE_DRIVERS_BLOB_H_
 
-#include <cstdint>
+#include <string>
 #include <string_view>
-#include <vector>
 
 #include "reference_drivers/object.h"
-#include "third_party/abseil-cpp/absl/types/span.h"
 #include "util/ref_counted.h"
 
 namespace ipcz::reference_drivers {
 
-// A driver-managed object which packages an arbitrary collection of string data
-// and transmissible driver handles. Blobs are used to exercise driver object
-// boxing in tests.
+// A driver-managed object which packages arbitrary string data. Blobs are used
+// to exercise driver object boxing in tests.
 //
 // Note that unlike the transport and memory objects defined by the reference
 // drivers, a blob is not a type of object known to ipcz. Instead it is used to
@@ -37,15 +34,12 @@
     bool flag_ = false;
   };
 
-  Blob(const IpczDriver& driver,
-       std::string_view message,
-       absl::Span<IpczDriverHandle> handles = {});
+  explicit Blob(std::string_view message);
 
   // Object:
   IpczResult Close() override;
 
   std::string& message() { return message_; }
-  std::vector<IpczDriverHandle>& handles() { return handles_; }
 
   const Ref<RefCountedFlag>& destruction_flag_for_testing() const {
     return destruction_flag_for_testing_;
@@ -58,9 +52,7 @@
   ~Blob() override;
 
  private:
-  const IpczDriver& driver_;
   std::string message_;
-  std::vector<IpczDriverHandle> handles_;
   const Ref<RefCountedFlag> destruction_flag_for_testing_{
       MakeRefCounted<RefCountedFlag>()};
 };
diff --git a/third_party/ipcz/src/reference_drivers/file_descriptor.h b/third_party/ipcz/src/reference_drivers/file_descriptor.h
index bd9385a8..6e2233e6 100644
--- a/third_party/ipcz/src/reference_drivers/file_descriptor.h
+++ b/third_party/ipcz/src/reference_drivers/file_descriptor.h
@@ -5,6 +5,8 @@
 #ifndef IPCZ_SRC_REFERENCE_DRIVERS_FILE_DESCRIPTOR_H_
 #define IPCZ_SRC_REFERENCE_DRIVERS_FILE_DESCRIPTOR_H_
 
+#include <utility>
+
 namespace ipcz::reference_drivers {
 
 // Implements unique ownership of a single POSIX file descriptor.
@@ -23,6 +25,8 @@
 
   void reset();
 
+  [[nodiscard]] int release() { return std::exchange(fd_, -1); }
+
   // Duplicates the underlying descriptor, returning a new FileDescriptor object
   // to wrap it. This object must be valid before calling Clone().
   FileDescriptor Clone() const;
diff --git a/third_party/ipcz/src/reference_drivers/handle_eintr.h b/third_party/ipcz/src/reference_drivers/handle_eintr.h
new file mode 100644
index 0000000..927e9bd7
--- /dev/null
+++ b/third_party/ipcz/src/reference_drivers/handle_eintr.h
@@ -0,0 +1,20 @@
+// 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 IPCZ_INCLUDE_SRC_REFERENCE_DRIVERS_HANDLE_EINTR_H_
+#define IPCZ_INCLUDE_SRC_REFERENCE_DRIVERS_HANDLE_EINTR_H_
+
+// Helper to ignore EINTR errors when making interruptible system calls. The
+// expression `x` is retried until it produces a non-error result or a non-EINTR
+// error.
+#define HANDLE_EINTR(x)                                     \
+  ({                                                        \
+    decltype(x) eintr_wrapper_result;                       \
+    do {                                                    \
+      eintr_wrapper_result = (x);                           \
+    } while (eintr_wrapper_result == -1 && errno == EINTR); \
+    eintr_wrapper_result;                                   \
+  })
+
+#endif  // IPCZ_INCLUDE_SRC_REFERENCE_DRIVERS_HANDLE_EINTR_H_
diff --git a/third_party/ipcz/src/reference_drivers/multiprocess_reference_driver.cc b/third_party/ipcz/src/reference_drivers/multiprocess_reference_driver.cc
new file mode 100644
index 0000000..904cefc
--- /dev/null
+++ b/third_party/ipcz/src/reference_drivers/multiprocess_reference_driver.cc
@@ -0,0 +1,434 @@
+// 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 "reference_drivers/multiprocess_reference_driver.h"
+
+#include <cstring>
+#include <limits>
+#include <memory>
+#include <tuple>
+#include <utility>
+
+#include "ipcz/ipcz.h"
+#include "reference_drivers/blob.h"
+#include "reference_drivers/file_descriptor.h"
+#include "reference_drivers/memfd_memory.h"
+#include "reference_drivers/object.h"
+#include "reference_drivers/random.h"
+#include "reference_drivers/socket_transport.h"
+#include "reference_drivers/wrapped_file_descriptor.h"
+#include "third_party/abseil-cpp/absl/synchronization/mutex.h"
+#include "util/ref_counted.h"
+#include "util/safe_math.h"
+
+namespace ipcz::reference_drivers {
+
+namespace {
+
+// A transport implementation based on a SocketTransport.
+class MultiprocessTransport
+    : public ObjectImpl<MultiprocessTransport, Object::kTransport> {
+ public:
+  explicit MultiprocessTransport(std::unique_ptr<SocketTransport> transport)
+      : transport_(std::move(transport)) {}
+  MultiprocessTransport(const MultiprocessTransport&) = delete;
+  MultiprocessTransport& operator=(const MultiprocessTransport&) = delete;
+
+  void Activate(IpczHandle transport,
+                IpczTransportActivityHandler activity_handler) {
+    was_activated_ = true;
+    ipcz_transport_ = transport;
+    activity_handler_ = activity_handler;
+
+    absl::MutexLock lock(&transport_mutex_);
+    transport_->Activate(
+        [transport = WrapRefCounted(this)](SocketTransport::Message message) {
+          return transport->OnMessage(message);
+        },
+        [transport = WrapRefCounted(this)]() { transport->OnError(); });
+  }
+
+  void Deactivate() {
+    {
+      absl::MutexLock lock(&transport_mutex_);
+      transport_->Deactivate();
+      transport_.reset();
+    }
+
+    if (activity_handler_) {
+      activity_handler_(ipcz_transport_, nullptr, 0, nullptr, 0,
+                        IPCZ_TRANSPORT_ACTIVITY_DEACTIVATED, nullptr);
+    }
+  }
+
+  IpczResult Transmit(absl::Span<const uint8_t> data,
+                      absl::Span<const IpczDriverHandle> handles) {
+    std::vector<FileDescriptor> descriptors(handles.size());
+    for (size_t i = 0; i < handles.size(); ++i) {
+      ABSL_ASSERT(Object::FromHandle(handles[i])->type() ==
+                  Object::kFileDescriptor);
+      descriptors[i] =
+          WrappedFileDescriptor::TakeFromHandle(handles[i])->TakeDescriptor();
+    }
+
+    {
+      absl::MutexLock lock(&transport_mutex_);
+      if (transport_) {
+        transport_->Send({data, absl::MakeSpan(descriptors)});
+        return IPCZ_RESULT_OK;
+      }
+    }
+
+    return IPCZ_RESULT_OK;
+  }
+
+  FileDescriptor TakeDescriptor() {
+    ABSL_ASSERT(!was_activated_);
+    absl::MutexLock lock(&transport_mutex_);
+    return transport_->TakeDescriptor();
+  }
+
+ private:
+  ~MultiprocessTransport() override = default;
+
+  bool OnMessage(const SocketTransport::Message& message) {
+    std::vector<IpczDriverHandle> handles(message.descriptors.size());
+    for (size_t i = 0; i < handles.size(); ++i) {
+      handles[i] =
+          Object::ReleaseAsHandle(MakeRefCounted<WrappedFileDescriptor>(
+              std::move(message.descriptors[i])));
+    }
+
+    ABSL_ASSERT(activity_handler_);
+    IpczResult result = activity_handler_(
+        ipcz_transport_, message.data.data(), message.data.size(),
+        handles.data(), handles.size(), IPCZ_NO_FLAGS, nullptr);
+    return result == IPCZ_RESULT_OK || result == IPCZ_RESULT_UNIMPLEMENTED;
+  }
+
+  void OnError() {
+    activity_handler_(ipcz_transport_, nullptr, 0, nullptr, 0,
+                      IPCZ_TRANSPORT_ACTIVITY_ERROR, nullptr);
+  }
+
+  IpczHandle ipcz_transport_ = IPCZ_INVALID_HANDLE;
+  IpczTransportActivityHandler activity_handler_;
+  bool was_activated_ = false;
+
+  absl::Mutex transport_mutex_;
+  std::unique_ptr<SocketTransport> transport_ ABSL_GUARDED_BY(transport_mutex_);
+};
+
+class MultiprocessMemoryMapping
+    : public ObjectImpl<MultiprocessMemoryMapping, Object::kMapping> {
+ public:
+  explicit MultiprocessMemoryMapping(MemfdMemory::Mapping mapping)
+      : mapping_(std::move(mapping)) {}
+
+  void* address() const { return mapping_.base(); }
+
+ private:
+  ~MultiprocessMemoryMapping() override = default;
+
+  const MemfdMemory::Mapping mapping_;
+};
+
+class MultiprocessMemory
+    : public ObjectImpl<MultiprocessMemory, Object::kMemory> {
+ public:
+  explicit MultiprocessMemory(size_t num_bytes) : memory_(num_bytes) {}
+  MultiprocessMemory(FileDescriptor descriptor, size_t num_bytes)
+      : memory_(std::move(descriptor), num_bytes) {}
+
+  size_t size() const { return memory_.size(); }
+
+  Ref<MultiprocessMemory> Clone() {
+    return MakeRefCounted<MultiprocessMemory>(memory_.Clone().TakeDescriptor(),
+                                              memory_.size());
+  }
+
+  Ref<MultiprocessMemoryMapping> Map() {
+    return MakeRefCounted<MultiprocessMemoryMapping>(memory_.Map());
+  }
+
+  FileDescriptor TakeDescriptor() { return memory_.TakeDescriptor(); }
+
+ private:
+  ~MultiprocessMemory() override = default;
+
+  MemfdMemory memory_;
+};
+
+// Header at the start of every driver object serialized by this driver.
+struct IPCZ_ALIGN(8) SerializedObjectHeader {
+  // Enumeration indicating which type of driver object this is.
+  Object::Type type;
+
+  // For a memory object, the size of the underlying region. Ignored otherwise.
+  uint32_t memory_size;
+};
+
+IpczResult IPCZ_API Close(IpczDriverHandle handle,
+                          uint32_t flags,
+                          const void* options) {
+  Ref<Object> object = Object::TakeFromHandle(handle);
+  if (!object) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  object->Close();
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API Serialize(IpczDriverHandle handle,
+                              IpczDriverHandle transport,
+                              uint32_t flags,
+                              const void* options,
+                              void* data,
+                              size_t* num_bytes,
+                              IpczDriverHandle* handles,
+                              size_t* num_handles) {
+  Object* object = Object::FromHandle(handle);
+  if (!object) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  // First compute the serialized dimensions.
+  size_t required_num_bytes = sizeof(SerializedObjectHeader);
+  size_t required_num_handles;
+  switch (object->type()) {
+    case Object::kTransport:
+    case Object::kMemory:
+      required_num_handles = 1;
+      break;
+
+    case Object::kBlob:
+      required_num_bytes += Blob::FromObject(object)->message().size();
+      required_num_handles = 0;
+      break;
+
+    default:
+      return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  const size_t data_capacity = num_bytes ? *num_bytes : 0;
+  const size_t handle_capacity = num_handles ? *num_handles : 0;
+  if (num_bytes) {
+    *num_bytes = required_num_bytes;
+  }
+  if (num_handles) {
+    *num_handles = required_num_handles;
+  }
+  const bool need_more_space = data_capacity < required_num_bytes ||
+                               handle_capacity < required_num_handles;
+  if (need_more_space) {
+    return IPCZ_RESULT_RESOURCE_EXHAUSTED;
+  }
+
+  auto& header = *reinterpret_cast<SerializedObjectHeader*>(data);
+  header.type = object->type();
+  header.memory_size = 0;
+
+  switch (object->type()) {
+    case Object::kTransport:
+      handles[0] = WrappedFileDescriptor::Create(
+          MultiprocessTransport::TakeFromObject(object)->TakeDescriptor());
+      break;
+
+    case Object::kMemory: {
+      auto memory = MultiprocessMemory::TakeFromObject(object);
+      header.memory_size = checked_cast<uint32_t>(memory->size());
+      handles[0] = WrappedFileDescriptor::Create(memory->TakeDescriptor());
+      break;
+    }
+
+    case Object::kBlob: {
+      auto blob = Blob::TakeFromObject(object);
+      memcpy(&header + 1, blob->message().data(), blob->message().size());
+      break;
+    }
+
+    default:
+      return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API Deserialize(const void* data,
+                                size_t num_bytes,
+                                const IpczDriverHandle* handles,
+                                size_t num_handles,
+                                IpczDriverHandle transport,
+                                uint32_t flags,
+                                const void* options,
+                                IpczDriverHandle* driver_handle) {
+  const auto& header = *static_cast<const SerializedObjectHeader*>(data);
+  if (num_bytes < sizeof(header)) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  Ref<Object> object;
+  switch (header.type) {
+    case Object::kTransport:
+      if (num_handles == 1) {
+        object = MakeRefCounted<MultiprocessTransport>(
+            std::make_unique<SocketTransport>(
+                WrappedFileDescriptor::UnwrapHandle(handles[0])));
+      }
+      break;
+
+    case Object::kMemory:
+      if (num_handles == 1) {
+        object = MakeRefCounted<MultiprocessMemory>(
+            WrappedFileDescriptor::UnwrapHandle(handles[0]),
+            header.memory_size);
+      }
+      break;
+
+    case Object::kBlob:
+      object = MakeRefCounted<Blob>(
+          std::string_view(reinterpret_cast<const char*>(&header + 1),
+                           num_bytes - sizeof(header)));
+      break;
+
+    default:
+      break;
+  }
+
+  if (!object) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  *driver_handle = Object::ReleaseAsHandle(std::move(object));
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API CreateTransports(IpczDriverHandle transport0,
+                                     IpczDriverHandle transport1,
+                                     uint32_t flags,
+                                     const void* options,
+                                     IpczDriverHandle* new_transport0,
+                                     IpczDriverHandle* new_transport1) {
+  auto [first_socket, second_socket] = SocketTransport::CreatePair();
+  auto first = MakeRefCounted<MultiprocessTransport>(std::move(first_socket));
+  auto second = MakeRefCounted<MultiprocessTransport>(std::move(second_socket));
+  *new_transport0 = Object::ReleaseAsHandle(std::move(first));
+  *new_transport1 = Object::ReleaseAsHandle(std::move(second));
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API
+ActivateTransport(IpczDriverHandle driver_transport,
+                  IpczHandle transport,
+                  IpczTransportActivityHandler activity_handler,
+                  uint32_t flags,
+                  const void* options) {
+  MultiprocessTransport::FromHandle(driver_transport)
+      ->Activate(transport, activity_handler);
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API DeactivateTransport(IpczDriverHandle driver_transport,
+                                        uint32_t flags,
+                                        const void* options) {
+  MultiprocessTransport::FromHandle(driver_transport)->Deactivate();
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API Transmit(IpczDriverHandle driver_transport,
+                             const void* data,
+                             size_t num_bytes,
+                             const IpczDriverHandle* handles,
+                             size_t num_handles,
+                             uint32_t flags,
+                             const void* options) {
+  return MultiprocessTransport::FromHandle(driver_transport)
+      ->Transmit(absl::MakeSpan(static_cast<const uint8_t*>(data), num_bytes),
+                 absl::MakeSpan(handles, num_handles));
+}
+
+IpczResult IPCZ_API AllocateSharedMemory(size_t num_bytes,
+                                         uint32_t flags,
+                                         const void* options,
+                                         IpczDriverHandle* driver_memory) {
+  auto memory =
+      MakeRefCounted<MultiprocessMemory>(static_cast<size_t>(num_bytes));
+  *driver_memory = Object::ReleaseAsHandle(std::move(memory));
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API DuplicateSharedMemory(IpczDriverHandle driver_memory,
+                                          uint32_t flags,
+                                          const void* options,
+                                          IpczDriverHandle* new_driver_memory) {
+  auto memory = MultiprocessMemory::FromHandle(driver_memory)->Clone();
+  *new_driver_memory = Object::ReleaseAsHandle(std::move(memory));
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult GetSharedMemoryInfo(IpczDriverHandle driver_memory,
+                               uint32_t flags,
+                               const void* options,
+                               IpczSharedMemoryInfo* info) {
+  Object* object = Object::FromHandle(driver_memory);
+  if (!object || object->type() != Object::kMemory || !info ||
+      info->size < sizeof(IpczSharedMemoryInfo)) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  info->region_num_bytes = static_cast<MultiprocessMemory*>(object)->size();
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API MapSharedMemory(IpczDriverHandle driver_memory,
+                                    uint32_t flags,
+                                    const void* options,
+                                    void** address,
+                                    IpczDriverHandle* driver_mapping) {
+  auto mapping = MultiprocessMemory::FromHandle(driver_memory)->Map();
+  *address = mapping->address();
+  *driver_mapping = Object::ReleaseAsHandle(std::move(mapping));
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API GenerateRandomBytes(size_t num_bytes,
+                                        uint32_t flags,
+                                        const void* options,
+                                        void* buffer) {
+  RandomBytes(absl::MakeSpan(static_cast<uint8_t*>(buffer), num_bytes));
+  return IPCZ_RESULT_OK;
+}
+
+}  // namespace
+
+const IpczDriver kMultiprocessReferenceDriver = {
+    sizeof(kMultiprocessReferenceDriver),
+    Close,
+    Serialize,
+    Deserialize,
+    CreateTransports,
+    ActivateTransport,
+    DeactivateTransport,
+    Transmit,
+    AllocateSharedMemory,
+    GetSharedMemoryInfo,
+    DuplicateSharedMemory,
+    MapSharedMemory,
+    GenerateRandomBytes,
+};
+
+IpczDriverHandle CreateMultiprocessTransport(
+    std::unique_ptr<SocketTransport> transport) {
+  return Object::ReleaseAsHandle(
+      MakeRefCounted<MultiprocessTransport>(std::move(transport)));
+}
+
+FileDescriptor TakeMultiprocessTransportDescriptor(IpczDriverHandle transport) {
+  Ref<MultiprocessTransport> released_transport =
+      MultiprocessTransport::TakeFromHandle(transport);
+  return released_transport->TakeDescriptor();
+}
+
+}  // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/multiprocess_reference_driver.h b/third_party/ipcz/src/reference_drivers/multiprocess_reference_driver.h
new file mode 100644
index 0000000..a0eec29
--- /dev/null
+++ b/third_party/ipcz/src/reference_drivers/multiprocess_reference_driver.h
@@ -0,0 +1,34 @@
+// 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 IPCZ_SRC_REFERENCE_DRIVERS_MULTIPROCESS_REFERENCE_DRIVER_H_
+#define IPCZ_SRC_REFERENCE_DRIVERS_MULTIPROCESS_REFERENCE_DRIVER_H_
+
+#include <cstdint>
+#include <memory>
+
+#include "ipcz/ipcz.h"
+#include "reference_drivers/file_descriptor.h"
+#include "reference_drivers/socket_transport.h"
+
+namespace ipcz::reference_drivers {
+
+// A basic reference driver which supports multiprocess operation. This is also
+// suitable for single-process usage, but unlike kSingleProcessReferenceDriver
+// all transmissions through this driver are asynchronous.
+extern const IpczDriver kMultiprocessReferenceDriver;
+
+// Creates a new multiprocess-capable driver transport from a SocketTransport
+// endpoint and returns an IpczDriverHandle to reference it.
+IpczDriverHandle CreateMultiprocessTransport(
+    std::unique_ptr<SocketTransport> transport);
+
+// Extracts the underlying file descriptor from a socket-based multiprocess
+// driver transport. `transport` is effectively consumed and invalidated by this
+// call.
+FileDescriptor TakeMultiprocessTransportDescriptor(IpczDriverHandle transport);
+
+}  // namespace ipcz::reference_drivers
+
+#endif  // IPCZ_SRC_REFERENCE_DRIVERS_MULTIPROCESS_REFERENCE_DRIVER_H_
diff --git a/third_party/ipcz/src/reference_drivers/multiprocess_reference_driver_test.cc b/third_party/ipcz/src/reference_drivers/multiprocess_reference_driver_test.cc
new file mode 100644
index 0000000..aa966bae
--- /dev/null
+++ b/third_party/ipcz/src/reference_drivers/multiprocess_reference_driver_test.cc
@@ -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.
+
+#include "reference_drivers/multiprocess_reference_driver.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include "ipcz/ipcz.h"
+#include "reference_drivers/file_descriptor.h"
+#include "reference_drivers/wrapped_file_descriptor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ipcz::reference_drivers {
+namespace {
+
+TEST(MultiprocessReferenceDriverTest, SendDeactivated) {
+  const IpczDriver& driver = kMultiprocessReferenceDriver;
+  IpczDriverHandle a, b;
+  EXPECT_EQ(IPCZ_RESULT_OK,
+            driver.CreateTransports(IPCZ_INVALID_DRIVER_HANDLE,
+                                    IPCZ_INVALID_DRIVER_HANDLE, IPCZ_NO_FLAGS,
+                                    nullptr, &a, &b));
+
+  // Activate and immediately deactivate the transport.
+  auto handler = +[](IpczHandle, const void*, size_t, const IpczDriverHandle*,
+                     size_t, uint32_t, const void*) { return IPCZ_RESULT_OK; };
+  EXPECT_EQ(IPCZ_RESULT_OK,
+            driver.ActivateTransport(a, IPCZ_INVALID_HANDLE, handler,
+                                     IPCZ_NO_FLAGS, nullptr));
+  EXPECT_EQ(IPCZ_RESULT_OK,
+            driver.DeactivateTransport(a, IPCZ_NO_FLAGS, nullptr));
+
+  int fds[2];
+  EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, fds));
+
+  // This driver discards outgoing transmissions once the transport has been
+  // deactivated. The attached file descriptor should not leak as a result of
+  // this Transmit(), and if it does, the test will hang below.
+  IpczDriverHandle handle =
+      WrappedFileDescriptor::Create(FileDescriptor(fds[0]));
+  EXPECT_EQ(IPCZ_RESULT_OK,
+            driver.Transmit(a, nullptr, 0, &handle, 1, IPCZ_NO_FLAGS, nullptr));
+
+  // Wait for the other side to be closed by the driver. Since this is a
+  // blocking socket, a successful zero-length read() indicates EOF.
+  FileDescriptor fd(fds[1]);
+  uint8_t byte;
+  EXPECT_EQ(0, read(fd.get(), &byte, 1));
+
+  EXPECT_EQ(IPCZ_RESULT_OK, driver.Close(a, IPCZ_NO_FLAGS, nullptr));
+  EXPECT_EQ(IPCZ_RESULT_OK, driver.Close(b, IPCZ_NO_FLAGS, nullptr));
+}
+
+}  // namespace
+}  // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/object.h b/third_party/ipcz/src/reference_drivers/object.h
index 101e714..56e88cd 100644
--- a/third_party/ipcz/src/reference_drivers/object.h
+++ b/third_party/ipcz/src/reference_drivers/object.h
@@ -7,6 +7,7 @@
 
 #include <cstdint>
 
+#include "build/build_config.h"
 #include "ipcz/ipcz.h"
 #include "util/ref_counted.h"
 
@@ -24,6 +25,11 @@
     // driver object de/serialization via boxing and unboxing in tests. See the
     // Blob definition in src/reference_drivers/blob.h.
     kBlob,
+
+#if defined(OS_LINUX)
+    // A non-standard driver object type which wraps a FileDescriptor object.
+    kFileDescriptor,
+#endif
   };
 
   explicit Object(Type type);
@@ -60,14 +66,25 @@
  public:
   ObjectImpl() : Object(kType) {}
 
-  static T* FromHandle(IpczDriverHandle handle) {
-    Object* object = Object::FromHandle(handle);
+  static T* FromObject(Object* object) {
     if (!object || object->type() != kType) {
       return nullptr;
     }
     return static_cast<T*>(object);
   }
 
+  static T* FromHandle(IpczDriverHandle handle) {
+    return FromObject(Object::FromHandle(handle));
+  }
+
+  static Ref<T> TakeFromObject(Object* object) {
+    return AdoptRef(FromObject(object));
+  }
+
+  static Ref<T> TakeFromHandle(IpczDriverHandle handle) {
+    return AdoptRef(FromHandle(handle));
+  }
+
  protected:
   ~ObjectImpl() override = default;
 };
diff --git a/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.cc b/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.cc
new file mode 100644
index 0000000..f9b5cb1
--- /dev/null
+++ b/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.cc
@@ -0,0 +1,187 @@
+// 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 "reference_drivers/single_process_reference_driver_base.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <utility>
+
+#include "ipcz/ipcz.h"
+#include "reference_drivers/object.h"
+#include "reference_drivers/random.h"
+#include "third_party/abseil-cpp/absl/base/macros.h"
+#include "util/ref_counted.h"
+
+namespace ipcz::reference_drivers {
+
+namespace {
+
+// Shared memory objects in single-process drivers are plain heap allocations.
+class InProcessMemory : public ObjectImpl<InProcessMemory, Object::kMemory> {
+ public:
+  explicit InProcessMemory(size_t size)
+      : size_(size), data_(new uint8_t[size]) {
+    memset(&data_[0], 0, size_);
+  }
+
+  size_t size() const { return size_; }
+  void* address() const { return &data_[0]; }
+
+ private:
+  ~InProcessMemory() override = default;
+
+  const size_t size_;
+  const std::unique_ptr<uint8_t[]> data_;
+};
+
+// As there's nothing to "map" from a heap allocation, single-process driver
+// memory mappings simply hold an active reference to the underlying
+// heap allocation.
+class InProcessMapping : public ObjectImpl<InProcessMapping, Object::kMapping> {
+ public:
+  explicit InProcessMapping(Ref<InProcessMemory> memory)
+      : memory_(std::move(memory)) {}
+
+  size_t size() const { return memory_->size(); }
+  void* address() const { return memory_->address(); }
+
+ private:
+  ~InProcessMapping() override = default;
+
+  const Ref<InProcessMemory> memory_;
+};
+
+IpczResult IPCZ_API Close(IpczDriverHandle handle,
+                          uint32_t flags,
+                          const void* options) {
+  Ref<Object> object = Object::TakeFromHandle(handle);
+  if (!object) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  return object->Close();
+}
+
+IpczResult IPCZ_API Serialize(IpczDriverHandle handle,
+                              IpczDriverHandle transport,
+                              uint32_t flags,
+                              const void* options,
+                              void* data,
+                              size_t* num_bytes,
+                              IpczDriverHandle* handles,
+                              size_t* num_handles) {
+  Object* object = Object::FromHandle(handle);
+  if (!object) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  if (num_bytes) {
+    *num_bytes = 0;
+  }
+
+  // Since this is all in-process, all driver handles can be transmitted as-is.
+  const size_t handle_capacity = num_handles ? *num_handles : 0;
+  if (num_handles) {
+    *num_handles = 1;
+  }
+  if (handle_capacity < 1) {
+    return IPCZ_RESULT_RESOURCE_EXHAUSTED;
+  }
+
+  handles[0] = handle;
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API Deserialize(const void* data,
+                                size_t num_bytes,
+                                const IpczDriverHandle* handles,
+                                size_t num_handles,
+                                IpczDriverHandle transport,
+                                uint32_t flags,
+                                const void* options,
+                                IpczDriverHandle* driver_handle) {
+  ABSL_ASSERT(num_bytes == 0);
+  ABSL_ASSERT(num_handles == 1);
+  *driver_handle = handles[0];
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API AllocateSharedMemory(size_t num_bytes,
+                                         uint32_t flags,
+                                         const void* options,
+                                         IpczDriverHandle* driver_memory) {
+  if (num_bytes > std::numeric_limits<size_t>::max()) {
+    return IPCZ_RESULT_RESOURCE_EXHAUSTED;
+  }
+
+  auto memory = MakeRefCounted<InProcessMemory>(static_cast<size_t>(num_bytes));
+  *driver_memory = Object::ReleaseAsHandle(std::move(memory));
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult GetSharedMemoryInfo(IpczDriverHandle driver_memory,
+                               uint32_t flags,
+                               const void* options,
+                               IpczSharedMemoryInfo* info) {
+  Object* object = Object::FromHandle(driver_memory);
+  if (!object || object->type() != Object::kMemory || !info ||
+      info->size < sizeof(IpczSharedMemoryInfo)) {
+    return IPCZ_RESULT_INVALID_ARGUMENT;
+  }
+
+  info->region_num_bytes = static_cast<InProcessMemory*>(object)->size();
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API DuplicateSharedMemory(IpczDriverHandle driver_memory,
+                                          uint32_t flags,
+                                          const void* options,
+                                          IpczDriverHandle* new_driver_memory) {
+  Ref<InProcessMemory> memory(InProcessMemory::FromHandle(driver_memory));
+  *new_driver_memory = Object::ReleaseAsHandle(std::move(memory));
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API MapSharedMemory(IpczDriverHandle driver_memory,
+                                    uint32_t flags,
+                                    const void* options,
+                                    void** address,
+                                    IpczDriverHandle* driver_mapping) {
+  Ref<InProcessMemory> memory(InProcessMemory::FromHandle(driver_memory));
+  auto mapping = MakeRefCounted<InProcessMapping>(std::move(memory));
+  *address = mapping->address();
+  *driver_mapping = Object::ReleaseAsHandle(std::move(mapping));
+  return IPCZ_RESULT_OK;
+}
+
+IpczResult IPCZ_API GenerateRandomBytes(size_t num_bytes,
+                                        uint32_t flags,
+                                        const void* options,
+                                        void* buffer) {
+  RandomBytes(absl::MakeSpan(static_cast<uint8_t*>(buffer), num_bytes));
+  return IPCZ_RESULT_OK;
+}
+
+}  // namespace
+
+const IpczDriver kSingleProcessReferenceDriverBase = {
+    sizeof(kSingleProcessReferenceDriverBase),
+    Close,
+    Serialize,
+    Deserialize,
+    nullptr,
+    nullptr,
+    nullptr,
+    nullptr,
+    AllocateSharedMemory,
+    GetSharedMemoryInfo,
+    DuplicateSharedMemory,
+    MapSharedMemory,
+    GenerateRandomBytes,
+};
+
+}  // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.h b/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.h
new file mode 100644
index 0000000..e0e89b5
--- /dev/null
+++ b/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.h
@@ -0,0 +1,18 @@
+// 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 IPCZ_SRC_REFERENCE_DRIVERS_SINGLE_PROCESS_REFERENCE_DRIVER_BASE_H_
+#define IPCZ_SRC_REFERENCE_DRIVERS_SINGLE_PROCESS_REFERENCE_DRIVER_BASE_H_
+
+#include "ipcz/ipcz.h"
+
+namespace ipcz::reference_drivers {
+
+// A partial IpczDriver providing implementation common to both the sync and
+// and async single-process drivers.
+extern const IpczDriver kSingleProcessReferenceDriverBase;
+
+}  // namespace ipcz::reference_drivers
+
+#endif  // IPCZ_SRC_REFERENCE_DRIVERS_SINGLE_PROCESS_REFERENCE_DRIVER_BASE_H_
diff --git a/third_party/ipcz/src/reference_drivers/socket_transport.cc b/third_party/ipcz/src/reference_drivers/socket_transport.cc
index b14175a..74b1912 100644
--- a/third_party/ipcz/src/reference_drivers/socket_transport.cc
+++ b/third_party/ipcz/src/reference_drivers/socket_transport.cc
@@ -19,21 +19,13 @@
 #include <vector>
 
 #include "reference_drivers/file_descriptor.h"
+#include "reference_drivers/handle_eintr.h"
 #include "third_party/abseil-cpp/absl/synchronization/mutex.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/span.h"
 #include "util/log.h"
 #include "util/safe_math.h"
 
-#define HANDLE_EINTR(x)                                     \
-  ({                                                        \
-    decltype(x) eintr_wrapper_result;                       \
-    do {                                                    \
-      eintr_wrapper_result = (x);                           \
-    } while (eintr_wrapper_result == -1 && errno == EINTR); \
-    eintr_wrapper_result;                                   \
-  })
-
 namespace ipcz::reference_drivers {
 
 namespace {
diff --git a/third_party/ipcz/src/reference_drivers/single_process_reference_driver.cc b/third_party/ipcz/src/reference_drivers/sync_reference_driver.cc
similarity index 65%
rename from third_party/ipcz/src/reference_drivers/single_process_reference_driver.cc
rename to third_party/ipcz/src/reference_drivers/sync_reference_driver.cc
index 888d4f5a..af9c0bc 100644
--- a/third_party/ipcz/src/reference_drivers/single_process_reference_driver.cc
+++ b/third_party/ipcz/src/reference_drivers/sync_reference_driver.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 "reference_drivers/single_process_reference_driver.h"
+#include "reference_drivers/sync_reference_driver.h"
 
 #include <algorithm>
 #include <cstdint>
@@ -12,12 +12,10 @@
 #include <tuple>
 #include <vector>
 
-#include "ipcz/driver_object.h"
-#include "ipcz/driver_transport.h"
 #include "ipcz/ipcz.h"
-#include "ipcz/message.h"
 #include "reference_drivers/object.h"
 #include "reference_drivers/random.h"
+#include "reference_drivers/single_process_reference_driver_base.h"
 #include "third_party/abseil-cpp/absl/synchronization/mutex.h"
 #include "third_party/abseil-cpp/absl/types/span.h"
 #include "util/ref_counted.h"
@@ -161,28 +159,12 @@
     }
 
     if (peer) {
-      // Kind of a hack so we can deserialize messages as if they were read
-      // and deserialized by the peer. We want to do this because the serialized
-      // messages may encode driver objects with live resources that would
-      // otherwise leak. This is particularly problematic in test environments
-      // where we want to exercise various edge cases that can result in
-      // dropped connections and dropped messages, within a single test process
-      // that may run multiple such tests in succession.
-      //
-      // We construct a temporary DriverObject which wraps `this`, as needed
-      // for Message deserialization. This must be released when done, as it
-      // does not actually own a handle to the peer.
-      auto peer_transport = MakeRefCounted<DriverTransport>(
-          DriverObject(kSingleProcessReferenceDriver, peer->handle()));
       for (SavedMessage& m : saved_messages) {
-        ipcz::Message message;
-        message.DeserializeUnknownType(
-            ipcz::DriverTransport::RawMessage{m.data, m.handles},
-            *peer_transport);
+        for (IpczDriverHandle handle : m.handles) {
+          Object::TakeFromHandle(handle)->Close();
+        }
       }
 
-      std::ignore = peer_transport->Release();
-
       // NOTE: Although nothing should ever call back into `this` after Close(),
       // for consistency with other methods we still take precaution not to call
       // into the peer while holding `mutex_`.
@@ -337,94 +319,6 @@
   std::vector<SavedMessage> saved_messages_ ABSL_GUARDED_BY(mutex_);
 };
 
-// Shared memory regions for the single-process driver are just regular private
-// heap allocations.
-class InProcessMemory : public ObjectImpl<InProcessMemory, Object::kMemory> {
- public:
-  explicit InProcessMemory(size_t size)
-      : size_(size), data_(new uint8_t[size]) {
-    memset(&data_[0], 0, size_);
-  }
-
-  size_t size() const { return size_; }
-  void* address() const { return &data_[0]; }
-
- private:
-  ~InProcessMemory() override = default;
-
-  const size_t size_;
-  const std::unique_ptr<uint8_t[]> data_;
-};
-
-class InProcessMapping : public ObjectImpl<InProcessMapping, Object::kMapping> {
- public:
-  explicit InProcessMapping(Ref<InProcessMemory> memory)
-      : memory_(std::move(memory)) {}
-
-  size_t size() const { return memory_->size(); }
-  void* address() const { return memory_->address(); }
-
- private:
-  ~InProcessMapping() override = default;
-
-  const Ref<InProcessMemory> memory_;
-};
-
-IpczResult IPCZ_API Close(IpczDriverHandle handle,
-                          uint32_t flags,
-                          const void* options) {
-  Ref<Object> object = Object::TakeFromHandle(handle);
-  if (!object) {
-    return IPCZ_RESULT_INVALID_ARGUMENT;
-  }
-
-  return object->Close();
-}
-
-IpczResult IPCZ_API Serialize(IpczDriverHandle handle,
-                              IpczDriverHandle transport,
-                              uint32_t flags,
-                              const void* options,
-                              void* data,
-                              size_t* num_bytes,
-                              IpczDriverHandle* handles,
-                              size_t* num_handles) {
-  Object* object = Object::FromHandle(handle);
-  if (!object) {
-    return IPCZ_RESULT_INVALID_ARGUMENT;
-  }
-
-  if (num_bytes) {
-    *num_bytes = 0;
-  }
-
-  // Since this is all in-process, all driver handles can be transmitted as-is.
-  const size_t handle_capacity = num_handles ? *num_handles : 0;
-  if (num_handles) {
-    *num_handles = 1;
-  }
-  if (handle_capacity < 1) {
-    return IPCZ_RESULT_RESOURCE_EXHAUSTED;
-  }
-
-  handles[0] = handle;
-  return IPCZ_RESULT_OK;
-}
-
-IpczResult IPCZ_API Deserialize(const void* data,
-                                size_t num_bytes,
-                                const IpczDriverHandle* handles,
-                                size_t num_handles,
-                                IpczDriverHandle transport,
-                                uint32_t flags,
-                                const void* options,
-                                IpczDriverHandle* driver_handle) {
-  ABSL_ASSERT(num_bytes == 0);
-  ABSL_ASSERT(num_handles == 1);
-  *driver_handle = handles[0];
-  return IPCZ_RESULT_OK;
-}
-
 IpczResult IPCZ_API CreateTransports(IpczDriverHandle transport0,
                                      IpczDriverHandle transport1,
                                      uint32_t flags,
@@ -468,78 +362,22 @@
                  absl::MakeSpan(handles, num_handles));
 }
 
-IpczResult IPCZ_API AllocateSharedMemory(size_t num_bytes,
-                                         uint32_t flags,
-                                         const void* options,
-                                         IpczDriverHandle* driver_memory) {
-  if (num_bytes > std::numeric_limits<size_t>::max()) {
-    return IPCZ_RESULT_RESOURCE_EXHAUSTED;
-  }
-
-  auto memory = MakeRefCounted<InProcessMemory>(static_cast<size_t>(num_bytes));
-  *driver_memory = Object::ReleaseAsHandle(std::move(memory));
-  return IPCZ_RESULT_OK;
-}
-
-IpczResult GetSharedMemoryInfo(IpczDriverHandle driver_memory,
-                               uint32_t flags,
-                               const void* options,
-                               IpczSharedMemoryInfo* info) {
-  Object* object = Object::FromHandle(driver_memory);
-  if (!object || object->type() != Object::kMemory || !info ||
-      info->size < sizeof(IpczSharedMemoryInfo)) {
-    return IPCZ_RESULT_INVALID_ARGUMENT;
-  }
-
-  info->region_num_bytes = static_cast<InProcessMemory*>(object)->size();
-  return IPCZ_RESULT_OK;
-}
-
-IpczResult IPCZ_API DuplicateSharedMemory(IpczDriverHandle driver_memory,
-                                          uint32_t flags,
-                                          const void* options,
-                                          IpczDriverHandle* new_driver_memory) {
-  Ref<InProcessMemory> memory(InProcessMemory::FromHandle(driver_memory));
-  *new_driver_memory = Object::ReleaseAsHandle(std::move(memory));
-  return IPCZ_RESULT_OK;
-}
-
-IpczResult IPCZ_API MapSharedMemory(IpczDriverHandle driver_memory,
-                                    uint32_t flags,
-                                    const void* options,
-                                    void** address,
-                                    IpczDriverHandle* driver_mapping) {
-  Ref<InProcessMemory> memory(InProcessMemory::FromHandle(driver_memory));
-  auto mapping = MakeRefCounted<InProcessMapping>(std::move(memory));
-  *address = mapping->address();
-  *driver_mapping = Object::ReleaseAsHandle(std::move(mapping));
-  return IPCZ_RESULT_OK;
-}
-
-IpczResult IPCZ_API GenerateRandomBytes(size_t num_bytes,
-                                        uint32_t flags,
-                                        const void* options,
-                                        void* buffer) {
-  RandomBytes(absl::MakeSpan(static_cast<uint8_t*>(buffer), num_bytes));
-  return IPCZ_RESULT_OK;
-}
-
 }  // namespace
 
-const IpczDriver kSingleProcessReferenceDriver = {
-    sizeof(kSingleProcessReferenceDriver),
-    Close,
-    Serialize,
-    Deserialize,
+const IpczDriver kSyncReferenceDriver = {
+    sizeof(kSyncReferenceDriver),
+    kSingleProcessReferenceDriverBase.Close,
+    kSingleProcessReferenceDriverBase.Serialize,
+    kSingleProcessReferenceDriverBase.Deserialize,
     CreateTransports,
     ActivateTransport,
     DeactivateTransport,
     Transmit,
-    AllocateSharedMemory,
-    GetSharedMemoryInfo,
-    DuplicateSharedMemory,
-    MapSharedMemory,
-    GenerateRandomBytes,
+    kSingleProcessReferenceDriverBase.AllocateSharedMemory,
+    kSingleProcessReferenceDriverBase.GetSharedMemoryInfo,
+    kSingleProcessReferenceDriverBase.DuplicateSharedMemory,
+    kSingleProcessReferenceDriverBase.MapSharedMemory,
+    kSingleProcessReferenceDriverBase.GenerateRandomBytes,
 };
 
 }  // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/single_process_reference_driver.h b/third_party/ipcz/src/reference_drivers/sync_reference_driver.h
similarity index 69%
rename from third_party/ipcz/src/reference_drivers/single_process_reference_driver.h
rename to third_party/ipcz/src/reference_drivers/sync_reference_driver.h
index fbd139e..4dd4c26 100644
--- a/third_party/ipcz/src/reference_drivers/single_process_reference_driver.h
+++ b/third_party/ipcz/src/reference_drivers/sync_reference_driver.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IPCZ_SRC_DRIVERS_SINGLE_PROCESS_REFERENCE_DRIVER_H_
-#define IPCZ_SRC_DRIVERS_SINGLE_PROCESS_REFERENCE_DRIVER_H_
+#ifndef IPCZ_SRC_REFERENCE_DRIVERS_SYNC_REFERENCE_DRIVER_H_
+#define IPCZ_SRC_REFERENCE_DRIVERS_SYNC_REFERENCE_DRIVER_H_
 
 #include "ipcz/ipcz.h"
 
@@ -13,8 +13,8 @@
 // on one transport directly calls into the activity handler of its peer, so all
 // node operations and therefore all ipcz operations complete synchronously from
 // end to end.
-extern const IpczDriver kSingleProcessReferenceDriver;
+extern const IpczDriver kSyncReferenceDriver;
 
 }  // namespace ipcz::reference_drivers
 
-#endif  // IPCZ_SRC_DRIVERS_SINGLE_PROCESS_REFERENCE_DRIVER_H_
+#endif  // IPCZ_SRC_REFERENCE_DRIVERS_SYNC_REFERENCE_DRIVER_H_
diff --git a/third_party/ipcz/src/reference_drivers/single_process_reference_driver_test.cc b/third_party/ipcz/src/reference_drivers/sync_reference_driver_test.cc
similarity index 92%
rename from third_party/ipcz/src/reference_drivers/single_process_reference_driver_test.cc
rename to third_party/ipcz/src/reference_drivers/sync_reference_driver_test.cc
index 3381ee3d..2ec1f9a 100644
--- a/third_party/ipcz/src/reference_drivers/single_process_reference_driver_test.cc
+++ b/third_party/ipcz/src/reference_drivers/sync_reference_driver_test.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 "reference_drivers/single_process_reference_driver.h"
+#include "reference_drivers/sync_reference_driver.h"
 
 #include <cstddef>
 #include <functional>
@@ -77,8 +77,8 @@
   const TransportHandlers handlers_;
 };
 
-TEST(SingleProcessReferenceDriverTest, CreateTransports) {
-  const IpczDriver& driver = kSingleProcessReferenceDriver;
+TEST(SyncReferenceDriverTest, CreateTransports) {
+  const IpczDriver& driver = kSyncReferenceDriver;
   IpczDriverHandle a, b;
   EXPECT_EQ(IPCZ_RESULT_OK,
             driver.CreateTransports(IPCZ_INVALID_DRIVER_HANDLE,
@@ -88,8 +88,8 @@
   EXPECT_EQ(IPCZ_RESULT_OK, driver.Close(b, IPCZ_NO_FLAGS, nullptr));
 }
 
-TEST(SingleProcessReferenceDriverTest, TransmitBeforeActive) {
-  const IpczDriver& driver = kSingleProcessReferenceDriver;
+TEST(SyncReferenceDriverTest, TransmitBeforeActive) {
+  const IpczDriver& driver = kSyncReferenceDriver;
   IpczDriverHandle a, b;
   EXPECT_EQ(IPCZ_RESULT_OK,
             driver.CreateTransports(IPCZ_INVALID_DRIVER_HANDLE,
@@ -122,8 +122,8 @@
   EXPECT_EQ(IPCZ_RESULT_OK, driver.Close(b, IPCZ_NO_FLAGS, nullptr));
 }
 
-TEST(SingleProcessReferenceDriverTest, TransmitWhileActive) {
-  const IpczDriver& driver = kSingleProcessReferenceDriver;
+TEST(SyncReferenceDriverTest, TransmitWhileActive) {
+  const IpczDriver& driver = kSyncReferenceDriver;
   IpczDriverHandle a, b;
   EXPECT_EQ(IPCZ_RESULT_OK,
             driver.CreateTransports(IPCZ_INVALID_DRIVER_HANDLE,
@@ -155,8 +155,8 @@
   EXPECT_EQ(IPCZ_RESULT_OK, driver.Close(b, IPCZ_NO_FLAGS, nullptr));
 }
 
-TEST(SingleProcessReferenceDriverTest, Deactivate) {
-  const IpczDriver& driver = kSingleProcessReferenceDriver;
+TEST(SyncReferenceDriverTest, Deactivate) {
+  const IpczDriver& driver = kSyncReferenceDriver;
   IpczDriverHandle a, b;
   EXPECT_EQ(IPCZ_RESULT_OK,
             driver.CreateTransports(IPCZ_INVALID_DRIVER_HANDLE,
@@ -179,8 +179,8 @@
   EXPECT_EQ(IPCZ_RESULT_OK, driver.Close(b, IPCZ_NO_FLAGS, nullptr));
 }
 
-TEST(SingleProcessReferenceDriverTest, TransmitAfterDeactivated) {
-  const IpczDriver& driver = kSingleProcessReferenceDriver;
+TEST(SyncReferenceDriverTest, TransmitAfterDeactivated) {
+  const IpczDriver& driver = kSyncReferenceDriver;
   IpczDriverHandle a, b;
   EXPECT_EQ(IPCZ_RESULT_OK,
             driver.CreateTransports(IPCZ_INVALID_DRIVER_HANDLE,
@@ -217,8 +217,8 @@
   EXPECT_EQ(IPCZ_RESULT_OK, driver.Close(b, IPCZ_NO_FLAGS, nullptr));
 }
 
-TEST(SingleProcessReferenceDriverTest, NotifyError) {
-  const IpczDriver& driver = kSingleProcessReferenceDriver;
+TEST(SyncReferenceDriverTest, NotifyError) {
+  const IpczDriver& driver = kSyncReferenceDriver;
   IpczDriverHandle a, b;
   EXPECT_EQ(IPCZ_RESULT_OK,
             driver.CreateTransports(IPCZ_INVALID_DRIVER_HANDLE,
@@ -255,8 +255,8 @@
   EXPECT_EQ(IPCZ_RESULT_OK, driver.Close(b, IPCZ_NO_FLAGS, nullptr));
 }
 
-TEST(SingleProcessReferenceDriverTest, SharedMemory) {
-  const IpczDriver& driver = kSingleProcessReferenceDriver;
+TEST(SyncReferenceDriverTest, SharedMemory) {
+  const IpczDriver& driver = kSyncReferenceDriver;
 
   const size_t kSize = 64;
   IpczDriverHandle memory;
@@ -297,8 +297,8 @@
   EXPECT_EQ(IPCZ_RESULT_OK, driver.Close(memory, IPCZ_NO_FLAGS, nullptr));
 }
 
-TEST(SingleProcessReferenceDriverTest, TransmitHandles) {
-  const IpczDriver& driver = kSingleProcessReferenceDriver;
+TEST(SyncReferenceDriverTest, TransmitHandles) {
+  const IpczDriver& driver = kSyncReferenceDriver;
   IpczDriverHandle a, b;
   EXPECT_EQ(IPCZ_RESULT_OK,
             driver.CreateTransports(IPCZ_INVALID_DRIVER_HANDLE,
diff --git a/third_party/ipcz/src/reference_drivers/wrapped_file_descriptor.cc b/third_party/ipcz/src/reference_drivers/wrapped_file_descriptor.cc
new file mode 100644
index 0000000..675b874
--- /dev/null
+++ b/third_party/ipcz/src/reference_drivers/wrapped_file_descriptor.cc
@@ -0,0 +1,17 @@
+// 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 "reference_drivers/wrapped_file_descriptor.h"
+
+#include "third_party/abseil-cpp/absl/base/macros.h"
+#include "util/ref_counted.h"
+
+namespace ipcz::reference_drivers {
+
+WrappedFileDescriptor::WrappedFileDescriptor(FileDescriptor fd)
+    : fd_(std::move(fd)) {}
+
+WrappedFileDescriptor::~WrappedFileDescriptor() = default;
+
+}  // namespace ipcz::reference_drivers
diff --git a/third_party/ipcz/src/reference_drivers/wrapped_file_descriptor.h b/third_party/ipcz/src/reference_drivers/wrapped_file_descriptor.h
new file mode 100644
index 0000000..e91154b
--- /dev/null
+++ b/third_party/ipcz/src/reference_drivers/wrapped_file_descriptor.h
@@ -0,0 +1,41 @@
+// 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 IPCZ_SRC_REFERENCE_DRIVERS_WRAPPED_FILE_DESCRIPTOR_H_
+#define IPCZ_SRC_REFERENCE_DRIVERS_WRAPPED_FILE_DESCRIPTOR_H_
+
+#include "reference_drivers/file_descriptor.h"
+#include "reference_drivers/object.h"
+
+namespace ipcz::reference_drivers {
+
+// Wraps a FileDescriptor as a driver object. The Linux multiprocess reference
+// driver uses this to facilitate serialization of more complex objects into
+// these readily transmissible objects.
+class WrappedFileDescriptor
+    : public ObjectImpl<WrappedFileDescriptor, Object::kFileDescriptor> {
+ public:
+  explicit WrappedFileDescriptor(FileDescriptor fd);
+
+  const FileDescriptor& handle() const { return fd_; }
+  FileDescriptor TakeDescriptor() { return std::move(fd_); }
+
+  static IpczDriverHandle Create(FileDescriptor fd) {
+    return ReleaseAsHandle(
+        MakeRefCounted<WrappedFileDescriptor>(std::move(fd)));
+  }
+
+  static FileDescriptor UnwrapHandle(IpczDriverHandle handle) {
+    return TakeFromHandle(handle)->TakeDescriptor();
+  }
+
+ private:
+  ~WrappedFileDescriptor() override;
+
+  FileDescriptor fd_;
+};
+
+}  // namespace ipcz::reference_drivers
+
+#endif  // IPCZ_SRC_REFERENCE_DRIVERS_WRAPPED_FILE_DESCRIPTOR_H_
diff --git a/third_party/ipcz/src/test/multinode_test.cc b/third_party/ipcz/src/test/multinode_test.cc
index 88eaf71..91a1059a 100644
--- a/third_party/ipcz/src/test/multinode_test.cc
+++ b/third_party/ipcz/src/test/multinode_test.cc
@@ -4,15 +4,25 @@
 
 #include "test/multinode_test.h"
 
+#include <map>
+#include <string>
 #include <thread>
 
 #include "ipcz/ipcz.h"
-#include "reference_drivers/single_process_reference_driver.h"
+#include "reference_drivers/sync_reference_driver.h"
 #include "third_party/abseil-cpp/absl/base/macros.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
+#include "third_party/ipcz/src/test_buildflags.h"
 #include "util/log.h"
 
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+#include "reference_drivers/file_descriptor.h"
+#include "reference_drivers/multiprocess_reference_driver.h"
+#include "reference_drivers/socket_transport.h"
+#include "test/test_child_launcher.h"
+#endif
+
 namespace ipcz::test {
 
 namespace {
@@ -59,6 +69,30 @@
   absl::optional<std::thread> client_thread_;
 };
 
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+// Controls a node running within an isolated child process.
+class ChildProcessTestNodeController : public TestNode::TestNodeController {
+ public:
+  explicit ChildProcessTestNodeController(pid_t pid) : pid_(pid) {}
+  ~ChildProcessTestNodeController() override {
+    ABSL_ASSERT(result_.has_value());
+  }
+
+  // TestNode::TestNodeController:
+  bool WaitForShutdown() override {
+    if (result_.has_value()) {
+      return *result_;
+    }
+
+    result_ = TestChildLauncher::WaitForSuccessfulProcessTermination(pid_);
+    return *result_;
+  }
+
+  const pid_t pid_;
+  absl::optional<bool> result_;
+};
+#endif
+
 }  // namespace
 
 TestNode::~TestNode() {
@@ -78,7 +112,12 @@
   static IpczDriver kInvalidDriver = {};
   switch (driver_mode_) {
     case DriverMode::kSync:
-      return reference_drivers::kSingleProcessReferenceDriver;
+      return reference_drivers::kSyncReferenceDriver;
+
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+    case DriverMode::kMultiprocess:
+      return reference_drivers::kMultiprocessReferenceDriver;
+#endif
 
     default:
       // Other modes not yet supported.
@@ -151,34 +190,33 @@
   Connect connect(*this);
   IpczDriverHandle their_transport = absl::visit(connect, portals_or_transport);
 
-  // TODO: Support a multiprocess mode which launches the new node in a child
-  // child process, passing the transport there.
-  std::unique_ptr<TestNode> test_node = details.factory();
-  test_node->SetTransport(their_transport);
-  Ref<TestNodeController> controller =
-      MakeRefCounted<InProcessTestNodeController>(driver_mode_,
-                                                  std::move(test_node));
+  Ref<TestNodeController> controller;
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+  if (driver_mode_ == DriverMode::kMultiprocess) {
+    reference_drivers::FileDescriptor socket =
+        reference_drivers::TakeMultiprocessTransportDescriptor(their_transport);
+    controller = MakeRefCounted<ChildProcessTestNodeController>(
+        child_launcher_.Launch(details.name, std::move(socket)));
+  }
+#endif
+
+  if (!controller) {
+    std::unique_ptr<TestNode> test_node = details.factory();
+    test_node->SetTransport(their_transport);
+    controller = MakeRefCounted<InProcessTestNodeController>(
+        driver_mode_, std::move(test_node));
+  }
+
   spawned_nodes_.push_back(controller);
   return controller;
 }
 
 TestNode::TransportPair TestNode::CreateTransports() {
   TransportPair transports;
-  switch (driver_mode_) {
-    case DriverMode::kSync: {
-      const IpczResult result =
-          reference_drivers::kSingleProcessReferenceDriver.CreateTransports(
-              IPCZ_INVALID_DRIVER_HANDLE, IPCZ_INVALID_DRIVER_HANDLE,
-              IPCZ_NO_FLAGS, nullptr, &transports.ours, &transports.theirs);
-      ABSL_ASSERT(result == IPCZ_RESULT_OK);
-      break;
-    }
-
-    default:
-      LOG(FATAL) << "DriverMode not yet supported.";
-      return {};
-  }
-
+  const IpczResult result = GetDriver().CreateTransports(
+      IPCZ_INVALID_DRIVER_HANDLE, IPCZ_INVALID_DRIVER_HANDLE, IPCZ_NO_FLAGS,
+      nullptr, &transports.ours, &transports.theirs);
+  ABSL_ASSERT(result == IPCZ_RESULT_OK);
   return transports;
 }
 
@@ -187,4 +225,22 @@
   transport_ = transport;
 }
 
+int TestNode::RunAsChild() {
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+  auto transport = std::make_unique<reference_drivers::SocketTransport>(
+      TestChildLauncher::TakeChildSocketDescriptor());
+  SetTransport(
+      reference_drivers::CreateMultiprocessTransport(std::move(transport)));
+  Initialize(DriverMode::kMultiprocess, IPCZ_NO_FLAGS);
+  NodeBody();
+
+  const int exit_code = ::testing::Test::HasFailure() ? 1 : 0;
+  return exit_code;
+#else
+  // Not supported outside of Linux.
+  ABSL_ASSERT(false);
+  return 0;
+#endif
+}
+
 }  // namespace ipcz::test
diff --git a/third_party/ipcz/src/test/multinode_test.h b/third_party/ipcz/src/test/multinode_test.h
index 99508f7..5ae41e8 100644
--- a/third_party/ipcz/src/test/multinode_test.h
+++ b/third_party/ipcz/src/test/multinode_test.h
@@ -14,11 +14,17 @@
 #include "ipcz/ipcz.h"
 #include "test/test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
 #include "third_party/abseil-cpp/absl/base/macros.h"
 #include "third_party/abseil-cpp/absl/types/span.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
+#include "third_party/ipcz/src/test_buildflags.h"
 #include "util/ref_counted.h"
 
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+#include "test/test_child_launcher.h"
+#endif
+
 namespace ipcz::test {
 
 class TestNode;
@@ -26,8 +32,8 @@
 template <typename TestNodeType>
 class MultinodeTest;
 
-// Selects which driver test nodes will use. Interconnecting nodes must always
-// use the same driver.
+// Selects which driver will be used by test nodes. Interconnecting nodes must
+// always use the same driver.
 //
 // Multinode tests are parameterized over these modes to provide coverage of
 // various interesting constraints encountered in production. Some platforms
@@ -39,27 +45,44 @@
 // all driver modes. The synchronous version is generally easier to debug in
 // such cases.
 enum class DriverMode {
-  // Use the fully synchronous, single-process reference driver. This driver
-  // does not create any background threads and all ipcz operations will
-  // complete synchronously from end-to-end.
+  // Use the synchronous, single-process reference driver. This driver does not
+  // create any background threads and all ipcz operations (e.g. message
+  // delivery, portal transfer, proxy elimination, etc) complete synchronously
+  // from end-to-end. Each test node runs its test body on a dedicated thread
+  // within the test process.
   kSync,
 
-  // Use the async multiprocess driver as-is. All nodes can allocate their own
-  // shared memory directly through the driver.
+  // Use the asynchronous single-process reference driver. Transport messages
+  // are received asynchronously, similar to how most production drivers are
+  // likely to operate in practice. Such asynchrony gives rise to
+  // non-determinism throughout ipcz proper and provides good coverage of
+  // potential race conditions.
+  //
+  // As with the kSync driver, each test node runs its test body on a dedicated
+  // thread within the test process.
   kAsync,
 
-  // Use the async multiprocess driver, and force non-broker nodes to delegate
-  // shared memory allocation to their broker.
+  // Use the same driver as kAsync, but non-broker nodes are forced to delegate
+  // shared memory allocation to their broker. This simulates the production
+  // constraints of some sandbox environments and exercises additional
+  // asynchrony in ipcz proper.
   kAsyncDelegatedAlloc,
 
-  // Use the async multiprocess driver, and force non-broker-to-non-broker
-  // transmission of driver objects to be relayed through a broker. All nodes
-  // can allocate their own shared memory directly through the driver.
+  // Use the same driver as kAsync, but driver objects cannot be transmitted
+  // directly between non-brokers and must instead be relayed by a broker. This
+  // simulates the production constraints of some sandbox environments and
+  // exercises additional asynchrony in ipcz proper.
   kAsyncObjectBrokering,
 
-  // Use the async multiprocess driver, forcing shared memory AND driver
-  // object relay both to be delegated to a broker.
+  // Use the same driver as kAsync, imposing the additional constraints of both
+  // kAsyncDelegatedAlloc and kAsyncObjectBrokering as described above.
   kAsyncObjectBrokeringAndDelegatedAlloc,
+
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+  // Use a multiprocess-capable driver (Linux only for now), with each test node
+  // running in its own isolated child process.
+  kMultiprocess,
+#endif
 };
 
 namespace internal {
@@ -187,6 +210,9 @@
   };
   TransportPair CreateTransports();
 
+  // Helper used to support multiprocess TestNode invocation.
+  int RunAsChild();
+
  private:
   // Sets the transport to use when connecting to a broker via ConnectBroker.
   // Must only be called once.
@@ -218,6 +244,10 @@
   IpczHandle node_ = IPCZ_INVALID_HANDLE;
   IpczDriverHandle transport_ = IPCZ_INVALID_DRIVER_HANDLE;
   std::vector<Ref<TestNodeController>> spawned_nodes_;
+
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+  TestChildLauncher child_launcher_;
+#endif
 };
 
 // Actual parameterized GTest Test fixture for multinode tests. This or a
@@ -237,6 +267,15 @@
 
 }  // namespace ipcz::test
 
+#define MULTINODE_TEST_CHILD_MAIN_HELPER(func, node_name) \
+  MULTIPROCESS_TEST_MAIN(func) {                          \
+    node_name node;                                       \
+    return node.RunAsChild();                             \
+  }
+
+#define MULTINODE_TEST_CHILD_MAIN(fixture, node_name) \
+  MULTINODE_TEST_CHILD_MAIN_HELPER(fixture##_##node_name##_Node, node_name)
+
 // Defines the main body of a non-broker test node for a multinode test. The
 // named node can be spawned by another node using SpawnTestNode<T> where T is
 // the unique name given by `node_name` here. `fixture` must be
@@ -254,11 +293,20 @@
     };                                                                     \
     void NodeBody() override;                                              \
   };                                                                       \
+  MULTINODE_TEST_CHILD_MAIN(fixture, node_name);                           \
   void node_name::NodeBody()
 
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+#define IPCZ_EXTRA_DRIVER_MODES , ipcz::test::DriverMode::kMultiprocess
+#else
+#define IPCZ_EXTRA_DRIVER_MODES
+#endif
+
 // TODO: Add other DriverMode enumerators here as support is landed.
 #define INSTANTIATE_MULTINODE_TEST_SUITE_P(suite) \
-  INSTANTIATE_TEST_SUITE_P(, suite,               \
-                           ::testing::Values(ipcz::test::DriverMode::kSync))
+  INSTANTIATE_TEST_SUITE_P(                       \
+      , suite,                                    \
+      ::testing::Values(                          \
+          ipcz::test::DriverMode::kSync IPCZ_EXTRA_DRIVER_MODES))
 
 #endif  // IPCZ_SRC_TEST_MULTINODE_TEST_H_
diff --git a/third_party/ipcz/src/test/run_all_tests.cc b/third_party/ipcz/src/test/run_all_tests.cc
index 4455934..9d8cfda 100644
--- a/third_party/ipcz/src/test/run_all_tests.cc
+++ b/third_party/ipcz/src/test/run_all_tests.cc
@@ -5,10 +5,26 @@
 #include "standalone/base/logging.h"
 #include "standalone/base/stack_trace.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
+#include "third_party/ipcz/src/test_buildflags.h"
+
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+#include "third_party/ipcz/src/test/test_child_launcher.h"
+#endif
 
 int main(int argc, char** argv) {
   // TODO(rockot): Implement basic command line parsing for standalone builds.
   ipcz::standalone::StackTrace::EnableStackTraceSymbolization(argv[0]);
   testing::InitGoogleTest(&argc, argv);
+
+#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
+  ipcz::test::TestChildLauncher::Initialize(argc, argv);
+
+  int exit_code;
+  if (ipcz::test::TestChildLauncher::RunTestChild(exit_code)) {
+    return exit_code;
+  }
+#endif
+
   return RUN_ALL_TESTS();
 }
diff --git a/third_party/ipcz/src/test/test_child_launcher.cc b/third_party/ipcz/src/test/test_child_launcher.cc
new file mode 100644
index 0000000..b6d9b0e
--- /dev/null
+++ b/third_party/ipcz/src/test/test_child_launcher.cc
@@ -0,0 +1,176 @@
+// 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 "test/test_child_launcher.h"
+
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include "reference_drivers/handle_eintr.h"
+#include "test/multinode_test.h"
+#include "testing/multiprocess_func_list.h"
+#include "third_party/abseil-cpp/absl/base/macros.h"
+#include "third_party/abseil-cpp/absl/strings/str_cat.h"
+#include "util/safe_math.h"
+
+namespace ipcz::test {
+
+namespace {
+
+// NOTE: This switch name must be identical to Chromium's kTestChildProcess
+// switch in //base/base_switches.h in order for these tests to work properly as
+// part of any base::TestSuite based unit tests.
+constexpr std::string_view kTestChildProcess = "test-child-process";
+
+// Used to tell a forked child process which open file descriptor corresponds to
+// its ipcz driver's SocketTransport.
+constexpr std::string_view kSocketFd = "test-child-socket-fd";
+
+using ArgList = std::vector<std::string>;
+ArgList& GetArgList() {
+  static ArgList* list = new ArgList();
+  return *list;
+}
+
+std::string& GetTestNodeName() {
+  static std::string* name = new std::string();
+  return *name;
+}
+
+reference_drivers::FileDescriptor& GetSocketFd() {
+  static reference_drivers::FileDescriptor* descriptor =
+      new reference_drivers::FileDescriptor();
+  return *descriptor;
+}
+
+template <typename ValueType>
+std::string MakeSwitch(std::string_view name, ValueType value) {
+  return absl::StrCat("--", name.data(), "=", value);
+}
+
+// Produces an argv-style data representation of a vector of strings.
+std::vector<char*> MakeExecArgv(ArgList& args) {
+  // +1 to NULL-terminate.
+  std::vector<char*> argv(args.size() + 1);
+  for (size_t i = 0; i < args.size(); ++i) {
+    argv[i] = args[i].data();
+  }
+  return argv;
+}
+
+int GetMaxFds() {
+  struct rlimit num_files;
+  int result = getrlimit(RLIMIT_NOFILE, &num_files);
+  ABSL_ASSERT(result == 0);
+  return checked_cast<int>(num_files.rlim_cur);
+}
+
+}  // namespace
+
+TestChildLauncher::TestChildLauncher() = default;
+
+TestChildLauncher::~TestChildLauncher() = default;
+
+// static
+void TestChildLauncher::Initialize(int argc, char** argv) {
+  // This implements extremely cheesy command-line "parsing" by scanning for the
+  // only two switches we'll ever care about.
+
+  const std::string kTestChildSwitchPrefix =
+      absl::StrCat("--", kTestChildProcess.data(), "=");
+  const std::string kSocketFdSwitchPrefix =
+      absl::StrCat("--", kSocketFd.data(), "=");
+
+  // We stash a complete copy of the command line in GetArgList(), modulo the
+  // switches above which are specific to a single child process. This copy is
+  // used to stamp out new command lines for future fork/exec'd processes.
+  ArgList& args = GetArgList();
+  args.resize(argc);
+  for (int i = 0; i < argc; ++i) {
+    std::string_view value(argv[i]);
+    if (value.rfind(kTestChildSwitchPrefix) != std::string::npos) {
+      GetTestNodeName() = value.substr(kTestChildSwitchPrefix.size());
+    } else if (value.rfind(kSocketFdSwitchPrefix) != std::string::npos) {
+      int fd;
+      const bool ok = absl::SimpleAtoi(
+          value.substr(kSocketFdSwitchPrefix.size()).data(), &fd);
+      ABSL_HARDENING_ASSERT(ok);
+      GetSocketFd() = reference_drivers::FileDescriptor(fd);
+    } else {
+      args[i] = value;
+    }
+  }
+}
+
+// static
+bool TestChildLauncher::RunTestChild(int& exit_code) {
+  if (GetTestNodeName().empty()) {
+    return false;
+  }
+
+  // Run the function emitted by named test node's MUTLTIPROCESS_TEST_MAIN()
+  // invocation. Note that this only occurs in upstream ipcz_tests. If these
+  // tests are run as part of a base::TestSuite in the Chromium repository,
+  // the TestSuite itself is responsible for invoking this function in child
+  // processes. See base::TestSuite::Run() for that.
+  exit_code =
+      multi_process_function_list::InvokeChildProcessTest(GetTestNodeName());
+  return true;
+}
+
+// static
+reference_drivers::FileDescriptor
+TestChildLauncher::TakeChildSocketDescriptor() {
+  reference_drivers::FileDescriptor& fd = GetSocketFd();
+  ABSL_HARDENING_ASSERT(fd.is_valid());
+  return std::move(fd);
+}
+
+// static
+bool TestChildLauncher::WaitForSuccessfulProcessTermination(pid_t pid) {
+  int status;
+  pid_t result = HANDLE_EINTR(waitpid(pid, &status, 0));
+  return result == pid && WIFEXITED(status) && WEXITSTATUS(status) == 0;
+}
+
+pid_t TestChildLauncher::Launch(std::string_view node_name,
+                                reference_drivers::FileDescriptor socket) {
+  pid_t child_pid = fork();
+  ABSL_HARDENING_ASSERT(child_pid >= 0);
+
+  if (child_pid > 0) {
+    // In the parent.
+    socket.reset();
+    return child_pid;
+  }
+
+  // In the child. First clean up all file descriptors other than the ones we
+  // want to keep open.
+  for (int i = STDERR_FILENO + 1; i < GetMaxFds(); ++i) {
+    if (i != socket.get()) {
+      close(i);
+    }
+  }
+
+  // Execute the test binary with an extra command-line switch that circumvents
+  // the normal test runner path and instead runs the named TestNode's body.
+  ArgList child_args = GetArgList();
+  child_args.push_back(MakeSwitch(kTestChildProcess, node_name.data()));
+  child_args.push_back(MakeSwitch(kSocketFd, socket.release()));
+
+  std::vector<char*> child_argv = MakeExecArgv(child_args);
+  execv(child_argv[0], child_argv.data());
+
+  // Should never be reached.
+  ABSL_HARDENING_ASSERT(false);
+  return 0;
+}
+
+}  // namespace ipcz::test
diff --git a/third_party/ipcz/src/test/test_child_launcher.h b/third_party/ipcz/src/test/test_child_launcher.h
new file mode 100644
index 0000000..0651141
--- /dev/null
+++ b/third_party/ipcz/src/test/test_child_launcher.h
@@ -0,0 +1,50 @@
+// 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 IPCZ_SRC_TEST_TEST_CHILD_LAUNCHER_H_
+#define IPCZ_SRC_TEST_TEST_CHILD_LAUNCHER_H_
+
+#include <sys/types.h>
+
+#include "reference_drivers/file_descriptor.h"
+
+#include <string_view>
+
+namespace ipcz::test {
+
+// This class helps multinode tests launch child processes to run test nodes in
+// isolation. This is only supported on Linux.
+class TestChildLauncher {
+ public:
+  TestChildLauncher();
+  ~TestChildLauncher();
+
+  // Must be called early in process startup with inputs from main().
+  static void Initialize(int argc, char** argv);
+
+  // Called by standalone ipcz_tests main() to run a TestNode body within a
+  // child process. Must be called after Initialize(). Returns true if and only
+  // if the calling process was launched as a test child process and has
+  // appropriate command line arguments to initialize a TestNode.
+  static bool RunTestChild(int& exit_code);
+
+  // Extracts a FileDescriptor passed on the command line to this (child)
+  // process.
+  static reference_drivers::FileDescriptor TakeChildSocketDescriptor();
+
+  // Waits for a child process to terminate, and returns true if and only if
+  // the process terminated normally with an exit code of 0.
+  static bool WaitForSuccessfulProcessTermination(pid_t pid);
+
+  // Launches a new child process to run the TestNode identified by `node_name`,
+  // using `socket` as the basis for a SocketTransport which will connect to the
+  // test's main broker node. Returns the PID of the new child process. This
+  // call either succeeds or crashes, so the return PID will always be valid.
+  pid_t Launch(std::string_view node_name,
+               reference_drivers::FileDescriptor socket);
+};
+
+}  // namespace ipcz::test
+
+#endif  // IPCZ_SRC_TEST_TEST_CHILD_LAUNCHER_H_
diff --git a/third_party/ipcz/src/test/test_transport_listener.cc b/third_party/ipcz/src/test/test_transport_listener.cc
index 16ca0ba..f7eb836c 100644
--- a/third_party/ipcz/src/test/test_transport_listener.cc
+++ b/third_party/ipcz/src/test/test_transport_listener.cc
@@ -8,6 +8,7 @@
 
 #include "ipcz/driver_object.h"
 #include "ipcz/driver_transport.h"
+#include "ipcz/message.h"
 #include "ipcz/node.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/base/macros.h"
@@ -57,7 +58,13 @@
 void TestTransportListener::OnError(ErrorHandler handler) {
   ABSL_ASSERT(!error_handler_);
   error_handler_ = std::move(handler);
-  ActivateTransportIfNecessary();
+
+  // Since the caller only cares about handling errors, ensure all valid
+  // messages are cleanly discarded. This also activates the transport.
+  OnRawMessage([this](const DriverTransport::RawMessage& message) {
+    Message m;
+    return m.DeserializeUnknownType(message, *transport_);
+  });
 }
 
 void TestTransportListener::ActivateTransportIfNecessary() {
diff --git a/third_party/ipcz/src/trap_test.cc b/third_party/ipcz/src/trap_test.cc
index cf30087..5c2f537 100644
--- a/third_party/ipcz/src/trap_test.cc
+++ b/third_party/ipcz/src/trap_test.cc
@@ -6,7 +6,7 @@
 #include <utility>
 
 #include "ipcz/ipcz.h"
-#include "reference_drivers/single_process_reference_driver.h"
+#include "reference_drivers/sync_reference_driver.h"
 #include "test/test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/memory/memory.h"
@@ -23,8 +23,7 @@
   }
 
  private:
-  const IpczHandle node_{
-      CreateNode(reference_drivers::kSingleProcessReferenceDriver)};
+  const IpczHandle node_{CreateNode(reference_drivers::kSyncReferenceDriver)};
 };
 
 TEST_F(TrapTest, RemoveOnClose) {
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium
index 294a37d3..daa78ff 100644
--- a/third_party/metrics_proto/README.chromium
+++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@
 Name: Metrics Protos
 Short Name: metrics_proto
 URL: This is the canonical public repository
-Version: 453819681
-Date: 2022/06/09 UTC
+Version: 456316491
+Date: 2022/06/21 UTC
 License: BSD
 Security Critical: Yes
 
diff --git a/third_party/metrics_proto/omnibox_event.proto b/third_party/metrics_proto/omnibox_event.proto
index f47ebb4..fb72025 100644
--- a/third_party/metrics_proto/omnibox_event.proto
+++ b/third_party/metrics_proto/omnibox_event.proto
@@ -164,12 +164,12 @@
     // Android's Search Widget started directly from Launcher.
     ANDROID_SEARCH_WIDGET = 16;
 
-    // Android's Start surface homepage.
-    START_SURFACE_HOMEPAGE = 17;
+    START_SURFACE_HOMEPAGE = 17;  // DEPRECATED. Android's Start surface
+                                  // homepage.
 
-    // New Tab with Omnibox focused when Android's start surface finale is
-    // enabled.
-    START_SURFACE_NEW_TAB = 18;
+    START_SURFACE_NEW_TAB = 18;  // DEPRECATED. New Tab with Omnibox focused
+                                 // when Android's start surface finale is
+                                 // enabled.
 
     // Android's improved Search Widget with new suggestions.
     ANDROID_SHORTCUTS_WIDGET = 19;
@@ -180,15 +180,13 @@
     // Android's auxiliary search backend.
     ANDROID_AUXILIARY_SEARCH = 21;
 
-    // The user interacted with the search resumption module on the Android New
-    // Tab Page. This search resumption module offered suggestions based on a
+    // Android's search resumption module which offers suggestions based on a
     // search results page that the user was on.
-    NTP_SEARCH_RESUMPTION_SEARCH_RESULT_PAGE = 22;
+    SEARCH_RESUMPTION_SEARCH_RESULT_PAGE = 22;
 
-    // The user interacted with the search resumption module on the Android New
-    // Tab Page. This search resumption module offered suggestions based on a
+    // Android's search resumption module which offers suggestions based on a
     // non-search-results page that the user was on.
-    NTP_SEARCH_RESUMPTION_OTHER = 23;
+    SEARCH_RESUMPTION_OTHER = 23;
 
     // When adding new classifications, please consider adding them in
     // chromium's chrome/browser/resources/omnibox/omnibox.html
diff --git a/third_party/metrics_proto/system_profile.proto b/third_party/metrics_proto/system_profile.proto
index f406bf4..3c43f23 100644
--- a/third_party/metrics_proto/system_profile.proto
+++ b/third_party/metrics_proto/system_profile.proto
@@ -231,9 +231,9 @@
   // Information on the user's hardware.
   // Next tag: 27
   message Hardware {
-    // OS CPU architecture. Taken from uname -m and modified in Chromium logic.
-    // Common options are: x86, x86_64, armv7l, armv8l, aarch64.
-    // Not recorded on iOS.
+    // OS CPU architecture. Common options are: x86, x86_64, armv7l, armv8l,
+    // and aarch64.
+    // Started being correctly recorded on iOS in M90: crrev/c/2723012.
     optional string cpu_architecture = 1;
 
     // Browser process CPU architecture. Will be different from
diff --git a/third_party/metrics_proto/ukm/source.proto b/third_party/metrics_proto/ukm/source.proto
index e22c096..e301234 100644
--- a/third_party/metrics_proto/ukm/source.proto
+++ b/third_party/metrics_proto/ukm/source.proto
@@ -21,6 +21,7 @@
   DESKTOP_WEB_APP_ID = 6;
   WORKER_ID = 7;
   NO_URL_ID = 8;
+  REDIRECT_ID = 9;
 }
 
 // Android Activity Type defined by
diff --git a/third_party/r8/3pp/patches/0004-Add-a-way-to-enable-reportUnusedProguardConfiguratio.patch b/third_party/r8/3pp/patches/0004-Add-a-way-to-enable-reportUnusedProguardConfiguratio.patch
deleted file mode 100644
index 1311004b0..0000000
--- a/third_party/r8/3pp/patches/0004-Add-a-way-to-enable-reportUnusedProguardConfiguratio.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From f82443efc9e9a724f8072b8adb13f71ecf3429bf Mon Sep 17 00:00:00 2001
-From: Andrew Grieve <agrieve@chromium.org>
-Date: Thu, 26 May 2022 13:35:04 -0400
-Subject: [PATCH 4/4] Add a way to enable
- reportUnusedProguardConfigurationRules
-
-Bug: 1303951
----
- src/main/java/com/android/tools/r8/utils/InternalOptions.java | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
-index ee15be255a..01a601c12f 100644
---- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
-+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
-@@ -1832,7 +1832,7 @@ public class InternalOptions implements GlobalKeepInfoConfiguration {
-     public boolean allowInvokeErrors = false;
-     public boolean allowUnnecessaryDontWarnWildcards = true;
-     public boolean allowUnusedDontWarnRules = true;
--    public boolean reportUnusedProguardConfigurationRules = false;
-+    public boolean reportUnusedProguardConfigurationRules = System.getProperty("com.android.tools.r8.reportUnusedProguardConfigurationRules") != null;
-     public boolean alwaysUseExistingAccessInfoCollectionsInMemberRebinding = true;
-     public boolean alwaysUsePessimisticRegisterAllocation = false;
-     public boolean enableCheckCastAndInstanceOfRemoval = true;
--- 
-2.36.1.476.g0c4daa206d-goog
-
diff --git a/third_party/tflite/README.chromium b/third_party/tflite/README.chromium
index 613211d..848bf09 100644
--- a/third_party/tflite/README.chromium
+++ b/third_party/tflite/README.chromium
@@ -1,8 +1,8 @@
 Name: TensorFlow Lite
 Short Name: tflite
 URL: https://github.com/tensorflow/tensorflow
-Version: 0a25ee4aef238f0c5e33647eb6d5fee072054fd8
-Date: 2022/06/13
+Version: 0550a551f158167fa88acb17261d96e959529f70
+Date: 2022/06/21
 License: Apache 2.0
 License File: LICENSE
 Security Critical: Yes
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt
index 40ce970..5127fac 100644
--- a/third_party/webgpu-cts/ts_sources.txt
+++ b/third_party/webgpu-cts/ts_sources.txt
@@ -186,9 +186,9 @@
 src/webgpu/api/operation/vertex_state/correctness.spec.ts
 src/webgpu/api/operation/vertex_state/index_format.spec.ts
 src/webgpu/api/validation/validation_test.ts
+src/webgpu/api/validation/compute_pipeline.spec.ts
 src/webgpu/api/validation/createBindGroup.spec.ts
 src/webgpu/api/validation/createBindGroupLayout.spec.ts
-src/webgpu/api/validation/createComputePipeline.spec.ts
 src/webgpu/api/validation/createPipelineLayout.spec.ts
 src/webgpu/api/validation/createSampler.spec.ts
 src/webgpu/api/validation/createTexture.spec.ts
@@ -200,6 +200,7 @@
 src/webgpu/api/validation/buffer/mapping.spec.ts
 src/webgpu/api/validation/buffer/threading.spec.ts
 src/webgpu/api/validation/capability_checks/features/query_types.spec.ts
+src/webgpu/util/create_elements.ts
 src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts
 src/webgpu/api/validation/encoding/beginRenderPass.spec.ts
 src/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.ts
@@ -238,7 +239,6 @@
 src/webgpu/api/validation/queue/buffer_mapped.spec.ts
 src/webgpu/api/validation/queue/submit.spec.ts
 src/webgpu/api/validation/queue/writeBuffer.spec.ts
-src/webgpu/util/create_elements.ts
 src/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.ts
 src/webgpu/api/validation/queue/destroyed/query_set.spec.ts
 src/webgpu/api/validation/render_pass/attachment_compatibility.spec.ts
diff --git a/third_party/wpt_tools/README.chromium b/third_party/wpt_tools/README.chromium
index b280f71..ce4994d8 100644
--- a/third_party/wpt_tools/README.chromium
+++ b/third_party/wpt_tools/README.chromium
@@ -1,7 +1,7 @@
 Name: web-platform-tests - Test Suites for Web Platform specifications
 Short Name: wpt
 URL: https://github.com/web-platform-tests/wpt/
-Version: f6e61a6aafdc22d149cd38edb6c7be67b4037716
+Version: fd8aeb1bb2eb33bc43f8a5bbc682b0cff6075dfe
 License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html)
 License File: NOT_SHIPPED
 Security Critical: no
diff --git a/third_party/wpt_tools/WPTIncludeList b/third_party/wpt_tools/WPTIncludeList
index 0d846ab..e6dc118 100644
--- a/third_party/wpt_tools/WPTIncludeList
+++ b/third_party/wpt_tools/WPTIncludeList
@@ -224,6 +224,7 @@
 ./tools/webdriver/webdriver/bidi/modules/__init__.py
 ./tools/webdriver/webdriver/bidi/modules/_module.py
 ./tools/webdriver/webdriver/bidi/modules/browsing_context.py
+./tools/webdriver/webdriver/bidi/modules/script.py
 ./tools/webdriver/webdriver/bidi/modules/session.py
 ./tools/webdriver/webdriver/bidi/transport.py
 ./tools/webtransport/README.md
diff --git a/third_party/wpt_tools/wpt/tools/lint/lint.py b/third_party/wpt_tools/wpt/tools/lint/lint.py
index 92596af..f51e451 100644
--- a/third_party/wpt_tools/wpt/tools/lint/lint.py
+++ b/third_party/wpt_tools/wpt/tools/lint/lint.py
@@ -1025,6 +1025,11 @@
 
     if jobs == 0:
         jobs = multiprocessing.cpu_count()
+        if sys.platform == 'win32':
+            # Using too many child processes in Python 3 hits either hangs or a
+            # ValueError exception, and, has diminishing returns. Clamp to 56 to
+            # give margin for error.
+            jobs = min(jobs, 56)
 
     with open(os.path.join(repo_root, "lint.ignore")) as f:
         ignorelist, skipped_files = parse_ignorelist(f)
diff --git a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/client.py b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/client.py
index 762b71c..9dc80d8 100644
--- a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/client.py
+++ b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/client.py
@@ -92,6 +92,7 @@
         # For each module, have a property representing that module
         self.session = modules.Session(self)
         self.browsing_context = modules.BrowsingContext(self)
+        self.script = modules.Script(self)
 
     @property
     def event_loop(self):
diff --git a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/modules/__init__.py b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/modules/__init__.py
index a339ebc75..487b1270 100644
--- a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/modules/__init__.py
+++ b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/modules/__init__.py
@@ -2,3 +2,4 @@
 
 from .session import Session
 from .browsing_context import BrowsingContext
+from .script import Script
diff --git a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/modules/script.py b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/modules/script.py
new file mode 100644
index 0000000..d8ab66a4
--- /dev/null
+++ b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi/modules/script.py
@@ -0,0 +1,56 @@
+from enum import Enum
+from typing import Any, Optional, Mapping, MutableMapping, Union, Dict
+
+from ._module import BidiModule, command
+
+
+class ScriptEvaluateResultException(Exception):
+    def __init__(self, result: Mapping[str, Any]):
+        self.result = result
+        super().__init__("Script execution failed.")
+
+
+class OwnershipModel(Enum):
+    NONE = "none"
+    ROOT = "root"
+
+
+class RealmTarget(Dict[str, Any]):
+    def __init__(self, realm: str):
+        dict.__init__(self, realm=realm)
+
+
+class ContextTarget(Dict[str, Any]):
+    def __init__(self, context: str, sandbox: Optional[str] = None):
+        if sandbox is None:
+            dict.__init__(self, context=context)
+        else:
+            dict.__init__(self, context=context, sandbox=sandbox)
+
+
+Target = Union[RealmTarget, ContextTarget]
+
+
+class Script(BidiModule):
+    @command
+    def evaluate(self,
+                 expression: str,
+                 target: Target,
+                 await_promise: Optional[bool] = None,
+                 result_ownership: Optional[OwnershipModel] = None) -> Mapping[str, Any]:
+        params: MutableMapping[str, Any] = {
+            "expression": expression,
+            "target": target,
+        }
+
+        if await_promise is not None:
+            params["awaitPromise"] = await_promise
+        if result_ownership is not None:
+            params["resultOwnership"] = result_ownership
+        return params
+
+    @evaluate.result
+    def _evaluate(self, result: Mapping[str, Any]) -> Any:
+        if "result" not in result:
+            raise ScriptEvaluateResultException(result)
+        return result["result"]
diff --git a/third_party/wpt_tools/wpt/tools/wpt/browser.py b/third_party/wpt_tools/wpt/tools/wpt/browser.py
index b920674d..96b192bb 100644
--- a/third_party/wpt_tools/wpt/tools/wpt/browser.py
+++ b/third_party/wpt_tools/wpt/tools/wpt/browser.py
@@ -156,6 +156,8 @@
 
         if self.platform in ("linux", "win"):
             bits = "64" if uname[4] == "x86_64" else "32"
+        elif self.platform == "macos" and uname.machine == "arm64":
+            bits = "-aarch64"
         else:
             bits = ""
 
@@ -620,6 +622,8 @@
         """Returns a string that is used for the platform directory in Chromium Snapshots"""
         if (self.platform == "Linux" or self.platform == "Win") and uname[4] == "x86_64":
             return f"{self.platform}_x64"
+        if self.platform == "Mac" and uname.machine == "arm64":
+            return "Mac_Arm"
         return self.platform
 
     def find_webdriver(self, venv_path=None, channel=None, browser_binary=None):
@@ -746,8 +750,6 @@
         if webdriver_binary is None:
             self.logger.warning("No valid webdriver supplied to detect version.")
             return None
-        if uname[0] == "Windows":
-            return _get_fileversion(webdriver_binary, self.logger)
 
         try:
             version_string = call(webdriver_binary, "--version").strip()
@@ -864,11 +866,19 @@
 
     product = "chrome"
 
+    @property
+    def _chromedriver_api_platform_string(self):
+        """chromedriver.storage.googleapis.com has a different filename for M1 binary,
+        while the snapshot URL has a different directory but the same filename."""
+        if self.platform == "Mac" and uname.machine == "arm64":
+            return "mac64_m1"
+        return self._chromedriver_platform_string
+
     def _get_webdriver_url(self, version):
         """Get a ChromeDriver API URL to download a version of ChromeDriver that matches
         the browser binary version. Version selection is described here:
         https://chromedriver.chromium.org/downloads/version-selection"""
-        filename = f"chromedriver_{self._chromedriver_platform_string}.zip"
+        filename = f"chromedriver_{self._chromedriver_api_platform_string}.zip"
 
         version = self._remove_version_suffix(version)
 
@@ -886,6 +896,7 @@
                 # We currently use the latest Chromium revision to get a compatible Chromedriver
                 # version for Chrome Dev, since it is not available through the ChromeDriver API.
                 # If we've gotten to this point, it is assumed that this is Chrome Dev.
+                filename = f"chromedriver_{self._chromedriver_platform_string}.zip"
                 revision = self._get_chromium_revision(filename, version)
                 return self._build_snapshots_url(revision, filename)
         return f"https://chromedriver.storage.googleapis.com/{latest}/{filename}"
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt
index e385f471..222c916 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt
@@ -3,7 +3,6 @@
 mozdevice==4.0.3
 mozinstall==2.0.1
 mozleak==0.2
-moznetwork==1.1.0
 mozprofile==2.5.0
 mozrunner==8.2.1
 mozversion==2.3.0
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py
index 851e3efb..5404e53 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -95,7 +95,6 @@
             "certutil_binary": kwargs["certutil_binary"],
             "ca_certificate_path": config.ssl_config["ca_cert_path"],
             "e10s": kwargs["gecko_e10s"],
-            "enable_webrender": kwargs["enable_webrender"],
             "enable_fission": kwargs["enable_fission"],
             "stackfix_dir": kwargs["stackfix_dir"],
             "binary_args": kwargs["binary_args"],
@@ -211,7 +210,22 @@
             {"os": ["version"], "processor": ["bits"]})
 
 
-def get_environ(logger, binary, debug_info, stylo_threads, headless, enable_webrender,
+def log_gecko_crashes(logger, process, test, profile_dir, symbols_path, stackwalk_binary):
+    dump_dir = os.path.join(profile_dir, "minidumps")
+
+    try:
+        return bool(mozcrash.log_crashes(logger,
+                                         dump_dir,
+                                         symbols_path=symbols_path,
+                                         stackwalk_binary=stackwalk_binary,
+                                         process=process,
+                                         test=test))
+    except OSError:
+        logger.warning("Looking for crash dump files failed")
+        return False
+
+
+def get_environ(logger, binary, debug_info, stylo_threads, headless,
                 chaos_mode_flags=None):
     env = test_environment(xrePath=os.path.abspath(os.path.dirname(binary)),
                            debugger=debug_info is not None,
@@ -225,11 +239,6 @@
         env["MOZ_CHAOSMODE"] = str(chaos_mode_flags)
     if headless:
         env["MOZ_HEADLESS"] = "1"
-    if enable_webrender:
-        env["MOZ_WEBRENDER"] = "1"
-        env["MOZ_ACCELERATED"] = "1"
-    else:
-        env["MOZ_WEBRENDER"] = "0"
     return env
 
 
@@ -252,7 +261,7 @@
     __metaclass__ = ABCMeta
 
     def __init__(self, logger, binary, binary_args, profile_creator, debug_info,
-                 chaos_mode_flags, headless, enable_webrender, stylo_threads,
+                 chaos_mode_flags, headless, stylo_threads,
                  leak_check, stackfix_dir, symbols_path, asan):
         """Object that manages starting and stopping instances of Firefox."""
         self.logger = logger
@@ -262,7 +271,6 @@
         self.debug_info = debug_info
         self.chaos_mode_flags = chaos_mode_flags
         self.headless = headless
-        self.enable_webrender = enable_webrender
         self.stylo_threads = stylo_threads
         self.leak_check = leak_check
         self.stackfix_dir = stackfix_dir
@@ -304,7 +312,7 @@
         profile.set_preferences({"marionette.port": marionette_port})
 
         env = get_environ(self.logger, self.binary, self.debug_info, self.stylo_threads,
-                          self.headless, self.enable_webrender, self.chaos_mode_flags)
+                          self.headless, self.chaos_mode_flags)
 
         args = self.binary_args[:] if self.binary_args else []
         args += [cmd_arg("marionette"), "about:blank"]
@@ -712,7 +720,7 @@
 
     def __init__(self, logger, binary, prefs_root, test_type, extra_prefs=None, debug_info=None,
                  symbols_path=None, stackwalk_binary=None, certutil_binary=None,
-                 ca_certificate_path=None, e10s=False, enable_webrender=False, enable_fission=False,
+                 ca_certificate_path=None, e10s=False, enable_fission=False,
                  stackfix_dir=None, binary_args=None, timeout_multiplier=None, leak_check=False,
                  asan=False, stylo_threads=1, chaos_mode_flags=None, config=None,
                  browser_channel="nightly", headless=None, preload_browser=False,
@@ -760,7 +768,6 @@
                                                      debug_info,
                                                      chaos_mode_flags,
                                                      headless,
-                                                     enable_webrender,
                                                      stylo_threads,
                                                      leak_check,
                                                      stackfix_dir,
@@ -805,18 +812,12 @@
                                  "supports_devtools": True}
 
     def check_crash(self, process, test):
-        dump_dir = os.path.join(self.instance.runner.profile.profile, "minidumps")
-
-        try:
-            return bool(mozcrash.log_crashes(self.logger,
-                                             dump_dir,
-                                             symbols_path=self.symbols_path,
-                                             stackwalk_binary=self.stackwalk_binary,
-                                             process=process,
-                                             test=test))
-        except OSError:
-            self.logger.warning("Looking for crash dump files failed")
-            return False
+        return log_gecko_crashes(self.logger,
+                                 process,
+                                 test,
+                                 self.instance.runner.profile.profile,
+                                 self.symbols_path,
+                                 self.stackwalk_binary)
 
 
 class FirefoxWdSpecBrowser(WebDriverBrowser):
@@ -946,3 +947,11 @@
         args["supports_devtools"] = False
         args["profile"] = self.profile.profile
         return cls, args
+
+    def check_crash(self, process, test):
+        return log_gecko_crashes(self.logger,
+                                 process,
+                                 test,
+                                 self.profile.profile,
+                                 self.symbols_path,
+                                 self.stackwalk_binary)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
index 1e3e5b7a..0ee65a71 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
@@ -2,7 +2,6 @@
 
 import os
 
-import moznetwork
 from mozrunner import FennecEmulatorRunner, get_app_context
 
 from .base import (get_free_port,
@@ -97,10 +96,7 @@
 
 
 def env_options():
-    # The server host is set to public localhost IP so that resources can be accessed
-    # from Android emulator
-    return {"server_host": moznetwork.get_ip(),
-            "bind_address": False,
+    return {"server_host": "127.0.0.1",
             "supports_debugger": True}
 
 
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/chromium.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
index fb3c0dd..eca63d13 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
@@ -1,11 +1,16 @@
 # mypy: allow-untyped-defs
 
+import functools
 import json
 import time
 
 from collections import defaultdict
 from mozlog.formatters import base
 
+from wptrunner.wptmanifest import serializer
+
+_escape_heading = functools.partial(serializer.escape, extras="]")
+
 
 class ChromiumFormatter(base.BaseFormatter):  # type: ignore
     """Formatter to produce results matching the Chromium JSON Test Results format.
@@ -75,7 +80,8 @@
         Messages are appended verbatim to self.messages[test].
         """
         if subtest:
-            result = "  [%s]\n    expected: %s\n" % (subtest, wpt_actual_status)
+            result = "  [%s]\n    expected: %s\n" % (_escape_heading(subtest),
+                                                     wpt_actual_status)
             self.actual_metadata[test].append(result)
             if message:
                 self.messages[test].append("%s: %s\n" % (subtest, message))
@@ -83,7 +89,8 @@
             # No subtest, so this is the top-level test. The result must be
             # prepended to the list, so that it comes before any subtest.
             test_name_last_part = test.split("/")[-1]
-            result = "[%s]\n  expected: %s\n" % (test_name_last_part, wpt_actual_status)
+            result = "[%s]\n  expected: %s\n" % (
+                _escape_heading(test_name_last_part), wpt_actual_status)
             self.actual_metadata[test].insert(0, result)
             if message:
                 self.messages[test].insert(0, "Harness: %s\n" % message)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
index 60e48ba..bf815d5 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
@@ -190,12 +190,14 @@
     logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
 
     # Run two tests with subtest messages. The subtest name should be included
-    # in the output. We should also tolerate missing messages.
+    # in the output. We should also tolerate missing messages and subtest names
+    # with unusual characters.
     logger.suite_start(["t1", "t2"], run_info={}, time=123)
     logger.test_start("t1")
     logger.test_status("t1", status="FAIL", subtest="t1_a",
                        message="t1_a_message")
-    logger.test_status("t1", status="PASS", subtest="t1_b",
+    # Subtest name includes a backslash and two closing square brackets.
+    logger.test_status("t1", status="PASS", subtest=r"t1_\[]]b",
                        message="t1_b_message")
     logger.test_end("t1", status="PASS", expected="PASS")
     logger.test_start("t2")
@@ -221,11 +223,13 @@
     assert t1_artifacts["wpt_actual_metadata"] == [
         "[t1]\n  expected: PASS\n",
         "  [t1_a]\n    expected: FAIL\n",
-        "  [t1_b]\n    expected: PASS\n",
+        "  [t1_\\\\[\\]\\]b]\n    expected: PASS\n",
     ]
     assert t1_artifacts["wpt_log"] == [
         "t1_a: t1_a_message\n",
-        "t1_b: t1_b_message\n",
+        # Only humans will read the log, so there's no need to escape
+        # characters here.
+        "t1_\\[]]b: t1_b_message\n",
     ]
     assert t1_artifacts["wpt_subtest_failure"] == ["true"]
     t2_artifacts = output_json["tests"]["t2"]["artifacts"]
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestupdate.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestupdate.py
index 1131f33..ce12bc33 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestupdate.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestupdate.py
@@ -204,7 +204,7 @@
         self._from_file = True
         self.new_disabled = False
         self.has_result = False
-        self.modified = False
+        self._modified = False
         self.update_properties = UpdateProperties(
             self,
             expected=ExpectedUpdate,
@@ -242,6 +242,16 @@
         """The id of the test represented by this TestNode"""
         return urljoin(self.parent.url, self.name)
 
+    @property
+    def modified(self):
+        if self._modified:
+            return self._modified
+        return any(child.modified for child in self.children)
+
+    @modified.setter
+    def modified(self, value):
+        self._modified = value
+
     def disabled(self, run_info):
         """Boolean indicating whether this test is disabled when run in an
         environment with the given run_info
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py
index b560e8f..733dba0 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py
@@ -723,13 +723,13 @@
             test, test_group, group_metadata = self.get_next_test()
             if test is None:
                 return RunnerManagerState.stop(force_stop)
-            restart = (self.restart_on_new_group and
-                       test_group is not self.state.test_group)
-            if restart:
+            if self.restart_on_new_group and test_group is not self.state.test_group:
                 self.logger.info("Restarting browser for new test group")
+                restart = True
         else:
             test_group = self.state.test_group
             group_metadata = self.state.group_metadata
+
         if restart:
             return RunnerManagerState.restarting(test, test_group, group_metadata, force_stop)
         else:
diff --git a/third_party/xnnpack/BUILD.gn b/third_party/xnnpack/BUILD.gn
index 0b561620..ce9372c 100644
--- a/third_party/xnnpack/BUILD.gn
+++ b/third_party/xnnpack/BUILD.gn
@@ -21,6 +21,8 @@
     "src/src",
   ]
 
+  cflags = [ "-Wno-unused-function" ]
+
   defines = [
     # Don't enable this without first talking to Chrome Security!
     # XNNPACK runs in the browser process. The hardening and fuzzing needed
@@ -47,6 +49,7 @@
     "src/src/datatype-strings.c",
     "src/src/indirection.c",
     "src/src/init.c",
+    "src/src/log.c",
     "src/src/memory-planner.c",
     "src/src/memory.c",
     "src/src/mutex.c",
@@ -655,7 +658,7 @@
     "src/src/subgraph/even-split.c",
     "src/src/subgraph/floor.c",
     "src/src/subgraph/fully-connected.c",
-    "src/src/subgraph/global-average-pooling-2d.c",
+    "src/src/subgraph/global-average-pooling.c",
     "src/src/subgraph/hardswish.c",
     "src/src/subgraph/leaky-relu.c",
     "src/src/subgraph/max-pooling-2d.c",
diff --git a/third_party/xnnpack/README.chromium b/third_party/xnnpack/README.chromium
index e9b9075..48d7e71 100644
--- a/third_party/xnnpack/README.chromium
+++ b/third_party/xnnpack/README.chromium
@@ -1,8 +1,8 @@
 Name: XNNPACK
 Short Name: xnnpack
 URL: https://github.com/google/xnnpack
-Version: 108f3657bc0cc9592f88adb124a21bcf9ca63f06
-Date: 2022/06/10
+Version: 55775ab7afc3a89ed93491e6600bb9afa4dca148
+Date: 2022/06/21
 License: BSD
 Security Critical: Yes
 
diff --git a/third_party/xnnpack/generate_build_gn.py b/third_party/xnnpack/generate_build_gn.py
index d8b3a4e..af340c041 100644
--- a/third_party/xnnpack/generate_build_gn.py
+++ b/third_party/xnnpack/generate_build_gn.py
@@ -58,6 +58,10 @@
     "src/src",
   ]
 
+  cflags=[
+    "-Wno-unused-function",
+  ]
+
   defines = [
     # Don't enable this without first talking to Chrome Security!
     # XNNPACK runs in the browser process. The hardening and fuzzing needed
diff --git a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
index c7e2d966..b854538d 100644
--- a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
+++ b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
@@ -852,6 +852,14 @@
 
     const clang::TypeSourceInfo* type_source_info =
         field_decl->getTypeSourceInfo();
+    if (auto* ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl)) {
+      // Objective-C @synthesize statements should not be rewritten. They return
+      // null for getTypeSourceInfo().
+      if (ivar_decl->getSynthesize()) {
+        assert(!type_source_info);
+        return;
+      }
+    }
     assert(type_source_info && "assuming |type_source_info| is always present");
 
     clang::QualType pointer_type = type_source_info->getType();
diff --git a/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt b/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
index 55c31806..8112313 100644
--- a/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
+++ b/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
@@ -235,6 +235,11 @@
 # Populated manually - pointer to Objective-C object
 gfx::ScopedNSGraphicsContextSaveGState::context_
 base::mac::ScopedNSAutoreleasePool::autorelease_pool_
+content::ThemeHelperMac::theme_observer_
+content::PopupMenuHelper::menu_runner_
+content::ShellJavaScriptDialog::helper_
+ui::ClipboardFormatType::data_
+ui::WeakPtrNSObjectFactory::handle_
 
 #######
 # BackupRefPtr-specific sections
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py
index 132766e8..fa20058 100755
--- a/tools/clang/scripts/build.py
+++ b/tools/clang/scripts/build.py
@@ -755,11 +755,8 @@
     toolchain_hash = '2028cdaf24259d23adcff95393b8cc4f0eef714b'
     toolchain_name = 'debian_bullseye_amd64_sysroot'
     U = toolchain_bucket + toolchain_hash + '/' + toolchain_name + '.tar.xz'
-    sysroot = os.path.join(LLVM_BUILD_TOOLS_DIR, toolchain_name)
-    DownloadAndUnpack(U, sysroot)
-
-    # amd64 is the default toolchain, add it to base_cmake_args.
-    base_cmake_args.append('-DCMAKE_SYSROOT=' + sysroot)
+    sysroot_amd64 = os.path.join(LLVM_BUILD_TOOLS_DIR, toolchain_name)
+    DownloadAndUnpack(U, sysroot_amd64)
 
     # i386
     # hash from https://chromium-review.googlesource.com/c/chromium/src/+/3684954/1/build/linux/sysroot_scripts/sysroots.json#23
@@ -785,6 +782,13 @@
     sysroot_arm64 = os.path.join(LLVM_BUILD_TOOLS_DIR, toolchain_name)
     DownloadAndUnpack(U, sysroot_arm64)
 
+    # Add the sysroot to base_cmake_args.
+    if platform.machine() == 'aarch64':
+      base_cmake_args.append('-DCMAKE_SYSROOT=' + sysroot_arm64)
+    else:
+      # amd64 is the default toolchain.
+      base_cmake_args.append('-DCMAKE_SYSROOT=' + sysroot_amd64)
+
   if sys.platform == 'win32':
     base_cmake_args.append('-DLLVM_USE_CRT_RELEASE=MT')
 
@@ -1055,7 +1059,7 @@
     runtimes_triples_args.append(
         ('x86_64-unknown-linux-gnu',
          compiler_rt_cmake_flags(sanitizers=True, profile=True) + [
-             'CMAKE_SYSROOT=%s' % sysroot,
+             'CMAKE_SYSROOT=%s' % sysroot_amd64,
          ]))
     runtimes_triples_args.append(
         # Using "armv7a-unknown-linux-gnueabhihf" confuses the compiler-rt
diff --git a/tools/clang/scripts/process_crashreports.py b/tools/clang/scripts/process_crashreports.py
index d6d7cd91..0205304 100755
--- a/tools/clang/scripts/process_crashreports.py
+++ b/tools/clang/scripts/process_crashreports.py
@@ -66,6 +66,10 @@
     subprocess.check_call([sys.executable, GSUTIL, '-q', 'cp', tmp_name, dest])
     print('done')
     print('    %s' % dest)
+  except subprocess.CalledProcessError as e:
+    print('upload failed; if it was due to missing permissions, try running')
+    print('download_from_google_storage --config')
+    print('and then try again')
   finally:
     if tmp_name:
       os.remove(tmp_name)
diff --git a/tools/code_coverage/create_js_source_maps/create_js_source_maps.gni b/tools/code_coverage/create_js_source_maps/create_js_source_maps.gni
index 2812c42..9d3f28e5 100644
--- a/tools/code_coverage/create_js_source_maps/create_js_source_maps.gni
+++ b/tools/code_coverage/create_js_source_maps/create_js_source_maps.gni
@@ -6,7 +6,12 @@
 # "preprocess_if_expr" build rule(s) in the BUILD.gn file. If you are getting
 # "Target not found in this context" errors, check that the deps
 # names are correct and that they are defined earlier in the same BUILD.gn file.
+
+import("//ui/webui/webui_features.gni")
+
 template("create_js_source_maps") {
+  assert(enable_webui_inline_sourcemaps)
+
   action_foreach(target_name) {
     script =
         "//tools/code_coverage/create_js_source_maps/create_js_source_maps.py"
diff --git a/tools/cygprofile/cluster.py b/tools/cygprofile/cluster.py
index 4e189ff..b505aa1e 100644
--- a/tools/cygprofile/cluster.py
+++ b/tools/cygprofile/cluster.py
@@ -345,7 +345,7 @@
     other_clustering = []
 
   # Start with the renderer cluster to favor rendering performance.
-  final_ordering = renderer_clustering.copy()
+  final_ordering = list(renderer_clustering)
   seen = set(final_ordering)
   final_ordering.extend(s for s in browser_clustering if s not in seen)
   seen |= set(browser_clustering)
@@ -390,7 +390,7 @@
     other_clustering = []
 
   # Start with the renderer cluster to favor rendering performance.
-  final_ordering = renderer_clustering.copy()
+  final_ordering = list(renderer_clustering)
   seen = set(final_ordering)
   final_ordering.extend(s for s in browser_clustering if s not in seen)
   seen |= set(browser_clustering)
diff --git a/tools/gdb/gdb_chrome.py b/tools/gdb/gdb_chrome.py
index db2a754..79282f3 100644
--- a/tools/gdb/gdb_chrome.py
+++ b/tools/gdb/gdb_chrome.py
@@ -465,7 +465,7 @@
     return self.val['__a_']['__a_value']
 
 
-pp_set.add_printer('std::__Cr::atomic', '^std::__Cr::atomic<.*>$',
+pp_set.add_printer('std::Cr::__atomic', '^std::Cr::__atomic<.*>$',
                    AtomicPrinter)
 
 gdb.printing.register_pretty_printer(gdb, pp_set, replace=_DEBUGGING)
diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni
index ce01d36..940ef00f 100644
--- a/tools/grit/grit_rule.gni
+++ b/tools/grit/grit_rule.gni
@@ -391,12 +391,11 @@
     zip(_zip_target_name) {
       base_dir = _grit_output_dir
 
-      # This needs to get outputs from grit's internal target, not the final
-      # source_set.
-      inputs = filter_exclude(get_target_outputs(":${_grit_target_name}_grit"),
-                              [ "*.stamp" ])
+      # No need to depend on the source_set().
+      _grit_dep = ":${_grit_target_name}_grit"
+      deps = [ _grit_dep ]
+      inputs = filter_exclude(get_target_outputs(_grit_dep), [ "*.stamp" ])
       output = _resources_zip
-      deps = [ ":$_grit_target_name" ]
     }
 
     android_generated_resources(target_name) {
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py
index 128afff..82e76a98 100644
--- a/tools/json_schema_compiler/cc_generator.py
+++ b/tools/json_schema_compiler/cc_generator.py
@@ -1243,9 +1243,9 @@
     c = Code()
     c.Concat(self._GeneratePropertyFunctions(function_scope, params))
 
-    (c.Sblock('std::vector<base::Value> %(function_scope)s'
+    (c.Sblock('base::Value::List %(function_scope)s'
                   'Create(%(declaration_list)s) {')
-      .Append('std::vector<base::Value> create_results;')
+      .Append('base::Value::List create_results;')
       .Append('create_results.reserve(%d);' % len(params) if len(params)
               else '')
     )
@@ -1254,7 +1254,7 @@
       declaration_list.append(cpp_util.GetParameterDeclaration(
           param, self._type_helper.GetCppType(param.type_)))
       c.Cblock(self._CreateValueFromType(
-          'create_results.push_back(base::Value::FromUniquePtrValue(%s));',
+          'create_results.Append(base::Value::FromUniquePtrValue(%s));',
           param.name,
           param.type_,
           param.unix_name))
diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py
index 97edbfe3..56705ca 100644
--- a/tools/json_schema_compiler/h_generator.py
+++ b/tools/json_schema_compiler/h_generator.py
@@ -441,7 +441,7 @@
         c.Comment(param.description)
       declaration_list.append(cpp_util.GetParameterDeclaration(
           param, self._type_helper.GetCppType(param.type_)))
-    c.Append('std::vector<base::Value> Create(%s);' %
+    c.Append('base::Value::List Create(%s);' %
              ', '.join(declaration_list))
     return c
 
diff --git a/tools/json_schema_compiler/test/additional_properties_unittest.cc b/tools/json_schema_compiler/test/additional_properties_unittest.cc
index fc754d4..8677ea6 100644
--- a/tools/json_schema_compiler/test/additional_properties_unittest.cc
+++ b/tools/json_schema_compiler/test/additional_properties_unittest.cc
@@ -54,12 +54,12 @@
   result_object.integer = 5;
   result_object.additional_properties["key"] = "value";
 
-  std::vector<base::Value> expected;
+  base::Value::List expected;
   {
     base::Value dict(base::Value::Type::DICTIONARY);
     dict.SetIntKey("integer", 5);
     dict.SetStringKey("key", "value");
-    expected.push_back(std::move(dict));
+    expected.Append(std::move(dict));
   }
 
   EXPECT_EQ(expected,
diff --git a/tools/json_schema_compiler/test/crossref_unittest.cc b/tools/json_schema_compiler/test/crossref_unittest.cc
index 0d50682..fa63fdd 100644
--- a/tools/json_schema_compiler/test/crossref_unittest.cc
+++ b/tools/json_schema_compiler/test/crossref_unittest.cc
@@ -79,7 +79,7 @@
   auto test_type = std::make_unique<simple_api::TestType>();
   EXPECT_TRUE(simple_api::TestType::Populate(value, test_type.get()));
 
-  std::vector<base::Value> results =
+  base::Value::List results =
       crossref::GetTestType::Results::Create(*test_type);
   ASSERT_EQ(1u, results.size());
   EXPECT_EQ(value, results[0]);
diff --git a/tools/json_schema_compiler/test/enums_unittest.cc b/tools/json_schema_compiler/test/enums_unittest.cc
index 8312825b..f30d2d3 100644
--- a/tools/json_schema_compiler/test/enums_unittest.cc
+++ b/tools/json_schema_compiler/test/enums_unittest.cc
@@ -40,8 +40,9 @@
     ASSERT_TRUE(params.get());
     EXPECT_EQ(enums::ENUMERATION_ONE, params->enumeration);
 
-    EXPECT_EQ(args, enums::ReturnsEnumAsType::Results::Create(
-                        enums::ENUMERATION_ONE));
+    EXPECT_EQ(
+        base::Value(std::move(args)).GetList(),
+        enums::ReturnsEnumAsType::Results::Create(enums::ENUMERATION_ONE));
   }
   {
     enums::HasEnumeration enumeration;
diff --git a/tools/json_schema_compiler/test/idl_schemas_unittest.cc b/tools/json_schema_compiler/test/idl_schemas_unittest.cc
index 5f5ecdfa..bd43d87c 100644
--- a/tools/json_schema_compiler/test/idl_schemas_unittest.cc
+++ b/tools/json_schema_compiler/test/idl_schemas_unittest.cc
@@ -63,15 +63,15 @@
 
   // Test functions that take a callback function as a parameter, with varying
   // callback signatures.
-  std::vector<base::Value> f4_results(Function4::Results::Create());
-  std::vector<base::Value> expected;
+  base::Value::List f4_results = Function4::Results::Create();
+  base::Value::List expected;
   EXPECT_EQ(expected, f4_results);
 
-  std::vector<base::Value> f5_results(Function5::Results::Create(13));
+  base::Value::List f5_results = Function5::Results::Create(13);
   ASSERT_EQ(1u, f5_results.size());
   EXPECT_TRUE(f5_results[0].is_int());
 
-  std::vector<base::Value> f6_results(Function6::Results::Create(a));
+  base::Value::List f6_results = Function6::Results::Create(a);
   ASSERT_EQ(1u, f6_results.size());
   MyType1 c;
   EXPECT_TRUE(MyType1::Populate(f6_results[0], &c));
diff --git a/tools/json_schema_compiler/test/simple_api_unittest.cc b/tools/json_schema_compiler/test/simple_api_unittest.cc
index d01026f..2ea03d4 100644
--- a/tools/json_schema_compiler/test/simple_api_unittest.cc
+++ b/tools/json_schema_compiler/test/simple_api_unittest.cc
@@ -175,7 +175,7 @@
     std::unique_ptr<base::DictionaryValue> value = CreateTestTypeDictionary();
     auto test_type = std::make_unique<simple_api::TestType>();
     EXPECT_TRUE(simple_api::TestType::Populate(*value, test_type.get()));
-    std::vector<base::Value> results =
+    base::Value::List results =
         simple_api::GetTestType::Results::Create(*test_type);
     ASSERT_EQ(1u, results.size());
     EXPECT_EQ(results[0], *value);
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index d042223..adc660d 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -652,6 +652,8 @@
     'chromium.reclient.fyi': {
       'Linux Builder reclient staging': 'gpu_tests_release_bot_reclient',
       'Linux Builder reclient test': 'gpu_tests_release_bot_reclient',
+      'Mac Builder reclient staging': 'gpu_tests_release_bot_minimal_symbols_reclient',
+      'Mac Builder reclient test': 'gpu_tests_release_bot_minimal_symbols_reclient',
       'Simple Chrome Builder reclient staging': 'chromeos_amd64-generic-vm_use_fake_dbus_clients_reclient',
       'Simple Chrome Builder reclient test': 'chromeos_amd64-generic-vm_use_fake_dbus_clients_reclient',
       'Win x64 Builder reclient staging': 'gpu_tests_release_bot_minimal_symbols_reclient',
diff --git a/tools/mb/mb_config_expectations/chromium.reclient.fyi.json b/tools/mb/mb_config_expectations/chromium.reclient.fyi.json
index cf6bc02..15f84ac 100644
--- a/tools/mb/mb_config_expectations/chromium.reclient.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.reclient.fyi.json
@@ -19,6 +19,28 @@
       "use_remoteexec": true
     }
   },
+  "Mac Builder reclient staging": {
+    "gn_args": {
+      "dcheck_always_on": false,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "use_remoteexec": true
+    }
+  },
+  "Mac Builder reclient test": {
+    "gn_args": {
+      "dcheck_always_on": false,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "symbol_level": 1,
+      "use_remoteexec": true
+    }
+  },
   "Simple Chrome Builder reclient staging": {
     "args_file": "//build/args/chromeos/amd64-generic-vm.gni",
     "gn_args": {
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 4381d81..bef03b4 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -32880,6 +32880,15 @@
   </description>
 </action>
 
+<action name="WebApp.Preinstalled.UninstallByUser">
+  <owner>dibyapal@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <description>
+    The user uninstalled a preinstalled app which was previously not in
+    UserUninstalledPreinstalledWebAppPrefs, and has now been added to the prefs.
+  </description>
+</action>
+
 <action name="WebApp.SetWindowMode.Tab">
   <owner>alancutter@chromium.org</owner>
   <owner>desktop-pwas-team@google.com</owner>
@@ -33488,7 +33497,7 @@
   <suffix name="AddToHomescreenMessage"
       label="For AddToHomescreen IPH feature."/>
   <suffix name="AddToHomescreenTextBubble"
-      label="For AddToHomescreen IPH feature."/>
+      label="For AddToHomescreen IPH feature using text bubble (obsolete)."/>
   <suffix name="AutoDarkOptOut" label="For AutoDarkOptOut dialog feature."/>
   <suffix name="AutoDarkUserEducationMessage"
       label="For AutoDarkUserEducationMessage feature."/>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 30b06b6..3c13709 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -10593,6 +10593,7 @@
   <int value="17" label="EMF_INVALID_EXTENSION_ID_FOR_WORKER_CONTEXT"/>
   <int value="18" label="EMF_INVALID_PORT_CONTEXT"/>
   <int value="19" label="AWCI_INVALID_CALL_FROM_NOT_PRIMARY_MAIN_FRAME"/>
+  <int value="20" label="EFD_INVALID_EXTENSION_ID_FOR_PROCESS"/>
 </enum>
 
 <enum name="BadMessageReasonGuestView">
@@ -27002,6 +27003,18 @@
   <int value="8" label="MP3"/>
 </enum>
 
+<enum name="DownloadBubbleSubpageAction">
+  <int value="0" label="Subpage shown"/>
+  <int value="1" label="Checkbox shown"/>
+  <int value="2" label="First Button shown"/>
+  <int value="3" label="Second Button shown"/>
+  <int value="4" label="Back button pressed"/>
+  <int value="5" label="Subpage closed"/>
+  <int value="6" label="Checkbox clicked"/>
+  <int value="7" label="First button pressed"/>
+  <int value="8" label="Second button pressed"/>
+</enum>
+
 <enum name="DownloadCalendarFileUI">
   <int value="0" label="Warning alert is presented"/>
   <int value="1"
@@ -27790,52 +27803,98 @@
 </enum>
 
 <enum name="DownloadMimeTypeResult">
-  <int value="0" label="Other">MIME type other than those listed below.</int>
-  <int value="1" label="PK pass">application/vnd.apple.pkpass MIME type.</int>
-  <int value="2" label="iOS mobile config">
-    application/x-apple-aspen-config MIME type.
-  </int>
-  <int value="3" label="Zip Archive">application/zip MIME type.</int>
-  <int value="4" label="Microsoft Application (.exe file)">
-    application/x-msdownload MIME type.
-  </int>
-  <int value="5" label="Android Package Archive (.apk file)">
-    application/vnd.android.package-archive MIME type.
-  </int>
-  <int value="6" label="Virtual Contact File">text/vcard MIME type.</int>
-  <int value="7" label="iCalendar">text/calendar MIME type.</int>
-  <int value="8" label="Legacy Universal Scene Description (model/usd)">
-    model/usd MIME type.
-  </int>
-  <int value="9" label="Apple Disk Image">
-    application/x-apple-diskimage MIME type.
-  </int>
-  <int value="10" label="Apple Installer Package">
-    application/vnd.apple.installer+xml MIME type.
-  </int>
-  <int value="11" label="7 Zip Archive">
-    application/x-7z-compressed MIME type.
-  </int>
-  <int value="12" label="RAR Archive">
-    application/x-rar-compressed MIME type.
-  </int>
-  <int value="13" label="Tar Archive">application/x-tar MIME type.</int>
-  <int value="14" label="Adobe Flash">
-    application/x-shockwave-flash MIME type.
-  </int>
-  <int value="15" label="Amazon Kindle eBook">
-    application/vnd.amazon.ebook MIME type.
-  </int>
-  <int value="16" label="Binary Data">application/octet-stream MIME type.</int>
-  <int value="17" label="Bit Torrent">application/x-bittorrent MIME type.</int>
-  <int value="18" label="Java Archive">application/java-archive MIME type.</int>
+  <int value="0" label="Other"/>
+  <int value="1" label="PK pass"/>
+  <int value="2" label="iOS mobile config"/>
+  <int value="3" label="Zip Archive"/>
+  <int value="4" label="Microsoft Application (.exe file)"/>
+  <int value="5" label="Android Package Archive (.apk file)"/>
+  <int value="6" label="Virtual Contact File"/>
+  <int value="7" label="iCalendar"/>
+  <int value="8" label="Legacy Universal Scene Description (model/usd)"/>
+  <int value="9" label="Apple Disk Image"/>
+  <int value="10" label="Apple Installer Package"/>
+  <int value="11" label="7 Zip Archive"/>
+  <int value="12" label="RAR Archive"/>
+  <int value="13" label="Tar Archive"/>
+  <int value="14" label="Adobe Flash"/>
+  <int value="15" label="Amazon Kindle eBook"/>
+  <int value="16" label="Binary Data"/>
+  <int value="17" label="Bit Torrent"/>
+  <int value="18" label="Java Archive"/>
   <int value="19"
-      label="Legacy Pixar Universal Scene Description (model/vnd.pixar.usd)">
-    model/vnd.pixar.usd MIME type.
-  </int>
-  <int value="20" label="Universal Scene Description">
-    model/vnd.usdz+zip MIME type.
-  </int>
+      label="Legacy Pixar Universal Scene Description (model/vnd.pixar.usd)"/>
+  <int value="20" label="Universal Scene Description"/>
+  <int value="21" label="audio/aac"/>
+  <int value="22" label="application/x-abiword"/>
+  <int value="23" label="application/x-freearc"/>
+  <int value="24" label="image/avif"/>
+  <int value="25" label="video/x-msvideo"/>
+  <int value="26" label="image/bmp"/>
+  <int value="27" label="image/x-ms-bmp"/>
+  <int value="28" label="application/x-bzip"/>
+  <int value="29" label="application/x-bzip2"/>
+  <int value="30" label="application/x-cdf"/>
+  <int value="31" label="application/x-csh"/>
+  <int value="32" label="text/css"/>
+  <int value="33" label="text/csv"/>
+  <int value="34" label="application/msword"/>
+  <int value="35"
+      label="application/vnd.openxmlformats-officedocument.wordprocessingml.document"/>
+  <int value="36" label="application/vnd.ms-fontobject"/>
+  <int value="37" label="application/epub+zip"/>
+  <int value="38" label="application/gzip"/>
+  <int value="39" label="image/gif"/>
+  <int value="40" label="text/html"/>
+  <int value="41" label="image/vnd.microsoft.icon"/>
+  <int value="42" label="image/jpeg"/>
+  <int value="43" label="text/javascript"/>
+  <int value="44" label="application/json"/>
+  <int value="45" label="application/ld+json"/>
+  <int value="46" label="audio/midi"/>
+  <int value="47" label="audio/x-midi"/>
+  <int value="48" label="audio/mpeg"/>
+  <int value="49" label="video/mp4"/>
+  <int value="50" label="video/mpeg"/>
+  <int value="51" label="application/vnd.oasis.opendocument.presentation"/>
+  <int value="52" label="application/vnd.oasis.opendocument.spreadsheet"/>
+  <int value="53" label="application/vnd.oasis.opendocument.text"/>
+  <int value="54" label="audio/ogg"/>
+  <int value="55" label="video/ogg"/>
+  <int value="56" label="application/ogg"/>
+  <int value="57" label="audio/opus"/>
+  <int value="58" label="font/otf"/>
+  <int value="59" label="image/png"/>
+  <int value="60" label="application/pdf"/>
+  <int value="61" label="application/x-httpd-php"/>
+  <int value="62" label="application/vnd.ms-powerpoint"/>
+  <int value="63"
+      label="application/vnd.openxmlformats-officedocument.presentationml.presentation"/>
+  <int value="64" label="application/vnd.rar"/>
+  <int value="65" label="application/rtf"/>
+  <int value="66" label="application/x-sh"/>
+  <int value="67" label="image/svg+xml"/>
+  <int value="68" label="image/tiff"/>
+  <int value="69" label="video/mp2t"/>
+  <int value="70" label="font/ttf"/>
+  <int value="71" label="text/plain"/>
+  <int value="72" label="application/vnd.visio"/>
+  <int value="73" label="audio/wav"/>
+  <int value="74" label="audio/webm"/>
+  <int value="75" label="video/webm"/>
+  <int value="76" label="image/webp"/>
+  <int value="77" label="font/woff"/>
+  <int value="78" label="font/woff2"/>
+  <int value="79" label="application/xhtml+xml"/>
+  <int value="80" label="application/vnd.ms-excel"/>
+  <int value="81"
+      label="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"/>
+  <int value="82" label="application/xml"/>
+  <int value="83" label="application/vnd.mozilla.xul+xml"/>
+  <int value="84" label="video/3gpp"/>
+  <int value="85" label="audio/3gpp"/>
+  <int value="86" label="video/3gpp2"/>
+  <int value="87" label="audio/3gpp2"/>
 </enum>
 
 <enum name="DownloadMobileConfigFileUI">
@@ -47850,6 +47909,21 @@
       label="GOOPDATE_E_APP_UPDATE_DISABLED_BY_POLICY_MANUAL"/>
   <int value="-2147219198" label="GOOPDATEINSTALL_E_INSTALLER_FAILED"/>
   <int value="-2147217780" label="DRM_E_P256_ECDSA_SIGNING_ERROR"/>
+  <int value="-2147180543"
+      label="elevation_service::Elevator::kErrorCouldNotObtainCallingProcess"/>
+  <int value="-2147180542"
+      label="elevation_service::Elevator::kErrorCouldNotGenerateValidationData"/>
+  <int value="-2147180541"
+      label="elevation_service::Elevator::kErrorCouldNotDecryptWithUserContext"/>
+  <int value="-2147180540"
+      label="elevation_service::Elevator::kErrorCouldNotDecryptWithSystemContext"/>
+  <int value="-2147180539"
+      label="elevation_service::Elevator::kErrorCouldNotEncryptWithUserContext"/>
+  <int value="-2147180538"
+      label="elevation_service::Elevator::kErrorCouldNotEncryptWithSystemContext"/>
+  <int value="-2147180537"
+      label="elevation_service::Elevator::kValidationDidNotPass"/>
+  <int value="-2147180287" label="os_crypt::kErrorWrongData"/>
   <int value="-2147174250" label="MSPR_E_NO_DECRYPTOR_AVAILABLE"/>
   <int value="-2147172346" label="DRM_E_INVALID_LICENSE"/>
   <int value="-2147172343" label="DRM_E_LICENSEEXPIRED"/>
@@ -49444,6 +49518,14 @@
   <int value="3" label="Incognito switch and forced"/>
 </enum>
 
+<enum name="IncognitoMessageEvent">
+  <int value="0" label="Download message shown"/>
+  <int value="1" label="Download message accepted"/>
+  <int value="2" label="Download message dismissed with gesture"/>
+  <int value="3" label="Download message dismissed with timer"/>
+  <int value="4" label="Download message dismissed with different reason"/>
+</enum>
+
 <enum name="Inconsistencies">
   <int value="1" label="RangeChecksum"/>
   <int value="2" label="BucketOrder"/>
@@ -50187,6 +50269,14 @@
   <int value="1" label="During the running time"/>
 </enum>
 
+<enum name="InstallURLMigrationState">
+  <int value="0"
+      label="install_url migrated from external prefs to web_app DB"/>
+  <int value="1"
+      label="install_url already in sync in between external prefs and
+             web_app DB, no migration happened"/>
+</enum>
+
 <enum name="InstanceIDResult">
   <int value="0" label="Success"/>
   <int value="1" label="Invalid parameter"/>
@@ -56651,6 +56741,7 @@
   <int value="-1034344165" label="V8NoTurbo:disabled"/>
   <int value="-1033738911" label="enable-mac-views-dialogs"/>
   <int value="-1032884201" label="HeavyAdPrivacyMitigations:enabled"/>
+  <int value="-1032265414" label="AutocompleteExtendedSuggestions:disabled"/>
   <int value="-1031350684" label="PdfIsolation:disabled"/>
   <int value="-1030530357" label="PwaInstallUseBottomSheet:disabled"/>
   <int value="-1030513821" label="DetectedSourceLanguageOption:disabled"/>
@@ -57750,6 +57841,8 @@
   <int value="-310908854" label="new-wallpaper-picker"/>
   <int value="-310615515" label="EnableSuggestedFiles:disabled"/>
   <int value="-308793293" label="WebShare:disabled"/>
+  <int value="-308785012"
+      label="QuickIntensiveWakeUpThrottlingAfterLoading:enabled"/>
   <int value="-307260007" label="ExtensionsCheckup:disabled"/>
   <int value="-306935714" label="lite-video-force-override-decision"/>
   <int value="-304951461" label="TextSuggestionsTouchBar:enabled"/>
@@ -58171,6 +58264,8 @@
   <int value="-23090520" label="disable-search-button-in-omnibox"/>
   <int value="-22544408" label="enable-video-player-chromecast-support"/>
   <int value="-22506564" label="OptimizeDataUrls:disabled"/>
+  <int value="-22311932"
+      label="QuickIntensiveWakeUpThrottlingAfterLoading:disabled"/>
   <int value="-20597579" label="UseMultiloginEndpoint:enabled"/>
   <int value="-20438829" label="SyncUSSAutofillProfile:enabled"/>
   <int value="-20329017" label="EduCoexistence:disabled"/>
@@ -58494,6 +58589,7 @@
   <int value="189777537" label="DisableInitialMostVisitedFadeIn:enabled"/>
   <int value="190282969" label="JXL:disabled"/>
   <int value="191737931" label="enable-mark-http-as"/>
+  <int value="191891628" label="AutocompleteExtendedSuggestions:enabled"/>
   <int value="192167036" label="LogJsConsoleMessages:disabled"/>
   <int value="192320180" label="ignore-gpu-blocklist"/>
   <int value="192693676"
@@ -58839,7 +58935,6 @@
   <int value="402630521"
       label="IPH_KeyboardAccessoryPaymentVirtualCard:enabled"/>
   <int value="403288255" label="enable-wheel-scroll-latching"/>
-  <int value="403554154" label="SafetyCheckWeakPasswords:enabled"/>
   <int value="405329388"
       label="FramebustingNeedsSameOriginOrUserGesture:enabled"/>
   <int value="406549604" label="NtpSafeBrowsingModule:enabled"/>
@@ -59292,7 +59387,6 @@
   <int value="700926106" label="OmniboxPedalsBatch3NonEnglish:enabled"/>
   <int value="701766325" label="PerNavigationMojoInterface:enabled"/>
   <int value="701795774" label="WebAppEnableUrlHandlers:enabled"/>
-  <int value="702060507" label="SafetyCheckWeakPasswords:disabled"/>
   <int value="702117246" label="OmniboxSiteSearchStarterPack:disabled"/>
   <int value="703122112" label="ShoppingList:enabled"/>
   <int value="703469777" label="AndroidNightModeTabReparenting:enabled"/>
@@ -59364,7 +59458,6 @@
   <int value="741760108" label="SidePanelPrototype:enabled"/>
   <int value="742083923" label="MimeHandlerViewInCrossProcessFrame:disabled"/>
   <int value="743714331" label="HelpAppLauncherSearch:enabled"/>
-  <int value="744342941" label="SafetyCheckChromeCleanerChild:enabled"/>
   <int value="745541471" label="PaintHolding:disabled"/>
   <int value="745783589" label="translate-force-trigger-on-english"/>
   <int value="745850072" label="FastCheckout:disabled"/>
@@ -59455,7 +59548,6 @@
   <int value="803982925" label="CellularForbidAttachApn:disabled"/>
   <int value="804551127" label="ArcKeyboardShortcutHelperIntegration:disabled"/>
   <int value="804958673" label="LensCameraAssistedSearch:enabled"/>
-  <int value="805882800" label="SafetyCheckChromeCleanerChild:disabled"/>
   <int value="806035639" label="EnableNeuralPalmDetectionFilter:disabled"/>
   <int value="806334184" label="AndroidSpellChecker:enabled"/>
   <int value="806783713" label="DesktopPWAsTabStripLinkCapturing:enabled"/>
@@ -65588,6 +65680,9 @@
   <int value="22" label="SetupAshDirCopyExtensionsFailed"/>
   <int value="23" label="SetupAshDirCopyIndexedDBFailed"/>
   <int value="24" label="SetupAshDirMigrateLevelDBForSyncDataFailed"/>
+  <int value="25" label="SetupAshDirCopyStorageFailed"/>
+  <int value="26" label="MoveSplitItemsToOriginalDirMoveStorageFailed"/>
+  <int value="27" label="MoveLacrosItemsCreateDirFailed"/>
 </enum>
 
 <enum name="MSECodec">
@@ -72330,6 +72425,7 @@
   <int value="7" label="Vpn Details"/>
   <int value="100" label="Bluetooth Devices"/>
   <int value="101" label="Bluetooth Device Details"/>
+  <int value="102" label="Bluetooth Saved Devices"/>
   <int value="200" label="Multi Device Features"/>
   <int value="201" label="Smart Lock"/>
   <int value="202" label="Nearby Share"/>
@@ -72940,20 +73036,6 @@
   </int>
 </enum>
 
-<enum name="PageLifecycleStateTransition">
-  <int value="0" label="Active to hidden and foregrounded"/>
-  <int value="1" label="Active to hidden and backgrounded"/>
-  <int value="2" label="Hidden and foregrounded to active"/>
-  <int value="3" label="Hidden and foregrounded to hidden and backgrounded"/>
-  <int value="4" label="Hidden and foregrounded to frozen"/>
-  <int value="5" label="Hidden and backgrounded to active"/>
-  <int value="6" label="Hidden and backgrounded to hidden and foregrounded"/>
-  <int value="7" label="Hidden and backgrounded to frozen"/>
-  <int value="8" label="Frozen to active"/>
-  <int value="9" label="Frozen to hidden and foregrounded"/>
-  <int value="10" label="Frozen to hidden and backgrounded"/>
-</enum>
-
 <enum name="PageLoadBackForwardCacheEvent">
   <int value="0" label="Enter back-forward cache"/>
   <int value="1" label="Restore from back-forward cache"/>
@@ -76268,6 +76350,14 @@
   <int value="24" label="PIPELINE_ERROR_DISCONNECTED"/>
 </enum>
 
+<enum name="PlaceholderMigrationState">
+  <int value="0"
+      label="is_placeholder field migrated from external prefs to web_app DB"/>
+  <int value="1"
+      label="is_placeholder field is in sync between external_prefs and
+             web_app DB, no migration happened"/>
+</enum>
+
 <enum name="Platform.BootMode.FirmwareWriteProtect">
   <int value="0" label="Off"/>
   <int value="1" label="On"/>
@@ -94874,11 +94964,20 @@
 
 <enum name="TrustedVaultDownloadKeysStatus">
   <int value="0" label="Success"/>
-  <int value="1" label="Member not found or corrupted"/>
+  <int value="1" label="Member not found or corrupted (deprecated)"/>
   <int value="2" label="No new keys"/>
   <int value="3" label="Key proof verification failed"/>
   <int value="4" label="Access token fetching failed"/>
   <int value="5" label="Other error"/>
+  <int value="6" label="Member not found"/>
+  <int value="7" label="Membership not found"/>
+  <int value="8" label="Membership corrupted"/>
+  <int value="9" label="Membership empty"/>
+  <int value="10" label="No primary account"/>
+  <int value="11" label="Device not registered"/>
+  <int value="12" label="Throttled client side"/>
+  <int value="13" label="Corrupted local device registration"/>
+  <int value="14" label="Aborted"/>
 </enum>
 
 <enum name="TrustedVaultFetchKeysAttempt">
@@ -96303,6 +96402,18 @@
   <int value="2" label="Child user changed type to regular"/>
 </enum>
 
+<enum name="UserUninstalledPreinstalledAppMigrationState">
+  <int value="0"
+      label="User uninstalled preinstalled apps migrated due to user
+             uninstalls"/>
+  <int value="1"
+      label="User uninstalled preinstalled apps migrated due to old pref
+             value update"/>
+  <int value="2"
+      label="User uninstalled preinstalled apps already in sync, no migration
+             happened"/>
+</enum>
+
 <enum name="UtilityProcessNameHash">
   <summary>
     The hash of a utility process name generated using `variations::HashName()`.
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml
index 7150682..34f0cdd 100644
--- a/tools/metrics/histograms/metadata/accessibility/histograms.xml
+++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -1214,22 +1214,6 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.LiveCaption.LoadSodaErrorMacOsVersion"
-    units="version" expires_after="2022-12-26">
-  <owner>abigailbklein@google.com</owner>
-  <owner>evliu@google.com</owner>
-  <owner>chrome-a11y-core@google.com</owner>
-  <summary>
-    The MacOS operating system version of the client that failed to load the
-    Speech On-Device API (SODA). Logs the the system's MacOS major and minor
-    version numbers combined into an integer value. For example, for MacOS
-    Sierra this returns 1012, and for MacOS Big Sur it returns 1100. Note that
-    the accuracy returned by this function is as granular as the major version
-    number of Darwin. This is logged once for each media stream if the SODA
-    binary failed to load on MacOS.
-  </summary>
-</histogram>
-
 <histogram name="Accessibility.LiveCaption.LoadSodaResult"
     enum="LoadSodaResult" expires_after="2023-06-13">
   <owner>abigailbklein@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml
index 5757717..a08f344f 100644
--- a/tools/metrics/histograms/metadata/arc/histograms.xml
+++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -1432,7 +1432,7 @@
 </histogram>
 
 <histogram name="Arc.OptInNetworkErrorAction" enum="ArcOptInNetworkErrorAction"
-    expires_after="2022-08-01">
+    expires_after="2023-02-04">
   <owner>mhasank@google.com</owner>
   <owner>arc-core@google.com</owner>
   <summary>
@@ -1699,7 +1699,7 @@
 </histogram>
 
 <histogram name="Arc.Reauthorization.Result{ArcUserTypes}"
-    enum="ArcProvisioningStatus" expires_after="2022-08-04">
+    enum="ArcProvisioningStatus" expires_after="2023-02-04">
   <owner>mhasank@google.com</owner>
   <owner>arc-core@gmail.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index 481d2c1..b9e997f 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -578,6 +578,7 @@
   </summary>
   <token key="TaskStatus">
     <variant name="Cancelled"/>
+    <variant name="MoveLacrosItemsCreateDirFailed"/>
     <variant name="MoveLacrosItemsToNewDirMoveFailed"/>
     <variant name="MoveLacrosItemsToNewDirNoWritePerm"/>
     <variant name="MoveSplitItemsToOriginalDirCreateDirFailed"/>
@@ -3426,6 +3427,26 @@
   </summary>
 </histogram>
 
+<histogram name="Ash.Personalization.KeyboardBacklight.Color.Settled"
+    enum="PersonalizationKeyboardBacklightColor" expires_after="2023-06-15">
+  <owner>jasontt@chromium.org</owner>
+  <owner>assistive-eng@google.com</owner>
+  <summary>
+    Records the keyboard backlight color that the user has settled on. Emitted
+    once for every UMA upload.
+  </summary>
+</histogram>
+
+<histogram name="Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid"
+    enum="BooleanValid" expires_after="2023-06-15">
+  <owner>jasontt@chromium.org</owner>
+  <owner>assistive-eng@google.com</owner>
+  <summary>
+    Emitted when the keyboard backlight is updated to a new wallpaper extracted
+    color. Non transparent colors are considered valid.
+  </summary>
+</histogram>
+
 <histogram name="Ash.Personalization.Path" enum="PersonalizationPath"
     expires_after="2023-04-15">
   <owner>jasontt@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml
index c0a6b60..729cc5c4 100644
--- a/tools/metrics/histograms/metadata/browser/histograms.xml
+++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -119,6 +119,26 @@
   </summary>
 </histogram>
 
+<histogram name="Browser.ERP.EventUploadSizeAdjustment.{Param}" units="bytes"
+    expires_after="2023-06-30">
+  <owner>xuhong@chromium.org</owner>
+  <owner>lbaraz@chromium.org</owner>
+  <owner>cros-reporting-team@google.com</owner>
+  <summary>
+    {Param} informed by the Missive daemon. Updated every time the Missive
+    daemon requests uploading.
+  </summary>
+  <token key="Param">
+    <variant name="MaxUploadSize"
+        summary="The maximum upload size computed based on new events rate
+                 and remaining storage capacity"/>
+    <variant name="NewEventsRate"
+        summary="The size of events enqueued every second"/>
+    <variant name="RemainingStorageCapacity"
+        summary="The remaining storage capacity"/>
+  </token>
+</histogram>
+
 <histogram name="Browser.PaintPreview.Capture.CompressedOnDiskSize" units="KB"
     expires_after="2022-12-11">
   <owner>ckitagawa@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/crostini/histograms.xml b/tools/metrics/histograms/metadata/crostini/histograms.xml
index 9cd626b..662538d 100644
--- a/tools/metrics/histograms/metadata/crostini/histograms.xml
+++ b/tools/metrics/histograms/metadata/crostini/histograms.xml
@@ -259,6 +259,9 @@
 
 <histogram name="Crostini.InstallSource" enum="CrostiniInstallSource"
     expires_after="2023-04-10">
+  <obsolete>
+    Removed in M105 - no longer needed
+  </obsolete>
   <owner>sidereal@google.com</owner>
   <owner>clumptini@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/download/histograms.xml b/tools/metrics/histograms/metadata/download/histograms.xml
index 73c2f88..c04a353 100644
--- a/tools/metrics/histograms/metadata/download/histograms.xml
+++ b/tools/metrics/histograms/metadata/download/histograms.xml
@@ -121,6 +121,18 @@
   <token key="DownloadDangerTypeString" variants="DownloadDangerTypeString"/>
 </histogram>
 
+<histogram name="Download.Bubble.SubpageAction"
+    enum="DownloadBubbleSubpageAction" expires_after="2022-12-14">
+  <owner>bhatiarohit@google.com</owner>
+  <owner>chrome-safebrowsing-alerts@chromium.org</owner>
+  <summary>
+    Record the user actions taken on the Download bubble warning subpage. The
+    warning subpage is shown when the user sees a download warning on the full
+    or the partial view, and navigates to the subpage for more actions. Recorded
+    only for Desktop platforms, where Download Bubble is enabled.
+  </summary>
+</histogram>
+
 <histogram name="Download.Bubble.{DownloadBubbleViewType}View.VisibleTime"
     units="ms" expires_after="2022-10-18">
   <owner>bhatiarohit@google.com</owner>
@@ -361,6 +373,16 @@
   <summary>The count of HTTP Response codes for download requests.</summary>
 </histogram>
 
+<histogram name="Download.Incognito.Message" enum="IncognitoMessageEvent"
+    expires_after="2022-12-31">
+  <owner>tommasin@chromium.org</owner>
+  <owner>chrome-incognito@google.com</owner>
+  <summary>
+    Records the clicks on Incognito download message in Android, when users
+    click download or dismiss the message.
+  </summary>
+</histogram>
+
 <histogram name="Download.InProgressDB.Counts"
     enum="DownloadInProgressDBCountType" expires_after="M83">
   <owner>qinmin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml
index 25faa04..14186690 100644
--- a/tools/metrics/histograms/metadata/extensions/histograms.xml
+++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -2038,6 +2038,20 @@
   </summary>
 </histogram>
 
+<histogram name="Extensions.GuestView.ChangeOwnerWebContentsOnAttach"
+    enum="Boolean" expires_after="2023-02-01">
+  <owner>mcnee@chromium.org</owner>
+  <owner>src/components/guest_view/OWNERS</owner>
+  <summary>
+    It is possible for a Chrome Apps webview to be attached to a WebContents
+    that did not create it. This reports True if attachment involves a change to
+    the owner WebContents or False if attachment does not change the owner.
+
+    We'd like to understand how common this case is, as this is architecturally
+    complex to support.
+  </summary>
+</histogram>
+
 <histogram name="Extensions.HasPermissions_Install3" enum="Boolean"
     expires_after="never">
 <!-- expires-never: Monitoring extension usage. -->
diff --git a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
index e5ceb7ab..9a46c01 100644
--- a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
+++ b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
@@ -38,8 +38,8 @@
       summary="educating users about adding website shortcuts to their home
                screen (using a message UI)"/>
   <variant name="IPH_AddToHomescreenTextBubble"
-      summary="educating users about adding website shortcuts to their home
-               screen (using a text bubble)"/>
+      summary="(obsolete) educating users about adding website shortcuts to
+               their home screen (using a text bubble)"/>
   <variant name="IPH_AutoDarkOptOut"
       summary="educating users about disabling auto dark feature globally"/>
   <variant name="IPH_AutoDarkUserEducationMessage"
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
index d8af1aa4..6e3f849 100644
--- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -1332,22 +1332,6 @@
   <affected-histogram name="PageLoad.Timing2.NavigationToLoadEventFired"/>
 </histogram_suffixes>
 
-<!-- TODO(https://crbug.com/1275800): convert this to patterned histograms -->
-
-<histogram_suffixes
-    name="ComponentUpdater.AndroidComponentLoader.ComponentName" separator=".">
-  <owner>hazems@chromium.org</owner>
-  <owner>src/android_webview/OWNERS</owner>
-  <owner>src/components/component_updater/android/OWNERS</owner>
-  <suffix name="ClientSidePhishing" label=""/>
-  <suffix name="OriginTrials" label=""/>
-  <suffix name="TrustTokenKeyCommitments" label=""/>
-  <suffix name="WebViewAppsPackageNamesAllowlist" label=""/>
-  <suffix name="WebViewEmptyComponent" label=""/>
-  <affected-histogram
-      name="ComponentUpdater.AndroidComponentLoader.LoadStatus"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="CompositorPendingTreeType" separator=".">
   <suffix name="Impl" label="Impl side invalidation initiated pending tree"/>
   <suffix name="Main" label="Commit initiated pending tree"/>
@@ -8361,43 +8345,6 @@
   <affected-histogram name="PLT.BeginToFinish_NormalLoad"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="PurgeAndSuspendExperiment" separator=".">
-  <suffix base="true" name="BlinkGCKB"
-      label="Constrained to the BlinkGC allocator"/>
-  <suffix base="true" name="DiscardableKB"
-      label="Constrained to discardable memory usage"/>
-  <suffix base="true" name="MallocKB" label="Constrained to malloc usage"/>
-  <suffix base="true" name="PartitionAllocKB"
-      label="Constrained to the ParitionAlloc allocator"/>
-  <suffix base="true" name="TotalAllocatedKB"
-      label="Summed over the PartitionAlloc, malloc, discardable memory,
-             mainThreadIsolate() and BlinkGC allocators"/>
-  <suffix base="true" name="V8MainThreadIsolateKB"
-      label="Constrained to memory usage by mainThreadIsolate()"/>
-  <affected-histogram name="PurgeAndSuspend.Experimental.MemoryGrowth"/>
-</histogram_suffixes>
-
-<histogram_suffixes name="PurgeAndSuspendExperimentPerHalfHour" separator=".">
-  <suffix name="30min"
-      label="Constrained to each allocator 30min after purging"/>
-  <suffix name="60min"
-      label="Constrained to each allocator 60min after purging"/>
-  <suffix name="90min"
-      label="Constrained to each allocator 90min after purging"/>
-  <affected-histogram
-      name="PurgeAndSuspend.Experimental.MemoryGrowth.BlinkGCKB"/>
-  <affected-histogram
-      name="PurgeAndSuspend.Experimental.MemoryGrowth.DiscardableKB"/>
-  <affected-histogram
-      name="PurgeAndSuspend.Experimental.MemoryGrowth.MallocKB"/>
-  <affected-histogram
-      name="PurgeAndSuspend.Experimental.MemoryGrowth.PartitionAllocKB"/>
-  <affected-histogram
-      name="PurgeAndSuspend.Experimental.MemoryGrowth.TotalAllocatedKB"/>
-  <affected-histogram
-      name="PurgeAndSuspend.Experimental.MemoryGrowth.V8MainThreadIsolateKB"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="QueryTimeSuffix" separator=".">
   <suffix name="0" label="N = 0"/>
   <suffix name="1" label="N = 1"/>
@@ -8648,51 +8595,6 @@
   <affected-histogram name="Event.Latency.RendererImpl"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="RendererMemoryAllocator" separator=".">
-  <suffix base="true" name="BlinkGC"
-      label="Constrained to the BlinkGC allocator"/>
-  <suffix base="true" name="Discardable"
-      label="Constrained to discardable memory usage"/>
-  <suffix base="true" name="Malloc" label="Constrained to malloc usage"/>
-  <suffix base="true" name="NonDiscardableTotalAllocated"
-      label="Summed over the PartitionAlloc, malloc, mainThreadIsolate() and
-             BlinkGC allocators"/>
-  <suffix base="true" name="PartitionAlloc"
-      label="Constrained to the PartitionAlloc allocator"/>
-  <suffix base="true" name="TotalAllocated"
-      label="Summed over the PartitionAlloc, malloc, discardable memory,
-             mainThreadIsolate() and BlinkGC allocators"/>
-  <suffix base="true" name="TotalAllocatedPerRenderView"
-      label="TotalAllocated divided by the number of RenderViews"/>
-  <suffix base="true" name="V8MainThreadIsolate"
-      label="Constrained to memory usage by mainThreadIsolate()"/>
-  <affected-histogram name="Memory.Experimental.Renderer"/>
-</histogram_suffixes>
-
-<histogram_suffixes name="RendererMemoryTiming" separator=".">
-  <suffix name="AfterBackgrounded.5min"
-      label="Recorded 5 minutes after backgrounded."/>
-  <suffix name="AfterBackgrounded.10min"
-      label="Recorded 10 minutes after backgrounded."/>
-  <suffix name="AfterBackgrounded.15min"
-      label="Recorded 15 minutes after backgrounded."/>
-  <suffix name="DidFinishLoad"
-      label="Recorded each time DidFinishLoad is called for *any* frame
-             within the page."/>
-  <suffix name="MainFrameDidFinishLoad"
-      label="Recorded when DidFinishLoad is called for the main frame."/>
-  <affected-histogram name="Memory.Experimental.Renderer.BlinkGC"/>
-  <affected-histogram name="Memory.Experimental.Renderer.Discardable"/>
-  <affected-histogram name="Memory.Experimental.Renderer.Malloc"/>
-  <affected-histogram
-      name="Memory.Experimental.Renderer.NonDiscardableTotalAllocated"/>
-  <affected-histogram name="Memory.Experimental.Renderer.PartitionAlloc"/>
-  <affected-histogram name="Memory.Experimental.Renderer.TotalAllocated"/>
-  <affected-histogram
-      name="Memory.Experimental.Renderer.TotalAllocatedPerRenderView"/>
-  <affected-histogram name="Memory.Experimental.Renderer.V8MainThreadIsolate"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="RendererScheduler_AfterNthMinuteInBackgroundSplit"
     separator=".">
   <suffix name="Background.AfterFifthMinute"
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index ba706cd..fd48f1a 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -500,7 +500,7 @@
 </histogram>
 
 <histogram name="IOS.FinishedNavigationHasContext" enum="Boolean"
-    expires_after="2019-05-01">
+    expires_after="2023-05-01">
   <owner>gambard@chromium.org</owner>
   <owner>bling-team@google.com</owner>
   <summary>
@@ -514,7 +514,7 @@
 </histogram>
 
 <histogram name="IOS.FinishedNavigationHasItem" enum="Boolean"
-    expires_after="2019-05-01">
+    expires_after="2023-05-01">
   <owner>gambard@chromium.org</owner>
   <owner>bling-team@google.com</owner>
   <summary>
@@ -1127,7 +1127,7 @@
 </histogram>
 
 <histogram name="IOS.PageLoadCount.LoadingStarted" units="units"
-    expires_after="2022-07-30">
+    expires_after="2023-06-30">
   <owner>gambard@chromium.org</owner>
   <owner>bling-team@google.com</owner>
   <summary>
@@ -1652,7 +1652,7 @@
 </histogram>
 
 <histogram name="IOS.Web.URLDidChangeToEmptyURL" enum="BooleanHit"
-    expires_after="2022-07-03">
+    expires_after="2023-07-03">
   <owner>gambard@chromium.org</owner>
   <owner>justincohen@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index 227d26a..e25128f 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -1632,7 +1632,8 @@
   </summary>
 </histogram>
 
-<histogram name="Media.AudioRendererMissedDeadline2.{Duration}.{LatencyTag}"
+<histogram
+    name="Media.AudioRendererMissedDeadline2{Mixing}{Duration}{LatencyTag}"
     units="permille" expires_after="2022-10-04">
   <owner>dalecurtis@chromium.org</owner>
   <owner>olka@chromium.org</owner>
@@ -1642,16 +1643,22 @@
     realtime deadline. Rounded up, clipped to 1/10 of the stream callbacks.
     Sampled when a low-latency output audio stream is destructed.
   </summary>
+  <token key="Mixing">
+    <variant name="" summary="Whole stream lifetime"/>
+    <variant name=".Mixing" summary="During mixing"/>
+  </token>
   <token key="Duration">
-    <variant name="Long" summary="Streams equal or longer than 3000 callbacks"/>
-    <variant name="Short" summary="Streams shorter than 3000 callbacks"/>
+    <variant name=".Long"
+        summary="Streams equal or longer than 3000 callbacks"/>
+    <variant name=".Short" summary="Streams shorter than 3000 callbacks"/>
   </token>
   <token key="LatencyTag">
-    <variant name="LatencyExactMs"/>
-    <variant name="LatencyInteractive"/>
-    <variant name="LatencyPlayback"/>
-    <variant name="LatencyRtc"/>
-    <variant name="LatencyUnknown"/>
+    <variant name="" summary="All latencies combined"/>
+    <variant name=".LatencyExactMs"/>
+    <variant name=".LatencyInteractive"/>
+    <variant name=".LatencyPlayback"/>
+    <variant name=".LatencyRtc"/>
+    <variant name=".LatencyUnknown"/>
   </token>
 </histogram>
 
@@ -2989,7 +2996,7 @@
 </histogram>
 
 <histogram base="true" name="Media.InitialDecoderSelectionTime" units="ms"
-    expires_after="2022-06-25">
+    expires_after="2023-03-25">
   <owner>cassew@google.com</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index a7b7509..33efcb5 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -515,7 +515,7 @@
 </histogram>
 
 <histogram name="Navigation.CodeCacheTime.{CodeCacheType}" units="ms"
-    expires_after="2022-06-15">
+    expires_after="2023-06-15">
   <owner>cduvall@chromium.org</owner>
   <owner>jam@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 4a96c72..ce4f8ce9 100644
--- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -35,7 +35,7 @@
 </histogram>
 
 <histogram name="NewTabPage.ActioniOS" enum="NewTabPageActioniOS"
-    expires_after="2022-06-26">
+    expires_after="2022-12-11">
   <owner>justincohen@chromium.org</owner>
   <owner>gambard@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index 3928c70..c40beb36 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -2817,22 +2817,29 @@
   </summary>
 </histogram>
 
-<histogram name="ComponentUpdater.AndroidComponentLoader.LoadStatus"
-    enum="AndroidComponentLoaderLoadStatus" expires_after="2022-07-01">
-<!-- Name completed by histogram_suffixes
-     name="ComponentUpdater.AndroidComponentLoader.ComponentName" -->
-
+<histogram
+    name="ComponentUpdater.AndroidComponentLoader.LoadStatus.{Component}"
+    units="BooleanSuccess" expires_after="2022-12-15">
   <owner>hazems@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
   <owner>src/components/component_updater/android/OWNERS</owner>
   <summary>
-    Records component loading success, or the failure reason if the component
-    loading fails using the EmbeddedComponentLoader. Note that success here just
-    means that the component has been fetched successfully from the components
-    provider service. However, this doesn't neccessary mean that the component
-    will be then loaded successfully in the system by its respective
+    Records {Component} component loading success, or the failure reason if the
+    component loading fails using the EmbeddedComponentLoader. Note that success
+    here just means that the component has been fetched successfully from the
+    components provider service. However, this doesn't neccessary mean that the
+    component will be then loaded successfully in the system by its respective
     ComponentLoaderPolicy implementation.
   </summary>
+  <token key="Component">
+    <variant name="ClientSidePhishing" summary="ClientSidePhishing"/>
+    <variant name="OriginTrials" summary="OriginTrials"/>
+    <variant name="TrustTokenKeyCommitments"
+        summary="TrustTokenKeyCommitments"/>
+    <variant name="WebViewAppsPackageNamesAllowlist"
+        summary="WebViewAppsPackageNamesAllowlist"/>
+    <variant name="WebViewEmptyComponent" summary="WebViewEmptyComponent"/>
+  </token>
 </histogram>
 
 <histogram name="ComponentUpdater.Calls" enum="ComponentUpdaterCalls"
@@ -8782,6 +8789,76 @@
   </summary>
 </histogram>
 
+<histogram name="OSCrypt.AppBoundEncryption.Decrypt.ResultCode" enum="Hresult"
+    expires_after="M106">
+  <owner>wfh@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>
+    The result code of the application-bound Decrypt operation. This is logged
+    once during browser startup on a background thread for system-level installs
+    on Windows only.
+  </summary>
+</histogram>
+
+<histogram name="OSCrypt.AppBoundEncryption.Decrypt.ResultLastError"
+    enum="WinGetLastError" expires_after="M106">
+  <owner>wfh@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>
+    The GetLastError code for a failed application-bound Decrypt operation. This
+    is logged once during browser startup on a background thread for
+    system-level installs on Windows only, if the call to Decrypt failed.
+  </summary>
+</histogram>
+
+<histogram name="OSCrypt.AppBoundEncryption.Decrypt.Time" units="ms"
+    expires_after="M106">
+  <owner>wfh@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>
+    The amount of time, in ms, that it takes to perform an application-bound
+    Decrypt call. This is logged once during browser startup on a background
+    thread for system-level installs on Windows only.
+  </summary>
+</histogram>
+
+<histogram name="OSCrypt.AppBoundEncryption.Encrypt.ResultCode" enum="Hresult"
+    expires_after="M106">
+  <owner>wfh@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>
+    The result code of the application-bound Encrypt operation. This is logged
+    once during browser startup on a background thread for system-level installs
+    on Windows only, for a client that is initializing a new local state or a
+    previously failing client.
+  </summary>
+</histogram>
+
+<histogram name="OSCrypt.AppBoundEncryption.Encrypt.ResultLastError"
+    enum="WinGetLastError" expires_after="M106">
+  <owner>wfh@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>
+    The GetLastError code for a failed application-bound Encrypt operation. This
+    is logged once during browser startup on a background thread for
+    system-level installs on Windows only, if the call to Encrypt failed, for a
+    client that is initializing a new local state or a previously failing
+    client.
+  </summary>
+</histogram>
+
+<histogram name="OSCrypt.AppBoundEncryption.Encrypt.Time" units="ms"
+    expires_after="M106">
+  <owner>wfh@chromium.org</owner>
+  <owner>nparker@chromium.org</owner>
+  <summary>
+    The amount of time, in ms, that it takes to perform an application-bound
+    Encrypt call. This is logged once during browser startup on a background
+    thread for system-level installs on Windows only, for a client that is
+    initializing a new local state or a previously failing client.
+  </summary>
+</histogram>
+
 <histogram name="OSCrypt.BackendUsage" enum="LinuxPasswordStoreUsage"
     expires_after="2023-01-09">
   <owner>cfroussios@chromium.org</owner>
@@ -10032,44 +10109,6 @@
   </summary>
 </histogram>
 
-<histogram base="true" name="PurgeAndSuspend.Experimental.MemoryGrowth"
-    units="KB" expires_after="M81">
-<!-- Name completed by histogram_suffixes name="PurgeAndSuspendExperiment" -->
-
-  <owner>tasak@google.com</owner>
-  <summary>
-    The growth of the background renderer's memory usage after a background
-    renderer is purged. This is recorded 5, 10 and 15 minutes after the purge.
-  </summary>
-</histogram>
-
-<histogram name="PurgeAndSuspend.Experimental.TimeToFirstActivePaint"
-    units="ms" expires_after="M81">
-  <obsolete>
-    Removed 2020-10.
-  </obsolete>
-  <owner>tasak@google.com</owner>
-  <summary>
-    Time elapsed from when the backgrounded and purged renderer is foregrounded
-    until the renderer is painted. This is recorded every time the backgrounded
-    and purged renderer is foregrounded.
-  </summary>
-</histogram>
-
-<histogram
-    name="PurgeAndSuspend.Experimental.TimeToFirstActivePaint.AfterBackgrounded.5min"
-    units="ms" expires_after="M81">
-  <obsolete>
-    Removed 2020-10.
-  </obsolete>
-  <owner>tasak@google.com</owner>
-  <summary>
-    Time elapsed from when the renderer, which is kept backgrounded for more
-    than 5 minutes, is foregrounded until the renderer is painted. This is
-    recorded every time such renderer is foregrounded.
-  </summary>
-</histogram>
-
 <histogram name="PushMessaging.BackgroundBudget" units="units"
     expires_after="2018-08-30">
   <owner>peter@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index b970935..b87f4ad4 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -2766,20 +2766,6 @@
   </summary>
 </histogram>
 
-<histogram name="PageScheduler.PageLifecycleStateTransition"
-    enum="PageLifecycleStateTransition" expires_after="M81">
-  <owner>panicker@chromium.org</owner>
-  <summary>
-    Tracks the transitions of the page between the various PageLifecycleStates:
-    active, hidden/backgrounded, hidden/foregrounded, and frozen. A page is
-    considered active if is visible. A page is considered backgrounded if not
-    visible and not currently providing a useful service, such as playing audio.
-    A page is considered foregrounded if it is not backgrounded. A page can be
-    frozen due to being hidden/backgrounded for a specified amount of time, or
-    frozen due to critical resources.
-  </summary>
-</histogram>
-
 <histogram
     name="PageSerialization.MhtmlGeneration.BrowserWaitForRendererTime.FrameTree"
     units="ms" expires_after="2020-12-01">
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml
index 07688aa..3b7c51c 100644
--- a/tools/metrics/histograms/metadata/permissions/histograms.xml
+++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -464,7 +464,7 @@
 
 <histogram
     name="Permissions.OnDevicePredictionService.Response.{PermissionType}"
-    enum="BooleanIgnored" expires_after="2022-06-19">
+    enum="BooleanIgnored" expires_after="2023-06-19">
   <owner>ravjit@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -517,7 +517,7 @@
 </histogram>
 
 <histogram name="Permissions.PredictionService.Response.{PermissionType}"
-    enum="BooleanIgnored" expires_after="2022-06-19">
+    enum="BooleanIgnored" expires_after="2023-06-19">
   <owner>ravjit@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/phonehub/histograms.xml b/tools/metrics/histograms/metadata/phonehub/histograms.xml
index c4be584..8a46ad43 100644
--- a/tools/metrics/histograms/metadata/phonehub/histograms.xml
+++ b/tools/metrics/histograms/metadata/phonehub/histograms.xml
@@ -45,8 +45,8 @@
   <summary>The steady state feature status of PhoneHub on user login.</summary>
 </histogram>
 
-<histogram name="PhoneHub.BubbleOpened.Connectable.Screen"
-    enum="PhoneHubScreen" expires_after="2023-02-01">
+<histogram name="PhoneHub.BubbleOpened.Connectable.Page" enum="PhoneHubScreen"
+    expires_after="2023-02-01">
   <owner>jonmann@chromium.org</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml
index 0cc0434d..e058564 100644
--- a/tools/metrics/histograms/metadata/power/histograms.xml
+++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -695,6 +695,20 @@
   <token key="UsageScenario" variants="UsageScenario"/>
 </histogram>
 
+<histogram name="Power.BatteryDischargeRateWhileHibernated" units="mW"
+    expires_after="2023-06-15">
+  <owner>puthik@chromium.org</owner>
+  <owner>evgreen@chromium.org</owner>
+  <owner>chromeos-platform-power@google.com</owner>
+  <summary>
+    Chrome OS battery discharge rate in mW while the system was hibernated,
+    sampled at resume. Only reported if the system was on battery power both
+    before hibernating and after resuming, if the energy level didn't increase
+    while hibernated (which would indicate that an AC adapter was connected),
+    and if the system was hibernated for at least a minute.
+  </summary>
+</histogram>
+
 <histogram name="Power.BatteryDischargeRateWhileSuspended" units="mW"
     expires_after="2023-05-12">
   <owner>puthik@chromium.org</owner>
@@ -1402,6 +1416,35 @@
   </token>
 </histogram>
 
+<histogram name="Power.HibernateAttemptsBeforeCancel" units="units"
+    expires_after="2023-06-15">
+  <owner>puthik@chromium.org</owner>
+  <owner>evgreen@chromium.org</owner>
+  <owner>chromeos-platform-power@google.com</owner>
+  <summary>
+    The number of hibernate attempts performed for a single hibernate request
+    (e.g. triggered by transition from suspend to hibernation) that was
+    eventually canceled on Chrome OS. This also includes requests that were
+    canceled due to the system eventually shutting down due to repeated
+    hibernation failures. This is recorded just after the SuspendDone signal is
+    emitted, while cleaning up from the canceled attempt.
+  </summary>
+</histogram>
+
+<histogram name="Power.HibernateAttemptsBeforeSuccess" units="units"
+    expires_after="2023-06-15">
+  <owner>puthik@chromium.org</owner>
+  <owner>evgreen@chromium.org</owner>
+  <owner>chromeos-platform-power@google.com</owner>
+  <summary>
+    The number of hibernation attempts performed for a single hibernation
+    request (e.g. triggered by transition from suspend to hibernation) that
+    eventually succeeded on Chrome OS. This includes the successful attempt.
+    This is recorded after the system resumes, just after the SuspendDone signal
+    is emitted, while unwinding the suspend preparations.
+  </summary>
+</histogram>
+
 <histogram name="Power.IdleCpuLoad.{ProcessType}" units="%"
     expires_after="2022-10-04">
   <owner>eseckler@chromium.org</owner>
@@ -1865,7 +1908,9 @@
     The number of suspend attempts performed for a single suspend request (e.g.
     triggered by the lid being closed) that was eventually canceled on Chrome
     OS. This also includes requests that were canceled due to the system
-    eventually shutting down due to repeated suspend failures.
+    eventually shutting down due to repeated suspend failures. This is recorded
+    just after the SuspendDone signal is emitted, while cleaning up from the
+    canceled attempt.
   </summary>
 </histogram>
 
@@ -1876,7 +1921,9 @@
   <summary>
     The number of suspend attempts performed for a single suspend request (e.g.
     triggered by the lid being closed) that eventually succeeded on Chrome OS.
-    This includes the successful attempt.
+    This includes the successful attempt. This is recorded after the system
+    resumes, just after the SuspendDone signal is emitted, while unwinding the
+    suspend preparations.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/metadata/prefetch/histograms.xml b/tools/metrics/histograms/metadata/prefetch/histograms.xml
index ca942390..013023a 100644
--- a/tools/metrics/histograms/metadata/prefetch/histograms.xml
+++ b/tools/metrics/histograms/metadata/prefetch/histograms.xml
@@ -28,10 +28,10 @@
 </variants>
 
 <histogram name="PrefetchProxy.AfterClick.Mainframe.CookieWaitTime" units="ms"
-    expires_after="2022-11-13">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the amount of time that the navigation to a previously prefetched
     page was delayed because cookies had to be copied from the isolated cookie
@@ -41,9 +41,9 @@
 
 <histogram name="PrefetchProxy.AfterClick.Subresources.UsedCache"
     enum="BooleanCacheHit" expires_after="2021-12-26">
-  <owner>robertogden@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records whether a previously prefetched subresource from an Isolated
     Prerender was served from cache when its page was later navigated to.
@@ -53,7 +53,7 @@
 <histogram
     name="PrefetchProxy.CanaryChecker.CacheEntryAge.{PrefetchProxyCanaryCheckerClient}"
     units="hours" expires_after="2023-04-25">
-  <owner>spelchat@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
     How old a cached probe result was when it was used, in hours.
@@ -65,7 +65,7 @@
 <histogram
     name="PrefetchProxy.CanaryChecker.CacheLookupResult.{PrefetchProxyCanaryCheckerClient}"
     enum="CanaryCheckLookupResult" expires_after="2023-04-25">
-  <owner>spelchat@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>chrome-brapp-loading@google.com</owner>
   <summary>
     Records the status of canary check cache lookups. A sample is recorded every
@@ -80,7 +80,7 @@
 <histogram
     name="PrefetchProxy.CanaryChecker.FinalState.{PrefetchProxyCanaryCheckerClient}"
     enum="BooleanSuccess" expires_after="2023-04-25">
-  <owner>spelchat@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
     Records the end state of a probe just before it goes inactive. This happens
@@ -94,7 +94,7 @@
 <histogram
     name="PrefetchProxy.CanaryChecker.GenerateCacheKey.{PrefetchProxyCanaryCheckerClient}"
     units="ms" expires_after="2023-04-25">
-  <owner>spelchat@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
     Records the amount of time spent generating a cache key for the availability
@@ -108,7 +108,7 @@
 <histogram
     name="PrefetchProxy.CanaryChecker.NetError.{PrefetchProxyCanaryCheckerClient}"
     enum="NetErrorCodes" expires_after="2023-04-25">
-  <owner>spelchat@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
     Records the net error of a completed or timed out probe. Note that if a HTTP
@@ -122,7 +122,7 @@
 <histogram
     name="PrefetchProxy.CanaryChecker.NumAttemptsBeforeSuccess.{PrefetchProxyCanaryCheckerClient}"
     units="count" expires_after="2023-04-25">
-  <owner>spelchat@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
     Records the number of attempts that are made to achieve a successful canary
@@ -139,7 +139,7 @@
 <histogram
     name="PrefetchProxy.CanaryChecker.TimeUntilFailure.{PrefetchProxyCanaryCheckerClient}"
     units="ms" expires_after="2023-04-25">
-  <owner>spelchat@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
     Records the amount of time spent working on a single probe attempt to get to
@@ -152,7 +152,7 @@
 <histogram
     name="PrefetchProxy.CanaryChecker.TimeUntilSuccess.{PrefetchProxyCanaryCheckerClient}"
     units="ms" expires_after="2023-04-25">
-  <owner>spelchat@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
     Records the amount of time spent working on a single probe attempt to get to
@@ -163,10 +163,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Prefetch.Mainframe.BodyLength" units="bytes"
-    expires_after="2022-10-23">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the response body length as cached in memory encountered when
     isolated prefetching a mainframe HTML resource from the Google Search Result
@@ -175,10 +175,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Prefetch.Mainframe.ConnectTime" units="ms"
-    expires_after="2021-06-20">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the time taken to establish a socket connection when isolated
     prefetching a mainframe HTML resource from the Google Search Result Page.
@@ -187,10 +187,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Prefetch.Mainframe.CookiesToCopy" units="count"
-    expires_after="2022-10-23">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the number of cookies that needed to be copied from the prefetch
     navigation to the user's profile after a prefetched link is navigated to.
@@ -198,10 +198,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Prefetch.Mainframe.NetError"
-    enum="NetErrorCodes" expires_after="2021-06-20">
-  <owner>robertogden@chromium.org</owner>
+    enum="NetErrorCodes" expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the Net Error encountered when isolated prefetching a mainframe HTML
     resource from the Google Search Result Page. Recorded for every completed
@@ -210,10 +210,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Prefetch.Mainframe.RespCode"
-    enum="HttpResponseCode" expires_after="2021-06-20">
-  <owner>robertogden@chromium.org</owner>
+    enum="HttpResponseCode" expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the HTTP response code encountered isolated prefetching a mainframe
     HTML resource from the Google Search Result Page. Recorded for non-network
@@ -222,10 +222,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Prefetch.Mainframe.RetryAfter" units="ms"
-    expires_after="2021-06-20">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the duration of a Retry-After header on a 503 response to a
     mainframe prefetch request.
@@ -233,10 +233,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Prefetch.Mainframe.TotalRedirects" units="count"
-    expires_after="2021-06-20">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the total number of redirects encountered while doing all the
     prefetches on an eligible Google Search Result page. Only recorded when at
@@ -245,10 +245,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Prefetch.Mainframe.TotalTime" units="ms"
-    expires_after="2022-10-30">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the total time taken when isolated prefetching a mainframe HTML
     resource from the Google Search Result Page. Recorded for successful
@@ -257,10 +257,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Prefetch.Subresources.NetError"
-    enum="NetErrorCodes" expires_after="2021-12-26">
-  <owner>robertogden@chromium.org</owner>
+    enum="NetErrorCodes" expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the net error encountered when prefetching a single subresource
     during Isolated Prerenders.
@@ -269,9 +269,9 @@
 
 <histogram name="PrefetchProxy.Prefetch.Subresources.Quantity" units="count"
     expires_after="2021-06-20">
-  <owner>robertogden@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the number of subresources that were NoStatePrefetch'd during an
     Isolated Prerender. Recorded once for each page that is NoStatePrefetch'd
@@ -281,9 +281,9 @@
 
 <histogram name="PrefetchProxy.Prefetch.Subresources.RespCode"
     enum="HttpResponseCode" expires_after="2021-06-20">
-  <owner>robertogden@chromium.org</owner>
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the HTTP response code encountered when prefetching a single
     subresource during Isolated Prerenders.
@@ -291,10 +291,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Proxy.Fallback.NetError" enum="NetErrorCodes"
-    expires_after="2021-06-20">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the Net Error encountered when Chrome did a fallback from the
     prefetch proxy. Recorded only on fallbacks.
@@ -302,10 +302,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.Proxy.RespCode" enum="HttpResponseCode"
-    expires_after="2021-06-20">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the HTTP response code encountered when connecting to the prefetch
     proxy CONNECT tunnel. Recorded every time Chrome gets CONNECT tunnel
@@ -314,10 +314,10 @@
 </histogram>
 
 <histogram name="PrefetchProxy.SpareRenderer.CountStartedOnSRP" units="count"
-    expires_after="2022-12-11">
-  <owner>robertogden@chromium.org</owner>
+    expires_after="2023-04-25">
+  <owner>curranmax@chromium.org</owner>
   <owner>ryansturm@chromium.org</owner>
-  <owner>tbansal@chromium.org</owner>
+  <owner>spelchat@chromium.org</owner>
   <summary>
     Records the number of spare renderers that were attempted to be started on
     the SRP, when the feature param is enabled.
@@ -325,7 +325,7 @@
 </histogram>
 
 <histogram name="PrefetchProxy.WasPrefetchTypeStateChangeValid"
-    enum="BooleanSupported" expires_after="2022-06-08">
+    enum="BooleanSupported" expires_after="2023-04-25">
   <owner>curranmax@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
index 563150e..24099f3 100644
--- a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
@@ -132,9 +132,9 @@
     Time difference in days between when a new version of the model from
     optimization guide is available and when the model is initialized in the
     client for a given {SegmentID}. Recorded at startup for each model to
-    identify low values for new users. It can also be recorded during the
-    session when new version of the model was updated.
+    identify low values for new users.
   </summary>
+  <token key="SegmentID" variants="SegmentationModel"/>
 </histogram>
 
 <histogram
diff --git a/tools/metrics/histograms/metadata/stability/histograms.xml b/tools/metrics/histograms/metadata/stability/histograms.xml
index b895b14..fb8ecc59 100644
--- a/tools/metrics/histograms/metadata/stability/histograms.xml
+++ b/tools/metrics/histograms/metadata/stability/histograms.xml
@@ -541,7 +541,7 @@
 </histogram>
 
 <histogram name="Stability.iOS.UTE.TimeBetweenUTEAndNextLaunch" units="ms"
-    expires_after="2022-07-03">
+    expires_after="2023-04-27">
   <owner>michaeldo@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml
index 15e0d613..6df6e29b 100644
--- a/tools/metrics/histograms/metadata/webapps/histograms.xml
+++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -289,6 +289,92 @@
   </summary>
 </histogram>
 
+<histogram name="WebApp.ExternalPrefs.InstallURLMigrationState"
+    enum="InstallURLMigrationState" expires_after="2023-07-15">
+  <owner>dibyapal@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <summary>
+    Records whether the install_urls have been migrated or not because the data
+    is in sync in between the externally installed prefs and the web_app DB.
+    This is always measured on startup before the WebAppProvider subsystems
+    initialize.
+  </summary>
+</histogram>
+
+<histogram name="WebApp.ExternalPrefs.PlaceholderMigrationState"
+    enum="PlaceholderMigrationState" expires_after="2023-07-15">
+  <owner>dibyapal@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <summary>
+    Records whether the is_placeholder field has been migrated or not because
+    the data is in sync in between the externally installed prefs and the
+    web_app DB. This is always measured on startup before the WebAppProvider
+    subsystems initialize.
+  </summary>
+</histogram>
+
+<histogram name="WebApp.ExternalPrefs.PrefDataAbsentDBDataAbsent" units="bool"
+    expires_after="2023-07-15">
+  <owner>dibyapal@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <summary>
+    Records whether the data from external apps is absent both in the external
+    prefs and the web_app DB. This is recorded on startup just before the
+    WebAppProvider system initializes, when no externally installed apps are
+    found on the system.
+  </summary>
+</histogram>
+
+<histogram name="WebApp.ExternalPrefs.PrefDataAbsentDBDataPresent" units="bool"
+    expires_after="2023-07-15">
+  <owner>dibyapal@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <summary>
+    Records whether the data from external apps is absent in the external prefs
+    but exists in the web_app DB. This is recorded on startup just before the
+    WebAppProvider system initializes. This should not happen, because then
+    somewhere the data is out of sync and not being written properly.
+  </summary>
+</histogram>
+
+<histogram name="WebApp.ExternalPrefs.PrefDataPresentDBDataAbsent" units="bool"
+    expires_after="2023-07-15">
+  <owner>dibyapal@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <summary>
+    Records whether the data from external apps is present in the external prefs
+    but is absent in the web_app DB. This is recorded on startup just before the
+    WebAppProvider system initializes. This usually means a system where
+    migration does not happen, and should stop increasing at a point after all
+    systems have been migrated, or should increase slowly.
+  </summary>
+</histogram>
+
+<histogram name="WebApp.ExternalPrefs.PrefDataPresentDBDataPresent"
+    units="bool" expires_after="2023-07-15">
+  <owner>dibyapal@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <summary>
+    Records whether the data from external apps is present both in the external
+    prefs and the web_app DB. This is recorded on startup just before the
+    WebAppProvider system initializes. This should always be increasing, and
+    denotes the best case where migration has happened.
+  </summary>
+</histogram>
+
+<histogram
+    name="WebApp.ExternalPrefs.UserUninstalledPreinstalledAppMigrationState"
+    enum="UserUninstalledPreinstalledAppMigrationState"
+    expires_after="2023-07-15">
+  <owner>dibyapal@chromium.org</owner>
+  <owner>desktop-pwas-team@google.com</owner>
+  <summary>
+    Records whether the user uninstalled preinstalled web app data is migrated
+    from the external prefs to the user uninstalled preinstalled prefs. This is
+    always measured on startup before the WebAppProvider subsystems initialize.
+  </summary>
+</histogram>
+
 <histogram name="WebApp.Icon.DownloadedHttpStatusCodeOnCreate"
     enum="HttpResponseCode" expires_after="2024-01-01">
   <owner>alancutter@chromium.org</owner>
diff --git a/tools/perf/contrib/system_health_scroll_jank/system_health_scroll_jank.py b/tools/perf/contrib/system_health_scroll_jank/system_health_scroll_jank.py
index d18bc010..307118e 100644
--- a/tools/perf/contrib/system_health_scroll_jank/system_health_scroll_jank.py
+++ b/tools/perf/contrib/system_health_scroll_jank/system_health_scroll_jank.py
@@ -12,16 +12,16 @@
     'Compositing.Display.DrawToSwapUs',
     'CompositorLatency.TotalLatency',
     'CompositorLatency.Type',
-    'Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin4',
-    'Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin4',
-    'Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin4',
-    'Event.Latency.ScrollUpdate.Wheel.TimeToScrollUpdateSwapBegin4',
     'Event.Latency.ScrollJank',
     'Event.Latency.ScrollUpdate.JankyDuration',
     'Event.Latency.ScrollUpdate.JankyEvents',
     'Event.Latency.ScrollUpdate.TotalDuration',
     'Event.Latency.ScrollUpdate.TotalEvents',
     'Event.Jank.ScrollUpdate.TotalJankyAndNonJankyDuration2',
+    'EventLatency.FirstGestureScrollUpdate.Touchscreen.TotalLatency',
+    'EventLatency.GestureScrollUpdate.Touchscreen.TotalLatency',
+    'EventLatency.FirstGestureScrollUpdate.Wheel.TotalLatency',
+    'EventLatency.GestureScrollUpdate.Wheel.TotalLatency',
     'Graphics.Smoothness.Checkerboarding.TouchScroll',
     'Graphics.Smoothness.Checkerboarding.WheelScroll',
     'Graphics.Smoothness.Jank.Compositor.TouchScroll',
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 9dc950a..1f313eb 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": "87054fb59f5b8043323a2d3e9d7e91e1f46a0e38",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/fb9252f9498fb45f62665a83bfdbe59b39cbccbd/trace_processor_shell.exe"
+            "hash": "9a036613eb5405c4d5f82b39c460d999922624b2",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/0eba417b2c72264fa825dc21067b9adc9b8adf70/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": "8f86d818de0a5224033257321e31d91f4599f7c9",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/3d3f58658fdecc553543e801076e44febf5490b5/trace_processor_shell"
+            "hash": "fc4705a4c9288cdf500d3b34c92e2f3be5c43be6",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/0eba417b2c72264fa825dc21067b9adc9b8adf70/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "e1ad4861384b06d911a65f035317914b8cc975c6",
             "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "2981176e3649eceaf7e13b78bee2cda9d90eafbf",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/fb9252f9498fb45f62665a83bfdbe59b39cbccbd/trace_processor_shell"
+            "hash": "f0dc264508f628e6740790d87f6bb7ad18b66759",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/0eba417b2c72264fa825dc21067b9adc9b8adf70/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/rust/build_rust.py b/tools/rust/build_rust.py
index 7418166..277cab45 100755
--- a/tools/rust/build_rust.py
+++ b/tools/rust/build_rust.py
@@ -45,7 +45,7 @@
 
 from pathlib import Path
 
-# Get variables and helpers from Clang update script
+# Get variables and helpers from Clang update script.
 sys.path.append(
     os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'clang',
                  'scripts'))
@@ -94,265 +94,272 @@
 
 
 def RunCommand(command, env=None, fail_hard=True):
-  print('Running', command)
-  if subprocess.run(command, env=env,
-                    shell=sys.platform == 'win32').returncode == 0:
-    return True
-  print('Failed.')
-  if fail_hard:
-    sys.exit(1)
-  return False
+    print('Running', command)
+    if subprocess.run(command, env=env,
+                      shell=sys.platform == 'win32').returncode == 0:
+        return True
+    print('Failed.')
+    if fail_hard:
+        sys.exit(1)
+    return False
 
 
 def CheckoutRust(commit, dir):
-  # Submodules we must update early since bootstrap wants them before it starts
-  # managing them.
-  force_update_submodules = [
-      'src/tools/rust-analyzer', 'compiler/rustc_codegen_cranelift'
-  ]
+    # Submodules we must update early since bootstrap wants them before it
+    # starts managing them.
+    force_update_submodules = [
+        'src/tools/rust-analyzer', 'compiler/rustc_codegen_cranelift'
+    ]
 
-  # Shared between first checkout and subsequent updates.
-  def UpdateSubmodules():
-    return RunCommand(['git', 'submodule', 'update', '--init', '--recursive'] +
-                      force_update_submodules,
-                      fail_hard=False)
+    # Shared between first checkout and subsequent updates.
+    def UpdateSubmodules():
+        return RunCommand(
+            ['git', 'submodule', 'update', '--init', '--recursive'] +
+            force_update_submodules,
+            fail_hard=False)
 
-  # Try updating the current repo if it exists and has no local diff.
-  if os.path.isdir(dir):
-    os.chdir(dir)
-    # git diff-index --quiet returns success when there is no diff.
-    # Also check that the first commit is reachable.
-    if (RunCommand(['git', 'diff-index', '--quiet', 'HEAD'], fail_hard=False)
-        and RunCommand(['git', 'fetch'], fail_hard=False)
-        and RunCommand(['git', 'checkout', commit], fail_hard=False)
-        and UpdateSubmodules()):
-      return
+    # Try updating the current repo if it exists and has no local diff.
+    if os.path.isdir(dir):
+        os.chdir(dir)
+        # git diff-index --quiet returns success when there is no diff.
+        # Also check that the first commit is reachable.
+        if (RunCommand(['git', 'diff-index', '--quiet', 'HEAD'],
+                       fail_hard=False)
+                and RunCommand(['git', 'fetch'], fail_hard=False)
+                and RunCommand(['git', 'checkout', commit], fail_hard=False)
+                and UpdateSubmodules()):
+            return
 
-    # If we can't use the current repo, delete it.
-    os.chdir(CHROMIUM_DIR)  # Can't remove dir if we're in it.
-    print('Removing %s.' % dir)
-    RmTree(dir)
+        # If we can't use the current repo, delete it.
+        os.chdir(CHROMIUM_DIR)  # Can't remove dir if we're in it.
+        print('Removing %s.' % dir)
+        RmTree(dir)
 
-  clone_cmd = ['git', 'clone', RUST_GIT_URL, dir]
+    clone_cmd = ['git', 'clone', RUST_GIT_URL, dir]
 
-  if RunCommand(clone_cmd, fail_hard=False):
-    os.chdir(dir)
-    if (RunCommand(['git', 'checkout', commit], fail_hard=False)
-        and UpdateSubmodules()):
-      return
+    if RunCommand(clone_cmd, fail_hard=False):
+        os.chdir(dir)
+        if (RunCommand(['git', 'checkout', commit], fail_hard=False)
+                and UpdateSubmodules()):
+            return
 
-  print('CheckoutRust failed.')
-  sys.exit(1)
+    print('CheckoutRust failed.')
+    sys.exit(1)
 
 
 def VerifyStage0JsonHash():
-  hasher = hashlib.sha256()
-  with open(STAGE0_JSON_PATH, 'rb') as input:
-    hasher.update(input.read())
-  actual_hash = hasher.hexdigest()
+    hasher = hashlib.sha256()
+    with open(STAGE0_JSON_PATH, 'rb') as input:
+        hasher.update(input.read())
+    actual_hash = hasher.hexdigest()
 
-  if actual_hash == STAGE0_JSON_SHA256:
-    return
+    if actual_hash == STAGE0_JSON_SHA256:
+        return
 
-  print('src/stage0.json hash is different than expected!')
-  print('Expected hash: ' + STAGE0_JSON_SHA256)
-  print('Actual hash:   ' + actual_hash)
-  sys.exit(1)
+    print('src/stage0.json hash is different than expected!')
+    print('Expected hash: ' + STAGE0_JSON_SHA256)
+    print('Actual hash:   ' + actual_hash)
+    sys.exit(1)
 
 
 def Configure(llvm_libs_root):
-  # Read the config.toml template file...
-  with open(RUST_CONFIG_TEMPLATE_PATH, 'r') as input:
-    template = string.Template(input.read())
+    # Read the config.toml template file...
+    with open(RUST_CONFIG_TEMPLATE_PATH, 'r') as input:
+        template = string.Template(input.read())
 
-  subs = {}
-  subs['INSTALL_DIR'] = RUST_TOOLCHAIN_OUT_DIR
-  subs['LLVM_ROOT'] = llvm_libs_root
-  subs['PACKAGE_VERSION'] = GetPackageVersion()
+    subs = {}
+    subs['INSTALL_DIR'] = RUST_TOOLCHAIN_OUT_DIR
+    subs['LLVM_ROOT'] = llvm_libs_root
+    subs['PACKAGE_VERSION'] = GetPackageVersion()
 
-  # ...and apply substitutions, writing to config.toml in Rust tree.
-  with open(os.path.join(RUST_SRC_DIR, 'config.toml'), 'w') as output:
-    output.write(template.substitute(subs))
+    # ...and apply substitutions, writing to config.toml in Rust tree.
+    with open(os.path.join(RUST_SRC_DIR, 'config.toml'), 'w') as output:
+        output.write(template.substitute(subs))
 
 
 def RunXPy(sub, args, gcc_toolchain_path, verbose):
-  ''' Run x.py, Rust's build script'''
-  clang_path = os.path.join(LLVM_BUILD_DIR, 'bin', 'clang')
-  RUSTENV = collections.defaultdict(str, os.environ)
-  # Cargo normally stores files in $HOME. Override this.
-  RUSTENV['CARGO_HOME'] = CARGO_HOME_DIR
-  RUSTENV['AR'] = os.path.join(LLVM_BUILD_DIR, 'bin', 'llvm-ar')
-  RUSTENV['CC'] = clang_path
-  RUSTENV['CXX'] = os.path.join(LLVM_BUILD_DIR, 'bin', 'clang++')
-  RUSTENV['LD'] = clang_path
-  # We use these flags to avoid linking with the system libstdc++.
-  gcc_toolchain_flag = (f'--gcc-toolchain={gcc_toolchain_path}'
-                        if gcc_toolchain_path else '')
-  # These affect how C/C++ files are compiled, but not Rust libs/exes.
-  RUSTENV['CFLAGS'] += f' {gcc_toolchain_flag}'
-  RUSTENV['CXXFLAGS'] += f' {gcc_toolchain_flag}'
-  RUSTENV['LDFLAGS'] += f' {gcc_toolchain_flag}'
-  # These affect how Rust crates are built. A `-Clink-arg=<foo>` arg passes foo
-  # to the clang invocation used to link.
-  #
-  # TODO(https://crbug.com/1281664): remove --no-gc-sections argument.
-  # Workaround for a bug causing std::env::args() to return an empty list,
-  # making Rust binaries unable to take command line arguments. Fix is landed
-  # upstream in LLVM but hasn't rolled into Chromium. Also see:
-  # * https://github.com/rust-lang/rust/issues/92181
-  # * https://reviews.llvm.org/D116528
-  RUSTENV['RUSTFLAGS_BOOTSTRAP'] = (
-      f'-Clinker={clang_path} -Clink-arg=-fuse-ld=lld '
-      f'-Clink-arg=-Wl,--no-gc-sections -Clink-arg={gcc_toolchain_flag} '
-      f'-L native={gcc_toolchain_path}/lib64')
-  RUSTENV['RUSTFLAGS_NOT_BOOTSTRAP'] = RUSTENV['RUSTFLAGS_BOOTSTRAP']
-  os.chdir(RUST_SRC_DIR)
-  cmd = [sys.executable, 'x.py', sub]
-  if verbose and verbose > 0:
-    cmd.append('-' + verbose * 'v')
-  RunCommand(cmd + args, env=RUSTENV)
+    ''' Run x.py, Rust's build script'''
+    clang_path = os.path.join(LLVM_BUILD_DIR, 'bin', 'clang')
+    RUSTENV = collections.defaultdict(str, os.environ)
+    # Cargo normally stores files in $HOME. Override this.
+    RUSTENV['CARGO_HOME'] = CARGO_HOME_DIR
+    RUSTENV['AR'] = os.path.join(LLVM_BUILD_DIR, 'bin', 'llvm-ar')
+    RUSTENV['CC'] = clang_path
+    RUSTENV['CXX'] = os.path.join(LLVM_BUILD_DIR, 'bin', 'clang++')
+    RUSTENV['LD'] = clang_path
+    # We use these flags to avoid linking with the system libstdc++.
+    gcc_toolchain_flag = (f'--gcc-toolchain={gcc_toolchain_path}'
+                          if gcc_toolchain_path else '')
+    # These affect how C/C++ files are compiled, but not Rust libs/exes.
+    RUSTENV['CFLAGS'] += f' {gcc_toolchain_flag}'
+    RUSTENV['CXXFLAGS'] += f' {gcc_toolchain_flag}'
+    RUSTENV['LDFLAGS'] += f' {gcc_toolchain_flag}'
+    # These affect how Rust crates are built. A `-Clink-arg=<foo>` arg passes
+    # foo to the clang invocation used to link.
+    #
+    # TODO(https://crbug.com/1281664): remove --no-gc-sections argument.
+    # Workaround for a bug causing std::env::args() to return an empty list,
+    # making Rust binaries unable to take command line arguments. Fix is landed
+    # upstream in LLVM but hasn't rolled into Chromium. Also see:
+    # * https://github.com/rust-lang/rust/issues/92181
+    # * https://reviews.llvm.org/D116528
+    RUSTENV['RUSTFLAGS_BOOTSTRAP'] = (
+        f'-Clinker={clang_path} -Clink-arg=-fuse-ld=lld '
+        f'-Clink-arg=-Wl,--no-gc-sections -Clink-arg={gcc_toolchain_flag} '
+        f'-L native={gcc_toolchain_path}/lib64')
+    RUSTENV['RUSTFLAGS_NOT_BOOTSTRAP'] = RUSTENV['RUSTFLAGS_BOOTSTRAP']
+    os.chdir(RUST_SRC_DIR)
+    cmd = [sys.executable, 'x.py', sub]
+    if verbose and verbose > 0:
+        cmd.append('-' + verbose * 'v')
+    RunCommand(cmd + args, env=RUSTENV)
 
 
 # Get arguments to run desired test suites, minus disabled tests.
 def GetTestArgs():
-  args = TEST_SUITES
-  for excluded in EXCLUDED_TESTS:
-    args.append('--skip')
-    args.append(excluded)
-  return args
+    args = TEST_SUITES
+    for excluded in EXCLUDED_TESTS:
+        args.append('--skip')
+        args.append(excluded)
+    return args
 
 
 def main():
-  parser = argparse.ArgumentParser(
-      description='Build and package Rust toolchain')
-  parser.add_argument('-v',
-                      '--verbose',
-                      action='count',
-                      help='run subcommands with verbosity')
-  parser.add_argument(
-      '--verify-stage0-hash',
-      action='store_true',
-      help='checkout Rust, verify the stage0 hash, then quit without building. '
-      'Will print the actual hash if different than expected.')
-  parser.add_argument(
-      '--skip-checkout',
-      action='store_true',
-      help='skip Rust git checkout. Useful for trying local changes')
-  parser.add_argument('--skip-clean',
-                      action='store_true',
-                      help='skip x.py clean step')
-  parser.add_argument('--skip-test',
-                      action='store_true',
-                      help='skip running rustc and libstd tests')
-  parser.add_argument('--skip-install',
-                      action='store_true',
-                      help='do not install to RUST_TOOLCHAIN_OUT_DIR')
-  parser.add_argument(
-      '--fetch-llvm-libs',
-      action='store_true',
-      help='fetch Clang/LLVM libs and extract into LLVM_BUILD_DIR. Useless '
-      'without --use-final-llvm-build-dir.')
-  parser.add_argument(
-      '--use-final-llvm-build-dir',
-      action='store_true',
-      help='use libs in LLVM_BUILD_DIR instead of LLVM_BOOTSTRAP_DIR. Useful '
-      'with --fetch-llvm-libs for local builds.')
-  parser.add_argument(
-      '--run-xpy',
-      action='store_true',
-      help='run x.py command in configured Rust checkout. Quits after running '
-      'specified command, skipping all normal build steps. For debugging. '
-      'Running x.py directly will not set the appropriate env variables nor '
-      'update config.toml')
-  args, rest = parser.parse_known_args()
+    parser = argparse.ArgumentParser(
+        description='Build and package Rust toolchain')
+    parser.add_argument('-v',
+                        '--verbose',
+                        action='count',
+                        help='run subcommands with verbosity')
+    parser.add_argument(
+        '--verify-stage0-hash',
+        action='store_true',
+        help=
+        'checkout Rust, verify the stage0 hash, then quit without building. '
+        'Will print the actual hash if different than expected.')
+    parser.add_argument(
+        '--skip-checkout',
+        action='store_true',
+        help='skip Rust git checkout. Useful for trying local changes')
+    parser.add_argument('--skip-clean',
+                        action='store_true',
+                        help='skip x.py clean step')
+    parser.add_argument('--skip-test',
+                        action='store_true',
+                        help='skip running rustc and libstd tests')
+    parser.add_argument('--skip-install',
+                        action='store_true',
+                        help='do not install to RUST_TOOLCHAIN_OUT_DIR')
+    parser.add_argument(
+        '--fetch-llvm-libs',
+        action='store_true',
+        help='fetch Clang/LLVM libs and extract into LLVM_BUILD_DIR. Useless '
+        'without --use-final-llvm-build-dir.')
+    parser.add_argument(
+        '--use-final-llvm-build-dir',
+        action='store_true',
+        help='use libs in LLVM_BUILD_DIR instead of LLVM_BOOTSTRAP_DIR. Useful '
+        'with --fetch-llvm-libs for local builds.')
+    parser.add_argument(
+        '--run-xpy',
+        action='store_true',
+        help='run x.py command in configured Rust checkout. Quits after '
+        'running specified command, skipping all normal build steps. For '
+        'debugging. Running x.py directly will not set the appropriate env '
+        'variables nor update config.toml')
+    args, rest = parser.parse_known_args()
 
-  # Get the LLVM root for libs. We use LLVM_BUILD_DIR tools either way.
-  #
-  # TODO(https://crbug.com/1245714): use LTO libs from LLVM_BUILD_DIR for
-  # stage 2+.
-  if args.use_final_llvm_build_dir:
-    llvm_libs_root = LLVM_BUILD_DIR
-  else:
-    llvm_libs_root = build.LLVM_BOOTSTRAP_DIR
+    # Get the LLVM root for libs. We use LLVM_BUILD_DIR tools either way.
+    #
+    # TODO(https://crbug.com/1245714): use LTO libs from LLVM_BUILD_DIR for
+    # stage 2+.
+    if args.use_final_llvm_build_dir:
+        llvm_libs_root = LLVM_BUILD_DIR
+    else:
+        llvm_libs_root = build.LLVM_BOOTSTRAP_DIR
 
-  if not args.skip_checkout:
-    CheckoutRust(RUST_REVISION, RUST_SRC_DIR)
+    if not args.skip_checkout:
+        CheckoutRust(RUST_REVISION, RUST_SRC_DIR)
 
-  VerifyStage0JsonHash()
-  if args.verify_stage0_hash:
-    # The above function exits and prints the actual hash if verification failed
-    # so we just quit here; if we reach this point, the hash is valid.
-    return 0
+    VerifyStage0JsonHash()
+    if args.verify_stage0_hash:
+        # The above function exits and prints the actual hash if verification
+        # failed so we just quit here; if we reach this point, the hash is
+        # valid.
+        return 0
 
-  if args.fetch_llvm_libs:
-    UpdatePackage('clang-libs', GetDefaultHostOs())
+    if args.fetch_llvm_libs:
+        UpdatePackage('clang-libs', GetDefaultHostOs())
 
-  # Fetch GCC package to build against same libstdc++ as Clang. This function
-  # will only download it if necessary.
-  args.gcc_toolchain = None
-  build.MaybeDownloadHostGcc(args)
+    # Fetch GCC package to build against same libstdc++ as Clang. This function
+    # will only download it if necessary.
+    args.gcc_toolchain = None
+    build.MaybeDownloadHostGcc(args)
 
-  # Set up config.toml in Rust source tree to configure build.
-  Configure(llvm_libs_root)
+    # Set up config.toml in Rust source tree to configure build.
+    Configure(llvm_libs_root)
 
-  if args.run_xpy:
-    if rest[0] == '--':
-      rest = rest[1:]
-    RunXPy(rest[0], rest[1:], args.gcc_toolchain, args.verbose)
-    return 0
-  else:
-    assert not rest
+    if args.run_xpy:
+        if rest[0] == '--':
+            rest = rest[1:]
+        RunXPy(rest[0], rest[1:], args.gcc_toolchain, args.verbose)
+        return 0
+    else:
+        assert not rest
 
-  # Delete vendored sources and .cargo subdir. Otherwise when updating an
-  # existing checkout, vendored sources will not be re-fetched leaving deps out
-  # of date.
-  if not args.skip_checkout:
-    for dir in [os.path.join(RUST_SRC_DIR, d) for d in ['vendor', '.cargo']]:
-      if os.path.exists(dir):
-        shutil.rmtree(dir)
+    # Delete vendored sources and .cargo subdir. Otherwise when updating an
+    # existing checkout, vendored sources will not be re-fetched leaving deps
+    # out of date.
+    if not args.skip_checkout:
+        for dir in [
+                os.path.join(RUST_SRC_DIR, d) for d in ['vendor', '.cargo']
+        ]:
+            if os.path.exists(dir):
+                shutil.rmtree(dir)
 
-  if not args.skip_clean:
-    print('Cleaning build artifacts...')
-    RunXPy('clean', [], args.gcc_toolchain, args.verbose)
+    if not args.skip_clean:
+        print('Cleaning build artifacts...')
+        RunXPy('clean', [], args.gcc_toolchain, args.verbose)
 
-  if not args.skip_test:
-    print('Running stage 2 tests...')
-    # Run a subset of tests. Tell x.py to keep the rustc we already built.
-    RunXPy('test', GetTestArgs(), args.gcc_toolchain, args.verbose)
+    if not args.skip_test:
+        print('Running stage 2 tests...')
+        # Run a subset of tests. Tell x.py to keep the rustc we already built.
+        RunXPy('test', GetTestArgs(), args.gcc_toolchain, args.verbose)
 
-  targets = [
-      'library/proc_macro', 'library/std', 'src/tools/cargo',
-      'src/tools/clippy', 'src/tools/rustfmt'
-  ]
+    targets = [
+        'library/proc_macro', 'library/std', 'src/tools/cargo',
+        'src/tools/clippy', 'src/tools/rustfmt'
+    ]
 
-  # Build stage 2 compiler, tools, and libraries. This should reuse earlier
-  # stages from the test command (if run).
-  print('Building stage 2 artifacts...')
-  RunXPy('build', ['--stage', '2'] + targets, args.gcc_toolchain, args.verbose)
+    # Build stage 2 compiler, tools, and libraries. This should reuse earlier
+    # stages from the test command (if run).
+    print('Building stage 2 artifacts...')
+    RunXPy('build', ['--stage', '2'] + targets, args.gcc_toolchain,
+           args.verbose)
 
-  if args.skip_install:
-    # Rust is fully built. We can quit.
-    return 0
+    if args.skip_install:
+        # Rust is fully built. We can quit.
+        return 0
 
-  print(f'Installing to {RUST_TOOLCHAIN_OUT_DIR} ...')
-  # Clean output directory.
-  if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
-    shutil.rmtree(RUST_TOOLCHAIN_OUT_DIR)
+    print(f'Installing to {RUST_TOOLCHAIN_OUT_DIR} ...')
+    # Clean output directory.
+    if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
+        shutil.rmtree(RUST_TOOLCHAIN_OUT_DIR)
 
-  RunXPy('install', DISTRIBUTION_ARTIFACTS, args.gcc_toolchain, args.verbose)
+    RunXPy('install', DISTRIBUTION_ARTIFACTS, args.gcc_toolchain, args.verbose)
 
-  # Write expected `rustc --version` string to our toolchain directory.
-  with open(RUST_SRC_VERSION_FILE_PATH) as version_file:
-    rust_version = version_file.readline().rstrip()
-  with open(VERSION_STAMP_PATH, 'w') as stamp:
-    stamp.write('rustc %s-dev (%s chromium)\n' %
-                (rust_version, GetPackageVersion()))
+    # Write expected `rustc --version` string to our toolchain directory.
+    with open(RUST_SRC_VERSION_FILE_PATH) as version_file:
+        rust_version = version_file.readline().rstrip()
+    with open(VERSION_STAMP_PATH, 'w') as stamp:
+        stamp.write('rustc %s-dev (%s chromium)\n' %
+                    (rust_version, GetPackageVersion()))
 
-  # x.py installed library sources to our toolchain directory. We also need to
-  # copy the vendor directory so Chromium checkouts have all the deps needed to
-  # build std.
-  shutil.copytree(RUST_SRC_VENDOR_DIR, RUST_TOOLCHAIN_SRC_DIST_VENDOR_DIR)
+    # x.py installed library sources to our toolchain directory. We also need to
+    # copy the vendor directory so Chromium checkouts have all the deps needed
+    # to build std.
+    shutil.copytree(RUST_SRC_VENDOR_DIR, RUST_TOOLCHAIN_SRC_DIST_VENDOR_DIR)
 
 
 if __name__ == '__main__':
-  sys.exit(main())
+    sys.exit(main())
diff --git a/tools/rust/package_rust.py b/tools/rust/package_rust.py
index abffce1d..7aefacbd 100755
--- a/tools/rust/package_rust.py
+++ b/tools/rust/package_rust.py
@@ -25,37 +25,38 @@
 
 
 def main():
-  parser = argparse.ArgumentParser(description='build and package Rust')
-  parser.add_argument('--upload',
-                      action='store_true',
-                      help='upload package to GCS')
-  args = parser.parse_args()
+    parser = argparse.ArgumentParser(description='build and package Rust')
+    parser.add_argument('--upload',
+                        action='store_true',
+                        help='upload package to GCS')
+    args = parser.parse_args()
 
-  # Only build on Linux. Other platforms are currently unsupported.
-  if not sys.platform.startswith('linux'):
-    print('Only Linux is supported!')
-    return 1
+    # Only build on Linux. Other platforms are currently unsupported.
+    if not sys.platform.startswith('linux'):
+        print('Only Linux is supported!')
+        return 1
 
-  gcs_platform = 'Linux_x64'
+    gcs_platform = 'Linux_x64'
 
-  # Clean build output directory
-  if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
-    shutil.rmtree(RUST_TOOLCHAIN_OUT_DIR)
+    # Clean build output directory.
+    if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
+        shutil.rmtree(RUST_TOOLCHAIN_OUT_DIR)
 
-  with open(os.path.join(THIRD_PARTY_DIR, BUILDLOG_NAME), 'w') as log:
-    build_cmd = [sys.executable, os.path.join(THIS_DIR, 'build_rust.py')]
-    TeeCmd(build_cmd, log)
+    with open(os.path.join(THIRD_PARTY_DIR, BUILDLOG_NAME), 'w') as log:
+        build_cmd = [sys.executable, os.path.join(THIS_DIR, 'build_rust.py')]
+        TeeCmd(build_cmd, log)
 
-  with tarfile.open(os.path.join(THIRD_PARTY_DIR, RUST_TOOLCHAIN_PACKAGE_NAME),
-                    'w:gz') as tar:
-    tar.add(RUST_TOOLCHAIN_OUT_DIR, arcname='rust-toolchain')
+    with tarfile.open(
+            os.path.join(THIRD_PARTY_DIR, RUST_TOOLCHAIN_PACKAGE_NAME),
+            'w:gz') as tar:
+        tar.add(RUST_TOOLCHAIN_OUT_DIR, arcname='rust-toolchain')
 
-  os.chdir(THIRD_PARTY_DIR)
-  MaybeUpload(args.upload, RUST_TOOLCHAIN_PACKAGE_NAME, gcs_platform)
-  MaybeUpload(args.upload, BUILDLOG_NAME, gcs_platform)
+    os.chdir(THIRD_PARTY_DIR)
+    MaybeUpload(args.upload, RUST_TOOLCHAIN_PACKAGE_NAME, gcs_platform)
+    MaybeUpload(args.upload, BUILDLOG_NAME, gcs_platform)
 
-  return 0
+    return 0
 
 
 if __name__ == '__main__':
-  sys.exit(main())
+    sys.exit(main())
diff --git a/tools/rust/update_rust.py b/tools/rust/update_rust.py
index 38facd21..1d7a7e7 100755
--- a/tools/rust/update_rust.py
+++ b/tools/rust/update_rust.py
@@ -45,70 +45,73 @@
 
 # Get the target version as specified above.
 def GetPackageVersion():
-  from update import (CLANG_REVISION, CLANG_SUB_REVISION)
-  return '%s-%s-%s-%s' % (RUST_REVISION, RUST_SUB_REVISION, CLANG_REVISION,
-                          CLANG_SUB_REVISION)
+    from update import (CLANG_REVISION, CLANG_SUB_REVISION)
+    return '%s-%s-%s-%s' % (RUST_REVISION, RUST_SUB_REVISION, CLANG_REVISION,
+                            CLANG_SUB_REVISION)
 
 
 # Get the version of the toolchain package we already have.
 def GetStampVersion():
-  if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
-    with open(VERSION_STAMP_PATH) as version_file:
-      existing_stamp = version_file.readline().rstrip()
-    version_re = re.compile(r'rustc [0-9.]+-dev \((.+?) chromium\)')
-    return version_re.fullmatch(existing_stamp).group(1)
+    if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
+        with open(VERSION_STAMP_PATH) as version_file:
+            existing_stamp = version_file.readline().rstrip()
+        version_re = re.compile(r'rustc [0-9.]+-dev \((.+?) chromium\)')
+        return version_re.fullmatch(existing_stamp).group(1)
 
-  return None
+    return None
 
 
 def main():
-  parser = argparse.ArgumentParser(description='Update Rust package')
-  parser.add_argument('--print-rust-revision',
-                      action='store_true',
-                      help='Print Rust revision (without Clang revision) and '
-                      'quit. Can be run outside of a Chromium checkout.')
-  parser.add_argument('--print-package-version',
-                      action='store_true',
-                      help='Print Rust package version (including both the '
-                      'Rust and Clang revisions) and quit.')
-  args = parser.parse_args()
+    parser = argparse.ArgumentParser(description='Update Rust package')
+    parser.add_argument(
+        '--print-rust-revision',
+        action='store_true',
+        help='Print Rust revision (without Clang revision) and '
+        'quit. Can be run outside of a Chromium checkout.')
+    parser.add_argument('--print-package-version',
+                        action='store_true',
+                        help='Print Rust package version (including both the '
+                        'Rust and Clang revisions) and quit.')
+    args = parser.parse_args()
 
-  if args.print_rust_revision:
-    print(f'{RUST_REVISION}-{RUST_SUB_REVISION}')
-    return 0
+    if args.print_rust_revision:
+        print(f'{RUST_REVISION}-{RUST_SUB_REVISION}')
+        return 0
 
-  if args.print_package_version:
-    print(GetPackageVersion())
-    return 0
+    if args.print_package_version:
+        print(GetPackageVersion())
+        return 0
 
-  from update import (DownloadAndUnpack, GetDefaultHostOs, GetPlatformUrlPrefix)
+    from update import (DownloadAndUnpack, GetDefaultHostOs,
+                        GetPlatformUrlPrefix)
 
-  # Exit early if the existing package is up-to-date. Note that we cannot simply
-  # call DownloadAndUnpack() every time: aside from unnecessarily downloading
-  # the toolchain if it hasn't changed, it also leads to multiple versions of
-  # the same rustlibs. build/rust/std/find_std_rlibs.py chokes in this case.
-  if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
-    if GetPackageVersion() == GetStampVersion():
-      return 0
+    # Exit early if the existing package is up-to-date. Note that we cannot
+    # simply call DownloadAndUnpack() every time: aside from unnecessarily
+    # downloading the toolchain if it hasn't changed, it also leads to multiple
+    # versions of the same rustlibs. build/rust/std/find_std_rlibs.py chokes in
+    # this case.
+    if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
+        if GetPackageVersion() == GetStampVersion():
+            return 0
 
-  if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
-    shutil.rmtree(RUST_TOOLCHAIN_OUT_DIR)
+    if os.path.exists(RUST_TOOLCHAIN_OUT_DIR):
+        shutil.rmtree(RUST_TOOLCHAIN_OUT_DIR)
 
-  try:
-    url = '%srust-toolchain-%s.tgz' % (GetPlatformUrlPrefix(
-        GetDefaultHostOs()), GetPackageVersion())
-    DownloadAndUnpack(url, THIRD_PARTY_DIR)
-  except urllib.error.HTTPError as e:
-    # Fail softly for now. This can happen if a Rust package was not produced,
-    # e.g. if the Rust build failed upon a Clang update, or if a Rust roll and
-    # a Clang roll raced against each other.
-    #
-    # TODO(https://crbug.com/1245714): reconsider how to handle this.
-    print(f'warning: could not download Rust package')
+    try:
+        url = '%srust-toolchain-%s.tgz' % (GetPlatformUrlPrefix(
+            GetDefaultHostOs()), GetPackageVersion())
+        DownloadAndUnpack(url, THIRD_PARTY_DIR)
+    except urllib.error.HTTPError as e:
+        # Fail softly for now. This can happen if a Rust package was not
+        # produced, e.g. if the Rust build failed upon a Clang update, or if a
+        # Rust roll and a Clang roll raced against each other.
+        #
+        # TODO(https://crbug.com/1245714): Reconsider how to handle this.
+        print(f'warning: could not download Rust package')
 
-  # Ensure the newly extracted package has the correct version.
-  assert GetPackageVersion() == GetStampVersion()
+    # Ensure the newly extracted package has the correct version.
+    assert GetPackageVersion() == GetStampVersion()
 
 
 if __name__ == '__main__':
-  sys.exit(main())
+    sys.exit(main())
diff --git a/tools/style_variable_generator/base_generator.py b/tools/style_variable_generator/base_generator.py
index dacd1fd..44c8ef9 100644
--- a/tools/style_variable_generator/base_generator.py
+++ b/tools/style_variable_generator/base_generator.py
@@ -45,6 +45,10 @@
         # If specified, only generates the given mode.
         self.generate_single_mode = None
 
+        # If true, resolves all blend() colors to the RGBA values at
+        # compile time.
+        self.resolve_blended_colors = True
+
         # A dictionary of options used to alter generator function. See
         # ./README.md for each generators list of options.
         self.generator_options = {}
@@ -64,7 +68,8 @@
             except ValueError as err:
                 raise ValueError(f'Could not add {path}') from err
 
-        self.model.PostProcess()
+        self.model.PostProcess(
+            resolve_blended_colors=self.resolve_blended_colors)
 
     def AddJSONToModel(self, json_string, in_file=None):
         '''Adds a |json_string| with variable definitions to the model.
diff --git a/tools/style_variable_generator/color_mappings_generator.py b/tools/style_variable_generator/color_mappings_generator.py
new file mode 100644
index 0000000..b5c594d9
--- /dev/null
+++ b/tools/style_variable_generator/color_mappings_generator.py
@@ -0,0 +1,119 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import math
+import os
+import re
+from style_variable_generator.color import Color
+from style_variable_generator.css_generator import CSSStyleGenerator
+from style_variable_generator.model import Modes, VariableType
+
+
+class ColorMappingsStyleGenerator(CSSStyleGenerator):
+    '''Generator for ColorMappings Variables'''
+
+    @staticmethod
+    def GetName():
+        return 'ColorMappings'
+
+    def __init__(self):
+        super().__init__()
+        self.resolve_blended_colors = False
+
+    def GetParameters(self):
+        return {
+            'color_mappings': self._CreateMappings(),
+            'colors': self.model.colors
+        }
+
+    def GetFilters(self):
+        return {
+            'to_color_id_name': self._ToColorIdName,
+            'color_mixer_color': self._ColorMixerColor,
+            'to_css_var_name': self.ToCSSVarName,
+            'cpp_opacity': self._CppOpacity,
+        }
+
+    def GetGlobals(self):
+        globals = {
+            'Modes': Modes,
+            'out_file_path': None,
+            'namespace_name':
+            self.generator_options.get('cpp_namespace', None),
+            'header_file': None,
+            'color_id_start_value':
+            self.generator_options['color_id_start_value'],
+            'in_files': self.GetInputFiles(),
+        }
+        if self.out_file_path:
+            globals['out_file_path'] = self.out_file_path
+            header_file = self.out_file_path.replace(".cc", ".h")
+            header_file = re.sub(r'.*gen/', '', header_file)
+            globals['header_file'] = header_file
+
+        return globals
+
+    def _CreateMappings(self):
+        mappings = collections.defaultdict(list)
+        for name, mode_values in self.model.colors.items():
+            set_name = self.model.variable_map[name].context['ColorMappings'][
+                'set_name']
+            mappings[set_name].append({
+                'name': name,
+                'mode_values': mode_values
+            })
+
+        return mappings
+
+    def _ToColorIdName(self, var_name):
+        return 'k%s' % (re.sub('[_\-\.]', '', var_name.title()))
+
+    def _CppOpacity(self, opacity, mode):
+        return math.floor(255 *
+                          self.model.opacities.ResolveOpacity(opacity, mode).a)
+
+    def _ColorMixerColor(self, c, mode):
+        '''Returns the C++ ColorMappings representation of |c|'''
+        assert (isinstance(c, Color))
+
+        if c.blended_colors:
+            return 'ui::GetResultingPaintColor(%s, %s)' % (
+                self._ColorMixerColor(c.blended_colors[0], mode),
+                self._ColorMixerColor(c.blended_colors[1], mode))
+
+        if c.var:
+            return '{%s}' % self._ToColorIdName(c.var)
+
+        if c.rgb_var:
+            return ('ui::SetAlpha({%s}, 0x%X)' % (self._ToColorIdName(
+                c.RGBVarToVar()), self._CppOpacity(c.opacity, mode)))
+
+        if c.opacity.a != 1:
+            return '{SkColorSetARGB(0x%X, 0x%X, 0x%X, 0x%X)}' % (
+                self._CppOpacity(c.opacity, mode), c.r, c.g, c.b)
+        else:
+            return '{SkColorSetRGB(0x%X, 0x%X, 0x%X)}' % (c.r, c.g, c.b)
+
+
+class ColorMappingsCCStyleGenerator(ColorMappingsStyleGenerator):
+    @staticmethod
+    def GetName():
+        return 'ColorMappingsCC'
+
+    def Render(self):
+        return self.ApplyTemplate(
+            self, 'templates/color_mappings_generator_cc.tmpl',
+            self.GetParameters())
+
+
+class ColorMappingsHStyleGenerator(ColorMappingsStyleGenerator):
+    @staticmethod
+    def GetName():
+        return 'ColorMappingsH'
+
+    def Render(self):
+        return self.ApplyTemplate(self,
+                                  'templates/color_mappings_generator_h.tmpl',
+                                  self.GetParameters())
diff --git a/tools/style_variable_generator/main.py b/tools/style_variable_generator/main.py
index 63b8158b..4521c835 100755
--- a/tools/style_variable_generator/main.py
+++ b/tools/style_variable_generator/main.py
@@ -14,6 +14,7 @@
 from style_variable_generator.proto_generator import ProtoStyleGenerator, ProtoJSONStyleGenerator
 from style_variable_generator.views_generator import ViewsCCStyleGenerator, ViewsHStyleGenerator
 from style_variable_generator.base_generator import Modes
+from style_variable_generator.color_mappings_generator import ColorMappingsCCStyleGenerator, ColorMappingsHStyleGenerator
 
 
 def parseGeneratorOptionList(options):
@@ -33,7 +34,8 @@
 
     generators = [
         CSSStyleGenerator, ViewsCCStyleGenerator, ViewsHStyleGenerator,
-        ProtoStyleGenerator, ProtoJSONStyleGenerator, TSStyleGenerator
+        ProtoStyleGenerator, ProtoJSONStyleGenerator, TSStyleGenerator,
+        ColorMappingsCCStyleGenerator, ColorMappingsHStyleGenerator
     ]
 
     parser.add_argument(
diff --git a/tools/style_variable_generator/model.py b/tools/style_variable_generator/model.py
index b1b3611..dff6b54 100644
--- a/tools/style_variable_generator/model.py
+++ b/tools/style_variable_generator/model.py
@@ -321,13 +321,14 @@
             return f'{namespace}.{name}'
         return name
 
-    def PostProcess(self):
+    def PostProcess(self, resolve_blended_colors=True):
         '''Called after all variables have been added to perform operations that
            require a complete worldview.
         '''
-        # Resolve blended colors after all the files are added because some
-        # color dependencies are between different files.
-        self.colors._ResolveBlendedColors()
+        if resolve_blended_colors:
+            # Resolve blended colors after all the files are added because some
+            # color dependencies are between different files.
+            self.colors._ResolveBlendedColors()
 
         self.Validate()
 
@@ -351,6 +352,18 @@
                 raise ValueError("Cannot find opacity %s referenced by %s" %
                                  (name, referrer))
 
+        def CheckColor(color, name):
+            if color.var:
+                CheckColorReference(color.var, name)
+            if color.rgb_var:
+                CheckColorReference(color.RGBVarToVar(), name)
+            if color.opacity and color.opacity.var:
+                CheckOpacityReference(color.opacity.var, name)
+            if color.blended_colors:
+                assert len(color.blended_colors) == 2
+                CheckColor(color.blended_colors[0], name)
+                CheckColor(color.blended_colors[1], name)
+
         RESERVED_SUFFIXES = ['_' + s for s in Modes.ALL + ['rgb', 'inverted']]
 
         # Check all colors in all modes refer to colors that exist in the
@@ -365,17 +378,9 @@
             if Modes.DEFAULT not in mode_values:
                 raise ValueError("Color %s not defined for default mode" %
                                  name)
+
             for mode, color in mode_values.items():
-                if color.var:
-                    CheckColorReference(color.var, name)
-                if color.rgb_var:
-                    CheckColorReference(color.RGBVarToVar(), name)
-                if color.opacity and color.opacity.var:
-                    CheckOpacityReference(color.opacity.var, name)
-                if color.blended_colors:
-                    assert len(color.blended_colors) == 2
-                    CheckColorReference(color.blended_colors[0], name)
-                    CheckColorReference(color.blended_colors[1], name)
+                CheckColor(color, name)
 
         for name, mode_values in opacities.items():
             for mode, opacity in mode_values.items():
diff --git a/tools/style_variable_generator/style_variable_generator.gni b/tools/style_variable_generator/style_variable_generator.gni
index 7ad4d07..3320fec 100644
--- a/tools/style_variable_generator/style_variable_generator.gni
+++ b/tools/style_variable_generator/style_variable_generator.gni
@@ -62,6 +62,7 @@
                            [
                              "deps",
                              "sources",
+                             "cpp_namespace",
                            ])
 
     inputs =
@@ -78,6 +79,8 @@
     ]
     args = [
              "--generator=ViewsCC",
+             "--generator-option",
+             "cpp_namespace=$cpp_namespace",
              "--out-file",
              rebase_path(out_file_cc, root_build_dir),
              "--generator=ViewsH",
@@ -98,4 +101,54 @@
     ]
     defines = [ "IS_${original_target_name}_IMPL" ]
   }
+
+  if (defined(invoker.color_id_start_value)) {
+    action("${target_name}_color_mappings_generator") {
+      script = script_file
+      forward_variables_from(invoker,
+                             [
+                               "deps",
+                               "sources",
+                               "cpp_namespace",
+                               "color_id_start_value",
+                             ])
+      inputs = common_inputs + [
+                 "//tools/style_variable_generator/color_mappings_generator.py",
+                 "//tools/style_variable_generator/templates/color_mappings_generator_cc.tmpl",
+                 "//tools/style_variable_generator/templates/color_mappings_generator_h.tmpl",
+               ]
+      out_file_cc = "$target_gen_dir/${original_target_name}_color_mappings.cc"
+      out_file_h = "$target_gen_dir/${original_target_name}_color_mappings.h"
+      outputs = [
+        out_file_cc,
+        out_file_h,
+      ]
+      args = [
+               "--generator-option",
+               "cpp_namespace=$cpp_namespace",
+               "--generator-option",
+               "color_id_start_value=$color_id_start_value",
+               "--generator=ColorMappingsCC",
+               "--out-file",
+               rebase_path(out_file_cc, root_build_dir),
+               "--generator=ColorMappingsH",
+               "--out-file",
+               rebase_path(out_file_h, root_build_dir),
+             ] + rebase_path(sources, root_build_dir)
+    }
+
+    component("${target_name}_color_mappings") {
+      sources = [
+        "$target_gen_dir/${original_target_name}_color_mappings.cc",
+        "$target_gen_dir/${original_target_name}_color_mappings.h",
+      ]
+      deps = [
+        ":${original_target_name}_color_mappings_generator",
+        "//base",
+        "//skia",
+        "//ui/color",
+      ]
+      defines = [ "IS_${original_target_name}_COLOR_MAPPINGS_IMPL" ]
+    }
+  }
 }
diff --git a/tools/style_variable_generator/templates/color_mappings_generator_cc.tmpl b/tools/style_variable_generator/templates/color_mappings_generator_cc.tmpl
new file mode 100644
index 0000000..e64499e
--- /dev/null
+++ b/tools/style_variable_generator/templates/color_mappings_generator_cc.tmpl
@@ -0,0 +1,47 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is generated from:
+{%- for path in in_files %}
+//   {{path}}
+{%-  endfor %}
+
+#include "{{header_file}}"
+
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/color/color_mixer.h"
+#include "ui/color/color_recipe.h"
+
+namespace {{namespace_name}} {
+
+{% for set_name, set_colors in color_mappings.items() %}
+void Add{{set_name}}ColorsToMixer(ui::ColorMixer& mixer, bool dark_mode) {
+{%- for obj in set_colors %}
+{%-   if obj.mode_values[Modes.DARK] %}
+  if (dark_mode) {
+    mixer[{{obj.name | to_color_id_name}}] = {{obj.mode_values[Modes.DARK] | color_mixer_color(Modes.DARK)}};
+  } else {
+    mixer[{{obj.name | to_color_id_name}}] = {{obj.mode_values[Modes.LIGHT] | color_mixer_color(Modes.LIGHT)}};
+  }
+{%-    else %}
+  mixer[{{obj.name | to_color_id_name}}] = {{obj.mode_values[Modes.LIGHT] | color_mixer_color(Modes.LIGHT)}};
+{%-    endif %}
+{%-  endfor %}
+}
+
+{% endfor %}
+
+
+std::string ColorIdName(ui::ColorId id) {
+  switch(id) {
+{%- for name in colors.keys() %}
+    case {{name | to_color_id_name}}:
+      return "{{name | to_css_var_name}}";
+{%-  endfor %}
+  }
+  NOTREACHED();
+  return "";
+}
+
+}  // namespace {{namespace_name}}
diff --git a/tools/style_variable_generator/templates/color_mappings_generator_h.tmpl b/tools/style_variable_generator/templates/color_mappings_generator_h.tmpl
new file mode 100644
index 0000000..e3eaa83
--- /dev/null
+++ b/tools/style_variable_generator/templates/color_mappings_generator_h.tmpl
@@ -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.
+
+{%- set header_guard = "%s_"|format(
+        out_file_path|upper|replace("/","_")|replace(".","_")|
+            replace("-", "_")) %}
+
+// This file is generated from:
+{%- for path in in_files %}
+//   {{path}}
+{%-  endfor %}
+
+#ifndef {{header_guard}}
+#define {{header_guard}}
+
+#include "base/component_export.h"
+#include "ui/color/color_id.h"
+
+namespace ui {
+class ColorMixer;
+}
+
+namespace {{namespace_name}} {
+
+#include "ui/color/color_id_macros.inc"
+
+{%- set ns = namespace(start_value=color_id_start_value) -%}
+
+{% for set_name, set_colors in color_mappings.items() %}
+
+
+#define {{set_name | upper}}_COLOR_IDS \
+{% for obj in set_colors %}
+{%- if loop.first -%}
+  E_CPONLY({{obj.name | to_color_id_name}}, k{{set_name}}ColorsStart, k{{set_name}}ColorsStart)
+{%- else -%}
+  E_CPONLY({{obj.name | to_color_id_name}})
+{%- endif %}{%   if not loop.last %} \
+{% endif %}
+{%-  endfor %}
+
+
+enum {{set_name}}ColorIds : ui::ColorId {
+  k{{set_name}}ColorsStart = {{ns.start_value}},
+
+  {{set_name | upper}}_COLOR_IDS
+
+  k{{set_name}}ColorsEnd,
+};
+
+
+COMPONENT_EXPORT({{namespace_name}}_COLOR_MAPPINGS) void Add{{set_name}}ColorsToMixer(ui::ColorMixer& mixer, bool dark_mode);
+
+{%- set ns.start_value = 'k%sColorsEnd' % set_name -%}
+
+{%-  endfor %}
+
+#include "ui/color/color_id_macros.inc"
+
+// clang-format on
+
+
+COMPONENT_EXPORT({{namespace_name}}_COLOR_MAPPINGS) std::string ColorIdName(ui::ColorId id);
+
+}  // namespace {{namespace_name}}
+
+#endif  // {{header_guard}}
diff --git a/tools/style_variable_generator/tests/colors_ref_tokens_test.json5 b/tools/style_variable_generator/tests/colors_ref_tokens_test.json5
index 14f1bceb..e1580b95 100644
--- a/tools/style_variable_generator/tests/colors_ref_tokens_test.json5
+++ b/tools/style_variable_generator/tests/colors_ref_tokens_test.json5
@@ -1,5 +1,10 @@
 {
   token_namespace: 'cros.ref',
+  options: {
+    ColorMappings: {
+      set_name: 'CrosRef'
+    },
+  },
   colors: {
     primary50: "#202124",
   },
diff --git a/tools/style_variable_generator/tests/colors_sys_tokens_test.json5 b/tools/style_variable_generator/tests/colors_sys_tokens_test.json5
index 82b36e66..46e9c8f 100644
--- a/tools/style_variable_generator/tests/colors_sys_tokens_test.json5
+++ b/tools/style_variable_generator/tests/colors_sys_tokens_test.json5
@@ -1,5 +1,10 @@
 {
   token_namespace: 'cros.sys',
+  options: {
+    ColorMappings: {
+      set_name: 'CrosSys'
+    },
+  },
   colors: {
     /* Primary */
     primary: {
diff --git a/tools/style_variable_generator/tests/goldens/colors_tokens_test_color_mappings.cc.generated b/tools/style_variable_generator/tests/goldens/colors_tokens_test_color_mappings.cc.generated
new file mode 100644
index 0000000..5f4b413
--- /dev/null
+++ b/tools/style_variable_generator/tests/goldens/colors_tokens_test_color_mappings.cc.generated
@@ -0,0 +1,66 @@
+// 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.
+
+// This file is generated from:
+//   tests/colors_ref_tokens_test.json5
+//   tests/colors_sys_tokens_test.json5
+
+#include "None"
+
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/color/color_mixer.h"
+#include "ui/color/color_recipe.h"
+
+namespace test_tokens {
+
+
+void AddCrosRefColorsToMixer(ui::ColorMixer& mixer, bool dark_mode) {
+  mixer[kCrosRefPrimary50] = {SkColorSetRGB(0x20, 0x21, 0x24)};
+}
+
+
+void AddCrosSysColorsToMixer(ui::ColorMixer& mixer, bool dark_mode) {
+  if (dark_mode) {
+    mixer[kCrosSysPrimary] = {SkColorSetARGB(0x7F, 0x0, 0x0, 0x0)};
+  } else {
+    mixer[kCrosSysPrimary] = {kCrosRefPrimary50};
+  }
+  if (dark_mode) {
+    mixer[kCrosSysOnPrimary] = {kCrosRefPrimary50};
+  } else {
+    mixer[kCrosSysOnPrimary] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)};
+  }
+  if (dark_mode) {
+    mixer[kCrosSysPrimaryContainer] = ui::SetAlpha({kCrosRefPrimary50}, 0x60);
+  } else {
+    mixer[kCrosSysPrimaryContainer] = ui::SetAlpha({kCrosRefPrimary50}, 0x19);
+  }
+  if (dark_mode) {
+    mixer[kCrosSysOnPrimaryContainer] = ui::GetResultingPaintColor({SkColorSetARGB(0xA, 0xFF, 0xFF, 0xFF)}, {kCrosRefPrimary50});
+  } else {
+    mixer[kCrosSysOnPrimaryContainer] = {SkColorSetRGB(0xFF, 0xFF, 0xFF)};
+  }
+}
+
+
+
+
+std::string ColorIdName(ui::ColorId id) {
+  switch(id) {
+    case kCrosRefPrimary50:
+      return "--cros-ref-primary50";
+    case kCrosSysPrimary:
+      return "--cros-sys-primary";
+    case kCrosSysOnPrimary:
+      return "--cros-sys-on_primary";
+    case kCrosSysPrimaryContainer:
+      return "--cros-sys-primary_container";
+    case kCrosSysOnPrimaryContainer:
+      return "--cros-sys-on_primary_container";
+  }
+  NOTREACHED();
+  return "";
+}
+
+}  // namespace test_tokens
diff --git a/tools/style_variable_generator/tests/goldens/colors_tokens_test_color_mappings.h.generated b/tools/style_variable_generator/tests/goldens/colors_tokens_test_color_mappings.h.generated
new file mode 100644
index 0000000..8523d53
--- /dev/null
+++ b/tools/style_variable_generator/tests/goldens/colors_tokens_test_color_mappings.h.generated
@@ -0,0 +1,67 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is generated from:
+//   tests/colors_ref_tokens_test.json5
+//   tests/colors_sys_tokens_test.json5
+
+#ifndef NONE_
+#define NONE_
+
+#include "base/component_export.h"
+#include "ui/color/color_id.h"
+
+namespace ui {
+class ColorMixer;
+}
+
+namespace test_tokens {
+
+#include "ui/color/color_id_macros.inc"
+
+
+#define CROSREF_COLOR_IDS \
+E_CPONLY(kCrosRefPrimary50, kCrosRefColorsStart, kCrosRefColorsStart)
+
+
+enum CrosRefColorIds : ui::ColorId {
+  kCrosRefColorsStart = 0xF000,
+
+  CROSREF_COLOR_IDS
+
+  kCrosRefColorsEnd,
+};
+
+
+COMPONENT_EXPORT(test_tokens_COLOR_MAPPINGS) void AddCrosRefColorsToMixer(ui::ColorMixer& mixer, bool dark_mode);
+
+
+#define CROSSYS_COLOR_IDS \
+E_CPONLY(kCrosSysPrimary, kCrosSysColorsStart, kCrosSysColorsStart) \
+E_CPONLY(kCrosSysOnPrimary) \
+E_CPONLY(kCrosSysPrimaryContainer) \
+E_CPONLY(kCrosSysOnPrimaryContainer)
+
+
+enum CrosSysColorIds : ui::ColorId {
+  kCrosSysColorsStart = kCrosRefColorsEnd,
+
+  CROSSYS_COLOR_IDS
+
+  kCrosSysColorsEnd,
+};
+
+
+COMPONENT_EXPORT(test_tokens_COLOR_MAPPINGS) void AddCrosSysColorsToMixer(ui::ColorMixer& mixer, bool dark_mode);
+
+#include "ui/color/color_id_macros.inc"
+
+// clang-format on
+
+
+COMPONENT_EXPORT(test_tokens_COLOR_MAPPINGS) std::string ColorIdName(ui::ColorId id);
+
+}  // namespace test_tokens
+
+#endif  // NONE_
diff --git a/tools/style_variable_generator/tests/style_variable_generator_test.py b/tools/style_variable_generator/tests/style_variable_generator_test.py
index 773a19f..7638aee 100755
--- a/tools/style_variable_generator/tests/style_variable_generator_test.py
+++ b/tools/style_variable_generator/tests/style_variable_generator_test.py
@@ -15,6 +15,7 @@
 from style_variable_generator.proto_generator import ProtoStyleGenerator, ProtoJSONStyleGenerator
 from style_variable_generator.views_generator import ViewsHStyleGenerator, ViewsCCStyleGenerator
 from style_variable_generator.ts_generator import TSStyleGenerator
+from style_variable_generator.color_mappings_generator import ColorMappingsHStyleGenerator, ColorMappingsCCStyleGenerator
 import unittest
 
 print(os.path.join(os.path.dirname(__file__)))
@@ -27,12 +28,6 @@
             self.maxDiff = None
             self.assertEqual(value, f.read())
 
-    def testColorTestJSON(self):
-        self.generator.out_file_path = (
-            'tools/style_variable_generator/colors_test_expected.h')
-        self.assertEqualToFile(self.generator.Render(),
-                               self.expected_output_file)
-
     def AddJSONFilesToModel(self, files):
         relpaths_from_cwd = [
             os.path.relpath(os.path.join(os.path.dirname(__file__), f),
@@ -48,6 +43,12 @@
             ['colors_test_palette.json5', 'colors_test.json5'])
         self.expected_output_file = 'colors_test_expected.h.generated'
 
+    def testColorTestJSON(self):
+        self.generator.out_file_path = (
+            'tools/style_variable_generator/colors_test_expected.h')
+        self.assertEqualToFile(self.generator.Render(),
+                               self.expected_output_file)
+
     def testTokenStyleNames(self):
         self.generator = ViewsHStyleGenerator()
         self.AddJSONFilesToModel(
@@ -62,6 +63,12 @@
             ['colors_test_palette.json5', 'colors_test.json5'])
         self.expected_output_file = 'colors_test_expected.cc.generated'
 
+    def testColorTestJSON(self):
+        self.generator.out_file_path = (
+            'tools/style_variable_generator/colors_test_expected.h')
+        self.assertEqualToFile(self.generator.Render(),
+                               self.expected_output_file)
+
     def testTokenStyleNames(self):
         self.generator = ViewsCCStyleGenerator()
         self.AddJSONFilesToModel(
@@ -76,6 +83,10 @@
             ['colors_test_palette.json5', 'colors_test.json5'])
         self.expected_output_file = 'colors_test_expected.css'
 
+    def testColorTestJSON(self):
+        self.assertEqualToFile(self.generator.Render(),
+                               self.expected_output_file)
+
     def testCustomDarkModeSelector(self):
         expected_file_name = 'colors_test_custom_dark_toggle_expected.css'
         self.generator.generator_options = {
@@ -127,6 +138,10 @@
             ['colors_test_palette.json5', 'colors_test.json5'])
         self.expected_output_file = 'colors_test_expected.ts'
 
+    def testColorTestJSON(self):
+        self.assertEqualToFile(self.generator.Render(),
+                               self.expected_output_file)
+
     def testIncludeStyleSheet(self):
         expected_file_name = 'colors_test_include_style_sheet_expected.ts'
         self.generator.generator_options = {'include_style_sheet': 'true'}
@@ -172,6 +187,10 @@
             ['colors_test_palette.json5', 'colors_test.json5'])
         self.expected_output_file = 'colors_test_expected.proto'
 
+    def testColorTestJSON(self):
+        self.assertEqualToFile(self.generator.Render(),
+                               self.expected_output_file)
+
 
 class ProtoJSONStyleGeneratorTest(unittest.TestCase, BaseStyleGeneratorTest):
     def setUp(self):
@@ -186,6 +205,37 @@
         self.AddJSONFilesToModel(paths)
         self.expected_output_file = 'colors_test_expected.protojson'
 
+    def testColorTestJSON(self):
+        self.assertEqualToFile(self.generator.Render(),
+                               self.expected_output_file)
+
+
+class ColorMappingsStyleGeneratorTest(unittest.TestCase,
+                                      BaseStyleGeneratorTest):
+    def setUp(self):
+        self.generator_options = {
+            'cpp_namespace': 'test_tokens',
+            'color_id_start_value': '0xF000'
+        }
+
+    def testColorMappingsCC(self):
+        self.generator = ColorMappingsCCStyleGenerator()
+        self.generator.generator_options = self.generator_options
+        self.AddJSONFilesToModel(
+            ['colors_ref_tokens_test.json5', 'colors_sys_tokens_test.json5'])
+        self.assertEqualToFile(
+            self.generator.Render(),
+            'colors_tokens_test_color_mappings.cc.generated')
+
+    def testColorMappingsH(self):
+        self.generator = ColorMappingsHStyleGenerator()
+        self.generator.generator_options = self.generator_options
+        self.AddJSONFilesToModel(
+            ['colors_ref_tokens_test.json5', 'colors_sys_tokens_test.json5'])
+        self.assertEqualToFile(
+            self.generator.Render(),
+            'colors_tokens_test_color_mappings.h.generated')
+
 
 class BlendStyleGeneratorTest(unittest.TestCase, BaseStyleGeneratorTest):
     def setUp(self):
@@ -194,6 +244,10 @@
             ['colors_test_palette.json5', 'blend_colors_test.json5'])
         self.expected_output_file = 'blend_colors_test_expected.css'
 
+    def testColorTestJSON(self):
+        self.assertEqualToFile(self.generator.Render(),
+                               self.expected_output_file)
+
 
 class InvertedStyleGeneratorTest(unittest.TestCase, BaseStyleGeneratorTest):
     def setUp(self):
@@ -202,6 +256,10 @@
             ['colors_test_palette.json5', 'inverted_colors_test.json5'])
         self.expected_output_file = 'inverted_colors_test_expected.css'
 
+    def testColorTestJSON(self):
+        self.assertEqualToFile(self.generator.Render(),
+                               self.expected_output_file)
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tools/style_variable_generator/views_generator.py b/tools/style_variable_generator/views_generator.py
index be4feff5..95b79a5 100644
--- a/tools/style_variable_generator/views_generator.py
+++ b/tools/style_variable_generator/views_generator.py
@@ -34,17 +34,23 @@
 
     def GetGlobals(self):
         globals = {
-            'Modes': Modes,
-            'out_file_path': None,
-            'namespace_name': None,
-            'header_file': None,
-            'in_files': self.GetInputFiles(),
-            'css_color_var': self.CSSColorVar,
+            'Modes':
+            Modes,
+            'out_file_path':
+            None,
+            'namespace_name':
+            self.generator_options.get(
+                'cpp_namespace',
+                os.path.splitext(os.path.basename(self.out_file_path))[0]),
+            'header_file':
+            None,
+            'in_files':
+            self.GetInputFiles(),
+            'css_color_var':
+            self.CSSColorVar,
         }
         if self.out_file_path:
             globals['out_file_path'] = self.out_file_path
-            globals['namespace_name'] = os.path.splitext(
-                os.path.basename(self.out_file_path))[0]
             header_file = self.out_file_path.replace(".cc", ".h")
             header_file = re.sub(r'.*gen/', '', header_file)
             globals['header_file'] = header_file
diff --git a/tools/visual_debugger/app.html b/tools/visual_debugger/app.html
index d4638bb2..7d89abe 100644
--- a/tools/visual_debugger/app.html
+++ b/tools/visual_debugger/app.html
@@ -138,6 +138,8 @@
       <div class="mdc-button__ripple"></div>
       <span class="mdc-button__label">Disconnect</span>
     </button>
+    <input type="checkbox" id="autoconnect" name="autoconnect" checked="true">
+    <label for="autoconnect" style="font-size:small; font:Roboto" > Autoconnect</label><br>
   </div>
 </div>
 
diff --git a/tools/visual_debugger/connection.js b/tools/visual_debugger/connection.js
index 100b295..ca68c17 100644
--- a/tools/visual_debugger/connection.js
+++ b/tools/visual_debugger/connection.js
@@ -8,92 +8,127 @@
 
 const Connection = {
 
+  getUrl() {
+    var request_error = "";
+    var server_error = "";
+    var url = "";
+    url = document.querySelector('#url').value;
+    if (!url) {
+      var http_requester = new XMLHttpRequest();
+      // Sync request to avoid complexity but is poor form.
+      try {
+        http_requester.open("GET", location.origin + '/discover.html', false);
+        http_requester.send();
+      }
+      catch (req_error) {
+        request_error = "Visual Debugger local server is inaccessible. \n" +
+          "Please launch the server with command:\n " +
+          "    ./launchdebugger {app_port} {remote_port} \n" +
+          " remote_port defaults to 7777 \n" +
+          " corresponds to the chromium command line\n    " +
+          " --remote-debugging-port=7777 \n" +
+          " app_port defaults to 8777. Currently app_port=" + location.port;
+      }
+
+      if (http_requester.status != 200) {
+        server_error = "Server reports error=" + http_requester.responseText;
+      }
+      else {
+        var discover_json = JSON.parse(http_requester.responseText);
+        url = discover_json.webSocketDebuggerUrl;
+      }
+    }
+    const return_strings = [url, request_error, server_error];
+    return return_strings;
+  },
+
+
+  startConnection() {
+    const loop_interval = 3000;
+    const connect_info = this.getUrl();
+    if (connect_info[1] != "") {
+      window.alert(connect_info[1]);
+      return;
+    }
+    if (connect_info[2] != "") {
+      window.alert(connect_info[2]);
+      return;
+    }
+    url = connect_info[0];
+
+    // Create WebSocket connection.
+    this.socket = new WebSocket(url);
+    const status = document.querySelector('#connection-status');
+    const connect = document.querySelector('#connect');
+    const disconnect = document.querySelector('#disconnect');
+
+    this.next_command_id = 1;
+
+    // Connection opened
+    this.socket.addEventListener('open', (event) => {
+      const message = {};
+      message['method'] = 'VisualDebugger.startStream';
+      this.sendMessage(message)
+
+      connect.setAttribute('disabled', true);
+      disconnect.removeAttribute('disabled');
+      status.classList.remove('disconnected');
+    });
+
+    // Listen for messages
+    this.socket.addEventListener('message', (event) => {
+      const json = JSON.parse(event.data);
+      // We now use devtool events so our frame data is packed
+      // into the args of the method.
+      if (json.method === "VisualDebugger.frameResponse") {
+        const frame_json = json.params.frameData;
+        if (frame_json.connection == "ok") {
+          Filter.sendStreamFilters();
+        } else if (frame_json.frame && frame_json.drawcalls) {
+          processIncomingFrame(frame_json);
+        }
+      }
+      else if (json.error) {
+        window.alert("Visual Debugger could not start stream.\n " +
+          "please add 'use_viz_debugger=true' to args.gn");
+        console.log(json.error);
+        this.socket.close();
+      }
+    });
+
+    this.socket.addEventListener('close', () => {
+      connect.removeAttribute('disabled');
+      disconnect.setAttribute('disabled', true);
+      status.classList.add('disconnected');
+      // Checks if connection can be made every
+      // loop_interval number of milliseconds.
+      var testing = function() {
+        var interval = setInterval(function() {
+          if (document.getElementById('autoconnect').checked) {
+            const test_connect = Connection.getUrl();
+            if (test_connect[0] != "") {
+              clearInterval(interval);
+              Connection.startConnection();
+            }
+          }
+        }, loop_interval);
+      }
+      testing();
+    });
+
+    disconnect.addEventListener('click', () => {
+      const message = {};
+      message['method'] = 'VisualDebugger.stopStream';
+      this.sendMessage(message);
+      document.getElementById('autoconnect').checked = false;
+      this.socket.close();
+    });
+  },
+
   initialize() {
     const connect = document.querySelector('#connect');
     connect.addEventListener('click', () => {
-      var url = document.querySelector('#url').value;
-      if (!url) {
-        var http_requester = new XMLHttpRequest();
-        // Sync request to avoid complexity but is poor form.
-        try {
-          http_requester.open("GET", location.origin + '/discover.html', false);
-          http_requester.send(null);
-        }
-        catch (req_error) {
-          window.alert("Visual Debugger local server is inaccessible. \n" +
-            "Please launch the server with command:\n " +
-            "    ./launchdebugger {app_port} {remote_port} \n" +
-            " remote_port defaults to 7777 \n" +
-            " corresponds to the chromium command line\n    " +
-            " --remote-debugging-port=7777 \n" +
-            " app_port defaults to 8777. Currently app_port=" + location.port);
-          console.log(req_error);
-          return;
-        }
-
-        if (http_requester.status != 200) {
-          window.alert("Server reports error=" + http_requester.responseText);
-          return;
-        }
-        else {
-          var discover_json = JSON.parse(http_requester.responseText);
-          // console.log(discover_json);
-          url = discover_json.webSocketDebuggerUrl;
-        }
-      }
-
-      // Create WebSocket connection.
-      this.socket = new WebSocket(url);
-      const status = document.querySelector('#connection-status');
-      const connect = document.querySelector('#connect');
-      const disconnect = document.querySelector('#disconnect');
-
-      this.next_command_id = 1;
-
-      // Connection opened
-      this.socket.addEventListener('open', (event) => {
-        const message = {};
-        message['method'] = 'VisualDebugger.startStream';
-        this.sendMessage(message)
-
-        connect.setAttribute('disabled', true);
-        disconnect.removeAttribute('disabled');
-        status.classList.remove('disconnected');
-      });
-
-      // Listen for messages
-      this.socket.addEventListener('message', (event) => {
-        const json = JSON.parse(event.data);
-        // We now use devtool events so our frame data is packed
-        // into the args of the method.
-        if (json.method === "VisualDebugger.frameResponse") {
-          const frame_json = json.params.frameData;
-          if (frame_json.connection == "ok") {
-            Filter.sendStreamFilters();
-          } else if (frame_json.frame && frame_json.drawcalls) {
-            processIncomingFrame(frame_json);
-          }
-        }
-        else if (json.error) {
-          window.alert("Visual Debugger could not start stream.\n " +
-            "please add 'use_viz_debugger=true' to args.gn");
-          console.log(json.error);
-          this.socket.close();
-        }
-      });
-
-      this.socket.addEventListener('close', () => {
-        connect.removeAttribute('disabled');
-        disconnect.setAttribute('disabled', true);
-        status.classList.add('disconnected');
-      });
-
-      disconnect.addEventListener('click', () => {
-        const message = {};
-        message['method'] = 'VisualDebugger.stopStream';
-        this.sendMessage(message)
-        this.socket.close();
-      });
+      this.startConnection();
     });
   },
 
@@ -103,4 +138,4 @@
     message['id'] = this.next_command_id++;
     this.socket.send(JSON.stringify(message));
   }
-};
+};
\ No newline at end of file
diff --git a/tools/visual_debugger/server.py b/tools/visual_debugger/server.py
index a73520af..7b77e3e 100755
--- a/tools/visual_debugger/server.py
+++ b/tools/visual_debugger/server.py
@@ -35,7 +35,9 @@
             "\n      ssh root@$DUT_IP -L " + \
             str(remote_port)+":localhost:" + str(remote_port)
         contents = bytes(contents, 'UTF-8')
-        self.send_response(400)
+        # Used error code 206 to prevent console logs every time
+        # connection is unsuccessful.
+        self.send_response(206)
 
       self.send_header("Content-type", "text/html")
       self.send_header("Content-length", len(contents))
diff --git a/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java b/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java
index 8b68fa2..0f29c9d 100644
--- a/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java
+++ b/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 
 import androidx.annotation.UiThread;
+import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
@@ -28,7 +29,8 @@
     /**
      * Matches the value set in res/values-sw600dp/values.xml
      */
-    private static final int SCREEN_BUCKET_TABLET = 2;
+    @VisibleForTesting
+    public static final int SCREEN_BUCKET_TABLET = 2;
 
     /**
      * Matches the value set in res/values-sw720dp/values.xml
diff --git a/ui/base/idle/idle_chromeos.cc b/ui/base/idle/idle_chromeos.cc
index f84a0692..8dca08e0 100644
--- a/ui/base/idle/idle_chromeos.cc
+++ b/ui/base/idle/idle_chromeos.cc
@@ -21,7 +21,7 @@
   if (IdleStateForTesting().has_value())
     return IdleStateForTesting().value() == IDLE_STATE_LOCKED;
 
-  return chromeos::SessionManagerClient::Get()->IsScreenLocked();
+  return ash::SessionManagerClient::Get()->IsScreenLocked();
 }
 
 }  // namespace ui
diff --git a/ui/chromeos/strings/network_element_localized_strings_provider.cc b/ui/chromeos/strings/network_element_localized_strings_provider.cc
index 8d0f68f..8f2b834 100644
--- a/ui/chromeos/strings/network_element_localized_strings_provider.cc
+++ b/ui/chromeos/strings/network_element_localized_strings_provider.cc
@@ -460,6 +460,10 @@
       "showHiddenNetworkWarning",
       base::FeatureList::IsEnabled(ash::features::kHiddenNetworkWarning));
 
+  html_source->AddBoolean(
+      "enableHiddenNetworkMigration",
+      base::FeatureList::IsEnabled(ash::features::kHiddenNetworkMigration));
+
   // Login screen and public account users can only create shared network
   // configurations. Other users default to unshared network configurations.
   // NOTE: Guest and kiosk users can only create unshared network configs.
diff --git a/ui/chromeos/styles/BUILD.gn b/ui/chromeos/styles/BUILD.gn
index 8c459f7..4d14fb5d 100644
--- a/ui/chromeos/styles/BUILD.gn
+++ b/ui/chromeos/styles/BUILD.gn
@@ -12,4 +12,19 @@
     "cros_shadows.json5",
     "cros_typography.json5",
   ]
+
+  cpp_namespace = "cros_styles"
+}
+
+style_variable_generator("cros_tokens") {
+  # If you change the sources, also change the paths in presubmit_support.py
+  sources = [
+    "cros_colors.json5",
+    "cros_palette.json5",
+    "cros_ref_colors.json5",
+    "cros_sys_colors.json5",
+  ]
+
+  cpp_namespace = "cros_tokens"
+  color_id_start_value = "0x4000"
 }
diff --git a/ui/chromeos/styles/cros_colors.json5 b/ui/chromeos/styles/cros_colors.json5
index da0bda7..a72cc1aa 100644
--- a/ui/chromeos/styles/cros_colors.json5
+++ b/ui/chromeos/styles/cros_colors.json5
@@ -17,6 +17,9 @@
       field_name: 'cros_colors',
       field_id: 2,
     },
+    ColorMappings: {
+      set_name: 'LegacySemantic'
+    },
   },
   colors: {
     /* =========================================================================
diff --git a/ui/chromeos/styles/cros_palette.json5 b/ui/chromeos/styles/cros_palette.json5
index d80c05c2..9b7502e 100644
--- a/ui/chromeos/styles/cros_palette.json5
+++ b/ui/chromeos/styles/cros_palette.json5
@@ -14,6 +14,9 @@
       field_name: 'palette_colors',
       field_id: 1,
     },
+    ColorMappings: {
+      set_name: 'LegacySemantic'
+    },
   },
   colors: {
     google_blue_50: "#e8f0fe",
diff --git a/ui/chromeos/styles/cros_ref_colors.json5 b/ui/chromeos/styles/cros_ref_colors.json5
index d0d92cc..018e04b 100644
--- a/ui/chromeos/styles/cros_ref_colors.json5
+++ b/ui/chromeos/styles/cros_ref_colors.json5
@@ -12,6 +12,11 @@
  */
 {
   token_namespace: 'cros.ref',
+  options: {
+    ColorMappings: {
+      set_name: 'CrosRef',
+    },
+  },
   colors: {
     primary0: '#000000',
     primary10: '#041e49',
diff --git a/ui/chromeos/styles/cros_sys_colors.json5 b/ui/chromeos/styles/cros_sys_colors.json5
index a6795a9..ee809ea1 100644
--- a/ui/chromeos/styles/cros_sys_colors.json5
+++ b/ui/chromeos/styles/cros_sys_colors.json5
@@ -9,6 +9,11 @@
  */
 {
   token_namespace: 'cros.sys',
+  options: {
+    ColorMappings: {
+      set_name: 'CrosSys',
+    },
+  },
   colors: {
     /* Primary */
     primary: {
diff --git a/ui/chromeos/translations/ui_chromeos_strings_az.xtb b/ui/chromeos/translations/ui_chromeos_strings_az.xtb
index 57ac2fb..ab2cabf 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_az.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_az.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Siyahı görünüşünə keçin</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> qovluq Linux ilə paylaşıldı</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> fayl seçildi</translation>
+<translation id="2387120140441437063">Zibil qutusuna atılan faylları açmaq mümkün deyil. Açmazdan əvvəl faylları bərpa edin.</translation>
 <translation id="2387458720915042159">Proksi bağlantı növü</translation>
 <translation id="2389832672041313158">Birma dili (Myanma)</translation>
 <translation id="2392369802118427583">Aktivləşdirin</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_bs.xtb b/ui/chromeos/translations/ui_chromeos_strings_bs.xtb
index 31c9b14..de134c5 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_bs.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_bs.xtb
@@ -159,7 +159,7 @@
 <translation id="2377319039870049694">Prebaci na prikaz liste</translation>
 <translation id="2377590462528165447">Broj foldera koji se dijele s Linuxom <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2378075407703503998">Broj odabranih fajlova: <ph name="SELCTED_FILE_COUNT" /></translation>
-<translation id="2387120140441437063">Datoteke u otpadu ne mogu se otvoriti. Vratite datoteke prije otvaranja.</translation>
+<translation id="2387120140441437063">Nije moguće otvoriti fajlove premještene u otpad. Vratite fajlove prije otvaranja.</translation>
 <translation id="2387458720915042159">Vrsta veze s proksi serverom</translation>
 <translation id="2389832672041313158">burmanski (Mijanmar)</translation>
 <translation id="2392369802118427583">Aktiviraj</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ca.xtb b/ui/chromeos/translations/ui_chromeos_strings_ca.xtb
index 7b1b00b4..85e3ed37 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ca.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ca.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Canvia a la visualització de llista</translation>
 <translation id="2377590462528165447">S'han compartit <ph name="NUMBER_OF_ITEMS" /> carpetes amb Linux</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> fitxers seleccionats</translation>
+<translation id="2387120140441437063">No es poden obrir els fitxers de la paperera. Restaura els fitxers abans d'obrir-los.</translation>
 <translation id="2387458720915042159">Tipus de connexió del servidor intermediari</translation>
 <translation id="2389832672041313158">Birmà (Birmània)</translation>
 <translation id="2392369802118427583">Activa</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_eu.xtb b/ui/chromeos/translations/ui_chromeos_strings_eu.xtb
index 9339a6c1..ae06c27 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_eu.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_eu.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Aldatu zerrenda-ikuspegira</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> karpeta partekatu dira Linux-ekin</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> fitxategi hautatu dira</translation>
+<translation id="2387120140441437063">Ezin dira ireki zaborrontzira eramandako fitxategiak. Lehenera itzazu ireki aurretik.</translation>
 <translation id="2387458720915042159">Proxy konexio mota</translation>
 <translation id="2389832672041313158">Birmaniarra</translation>
 <translation id="2392369802118427583">Aktibatu</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_fil.xtb b/ui/chromeos/translations/ui_chromeos_strings_fil.xtb
index d61b2f5d..d474457 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_fil.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_fil.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Lumipat sa list view</translation>
 <translation id="2377590462528165447">Nagbahagi ng <ph name="NUMBER_OF_ITEMS" /> (na) folder sa Linux</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> (na) file ang pinili</translation>
+<translation id="2387120140441437063">Hindi puwedeng buksan ang mga file na inilagay sa trash. Paki-restore ang mga file bago buksan.</translation>
 <translation id="2387458720915042159">Uri ng koneksyon sa proxy</translation>
 <translation id="2389832672041313158">Burmese/Myanmar</translation>
 <translation id="2392369802118427583">I-activate</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_gu.xtb b/ui/chromeos/translations/ui_chromeos_strings_gu.xtb
index 2df0fd2..8779d86 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_gu.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_gu.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">સૂચિ દૃશ્ય પર સ્વિચ કરો</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> ફોલ્ડર Linux સાથે શેર કર્યા</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> ફાઇલ પસંદ કરી</translation>
+<translation id="2387120140441437063">ટ્રેશ કરેલી ફાઇલો ખોલી શકાતી નથી. કૃપા કરીને ફાઇલોને ખોલતા પહેલાં રિસ્ટોર કરો.</translation>
 <translation id="2387458720915042159">પ્રૉક્સી કનેક્શનનો પ્રકાર</translation>
 <translation id="2389832672041313158">બર્મીઝ/મ્યાનમાર</translation>
 <translation id="2392369802118427583">સક્રિય કરો</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_hi.xtb b/ui/chromeos/translations/ui_chromeos_strings_hi.xtb
index 2d55956..95abd84 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_hi.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_hi.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">'सूची की तरह देखें' पर स्विच करें</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> फ़ोल्डर Linux के साथ शेयर किए गए</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> फ़ाइलें चयनित</translation>
+<translation id="2387120140441437063">ट्रैश में भेजी गई फ़ाइलों को नहीं खोला जा सकता. फ़ाइलों को खोलने से पहले उन्हें वापस लाएं.</translation>
 <translation id="2387458720915042159">प्रॉक्सी कनेक्शन प्रकार</translation>
 <translation id="2389832672041313158">बर्मीज़/म्यांमार</translation>
 <translation id="2392369802118427583">सक्रिय करें</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ka.xtb b/ui/chromeos/translations/ui_chromeos_strings_ka.xtb
index 60130da..9a5e156 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ka.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ka.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">სიის ხედზე გადართვა</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> საქაღალდე გაზიარებულია Linux-თან</translation>
 <translation id="2378075407703503998">არჩეულია <ph name="SELCTED_FILE_COUNT" /> ფაილი</translation>
+<translation id="2387120140441437063">წაშლილი ფაილების გახსნა ვერ ხერხდება. გახსნამდე აღადგინეთ ფაილები.</translation>
 <translation id="2387458720915042159">პროქსი-სერვერის კავშირის ტიპი</translation>
 <translation id="2389832672041313158">ბირმული/მიანმარული</translation>
 <translation id="2392369802118427583">გააქტიურება</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_km.xtb b/ui/chromeos/translations/ui_chromeos_strings_km.xtb
index 19982f6..9fb5598 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_km.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_km.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">ប្ដូរ​ទៅ​ទិដ្ឋភាពជាបញ្ជី</translation>
 <translation id="2377590462528165447">ថត <ph name="NUMBER_OF_ITEMS" /> ដែលបាន​ចែករំលែកជាមួយ Linux</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> ឯកសារត្រូវបានជ្រើសរើស</translation>
+<translation id="2387120140441437063">មិនអាច​បើក​ឯកសារ​ពីធុងសំរាម​បានទេ។ សូម​ស្ដារ​ឯកសារ​សិន មុនពេល​បើក។</translation>
 <translation id="2387458720915042159">ប្រភេទ​នៃការ​តភ្ជាប់​ប្រូកស៊ី</translation>
 <translation id="2389832672041313158">ភាសា​ភូមា/មីយ៉ាន់ម៉ា</translation>
 <translation id="2392369802118427583">ធ្វើសកម្មភាព</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_kn.xtb b/ui/chromeos/translations/ui_chromeos_strings_kn.xtb
index ac22791..e037154 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_kn.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_kn.xtb
@@ -155,6 +155,7 @@
 <translation id="2377319039870049694">ಪಟ್ಟಿ ವೀಕ್ಷಣೆಗೆ ಬದಲಾಯಿಸಿ</translation>
 <translation id="2377590462528165447">Linux ನೊಂದಿಗೆ <ph name="NUMBER_OF_ITEMS" /> ಫೋಲ್ಡರ್‌ಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> ಫೈಲ್‌ಗಳನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ</translation>
+<translation id="2387120140441437063">ಅನುಪಯುಕ್ತದಲ್ಲಿರುವ ಫೈಲ್‌ಗಳನ್ನು ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ. ತೆರೆಯುವ ಮೊದಲು ಫೈಲ್‌ಗಳನ್ನು ಮರುಸ್ಥಾಪಿಸಿ.</translation>
 <translation id="2387458720915042159">ಪ್ರಾಕ್ಸಿ ಪ್ರಕಾರ ಸಂಪರ್ಕ</translation>
 <translation id="2389832672041313158">ಬರ್ಮೀಸ್/ಮ್ಯಾನ್ಮಾರ್</translation>
 <translation id="2392369802118427583">ಸಕ್ರಿಯಗೊಳಿಸಿ</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ky.xtb b/ui/chromeos/translations/ui_chromeos_strings_ky.xtb
index d27a8c5..a7c3084 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ky.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ky.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Тизме көрүнүшүнө өтүү</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> папка Linux аркылуу бөлүшүлдү</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> файл тандалды</translation>
+<translation id="2387120140441437063">Таштандыдагы файлдар ачылбай жатат. Ачуудан мурун файлдарды калыбына келтириңиз.</translation>
 <translation id="2387458720915042159">Проксинин туташуу түрү</translation>
 <translation id="2389832672041313158">Бирмача (Мьянма)</translation>
 <translation id="2392369802118427583">Жандыруу</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_lo.xtb b/ui/chromeos/translations/ui_chromeos_strings_lo.xtb
index 1ed0d1b..8135126 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_lo.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_lo.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">ປ່ຽນເປັນມຸມມອງລາຍຊື່</translation>
 <translation id="2377590462528165447">ແບ່ງປັນ <ph name="NUMBER_OF_ITEMS" /> ໂຟນເດີກັບ Linux ແລ້ວ</translation>
 <translation id="2378075407703503998">ເລືອກ <ph name="SELCTED_FILE_COUNT" /> ໄຟລ໌ແລ້ວ</translation>
+<translation id="2387120140441437063">ບໍ່ສາມາດເປີດໄຟລ໌ທີ່ຢູ່ໃນຖັງຂີ້ເຫຍື້ອໄດ້. ກະລຸນາກູ້ໄຟລ໌ຄືນມາກ່ອນເປີດ.</translation>
 <translation id="2387458720915042159">ປະເພດການເຊື່ອມຕໍ່ພຣັອກຊີ</translation>
 <translation id="2389832672041313158">ພາສາມຽນມາ/ພະມ້າ</translation>
 <translation id="2392369802118427583">ເປີດໃຊ້ງານ</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ml.xtb b/ui/chromeos/translations/ui_chromeos_strings_ml.xtb
index 9a7ac0b..bbb1d55 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ml.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ml.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">ലിസ്റ്റ് കാഴ്‌ചയിലേക്ക് മാറുക</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> ഫോൾഡറുകൾ Linux ഉപയോഗിച്ച് പങ്കിട്ടു</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> ഫയലുകൾ തിരഞ്ഞെടുത്തു</translation>
+<translation id="2387120140441437063">ട്രാഷ് ചെയ്ത ഫയലുകൾ തുറക്കാനാകില്ല. തുറക്കും മുമ്പ് ഫയലുകൾ പുനഃസ്ഥാപിക്കുക.</translation>
 <translation id="2387458720915042159">പ്രോക്‌സി കണക്ഷൻ തരം</translation>
 <translation id="2389832672041313158">ബർമീസ്/മ്യാൻമർ</translation>
 <translation id="2392369802118427583">സജീവമാക്കുക</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_pt-BR.xtb b/ui/chromeos/translations/ui_chromeos_strings_pt-BR.xtb
index c5114d8..14913829 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_pt-BR.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_pt-BR.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Alternar para a visualização de lista</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> pastas compartilhadas com o Linux</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> arquivos selecionados</translation>
+<translation id="2387120140441437063">Não é possível abrir arquivos que estão na lixeira. Restaure os arquivos antes de abrir.</translation>
 <translation id="2387458720915042159">Tipo de conexão proxy</translation>
 <translation id="2389832672041313158">Birmanês (Mianmar)</translation>
 <translation id="2392369802118427583">Ativar</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sl.xtb b/ui/chromeos/translations/ui_chromeos_strings_sl.xtb
index 9ac24fd..6e1f8f7 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sl.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sl.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Preklop na pogled seznama</translation>
 <translation id="2377590462528165447">Št. map, deljenih z Linuxom: <ph name="NUMBER_OF_ITEMS" /></translation>
 <translation id="2378075407703503998">Št. izbranih datotek: <ph name="SELCTED_FILE_COUNT" /></translation>
+<translation id="2387120140441437063">Datotek v smetnjaku ni mogoče odpreti. Pred odpiranjem jih obnovite.</translation>
 <translation id="2387458720915042159">Vrsta povezave strežnika proxy</translation>
 <translation id="2389832672041313158">burmanščina/mjanmarščina</translation>
 <translation id="2392369802118427583">Aktiviraj</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sr-Latn.xtb b/ui/chromeos/translations/ui_chromeos_strings_sr-Latn.xtb
index b2b4da8..ecbafd0 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sr-Latn.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sr-Latn.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Pređi na prikaz liste</translation>
 <translation id="2377590462528165447">Direktorijumi (<ph name="NUMBER_OF_ITEMS" />) se dele sa Linux-om</translation>
 <translation id="2378075407703503998">Izabranih datoteka: <ph name="SELCTED_FILE_COUNT" /></translation>
+<translation id="2387120140441437063">Fajlovi u otpadu ne mogu da se otvore. Vratite fajlove pre otvaranja.</translation>
 <translation id="2387458720915042159">Tip veze sa proksijem</translation>
 <translation id="2389832672041313158">burmanski (Mijanmar)</translation>
 <translation id="2392369802118427583">Aktiviraj</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sr.xtb b/ui/chromeos/translations/ui_chromeos_strings_sr.xtb
index c80a144..c39f022 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sr.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Пређи на приказ листе</translation>
 <translation id="2377590462528165447">Директоријуми (<ph name="NUMBER_OF_ITEMS" />) се деле са Linux-ом</translation>
 <translation id="2378075407703503998">Изабраних датотека: <ph name="SELCTED_FILE_COUNT" /></translation>
+<translation id="2387120140441437063">Фајлови у отпаду не могу да се отворе. Вратите фајлове пре отварања.</translation>
 <translation id="2387458720915042159">Тип везе са проксијем</translation>
 <translation id="2389832672041313158">бурмански (Мијанмар)</translation>
 <translation id="2392369802118427583">Активирај</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ta.xtb b/ui/chromeos/translations/ui_chromeos_strings_ta.xtb
index 6fbdd1b0..38e8f1f 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ta.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ta.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">பட்டியல் காட்சிக்கு மாறு</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> ஃபோல்டர்கள் Linuxஸுடன் பகிரப்பட்டன</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> ஃபைல்கள்  தேர்ந்தெடுக்கப்பட்டன</translation>
+<translation id="2387120140441437063">நீக்கிய ஃபைல்களைத் திறக்க முடியாது. திறக்கும் முன் ஃபைல்களை மீட்டெடுக்கவும்.</translation>
 <translation id="2387458720915042159">ப்ராக்ஸி இணைப்பு வகை</translation>
 <translation id="2389832672041313158">பர்மீஸ்/மியான்மர்</translation>
 <translation id="2392369802118427583">செயல்படுத்து</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_te.xtb b/ui/chromeos/translations/ui_chromeos_strings_te.xtb
index cf44ebf..f39f1a2 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_te.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_te.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">లిస్ట్‌ వీక్షణకు మార్చు</translation>
 <translation id="2377590462528165447">Linuxతో <ph name="NUMBER_OF_ITEMS" /> ఫోల్డర్‌లు షేర్ చేయబడ్డాయి</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> ఫైళ్లు ఎంచుకోబడ్డాయి</translation>
+<translation id="2387120140441437063">ట్రాష్‌లో ఉన్న ఫైళ్లను తెరవడం సాధ్యం కాదు. దయచేసి తెరవడానికి ముందు, ఫైళ్లను రీస్టోర్ చేయండి.</translation>
 <translation id="2387458720915042159">ప్రాక్సీ కనెక్షన్ రకం</translation>
 <translation id="2389832672041313158">బర్మీస్/మయన్మార్</translation>
 <translation id="2392369802118427583">సక్రియం చేయి</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ur.xtb b/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
index 4f9eb35..2411083 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ur.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">فہرست والے منظر پر سوئچ کریں</translation>
 <translation id="2377590462528165447">‏<ph name="NUMBER_OF_ITEMS" /> فولڈرز کا Linux کے ساتھ اشتراک کیا گیا</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> فائلیں منتخب کی گئیں</translation>
+<translation id="2387120140441437063">کوڑے دان میں ڈالی ہوئیں فائلز نہیں کھول سکتے۔ براہ کرم کھولنے سے پہلے فائلز بحال کریں۔</translation>
 <translation id="2387458720915042159">پراکسی کنکشن کی قسم</translation>
 <translation id="2389832672041313158">برمی/میانمار</translation>
 <translation id="2392369802118427583">فعال کریں</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_uz.xtb b/ui/chromeos/translations/ui_chromeos_strings_uz.xtb
index 81f61e43..6f5f6d4 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_uz.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_uz.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">Qator shaklida</translation>
 <translation id="2377590462528165447"><ph name="NUMBER_OF_ITEMS" /> ta jild Linuxga ulashilgan</translation>
 <translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> ta fayl belgilandi</translation>
+<translation id="2387120140441437063">Fayllar chiqindiga tashlangani uchun ochilmadi. Ochishdan oldin ularni tiklang.</translation>
 <translation id="2387458720915042159">Proksi-server orqali ulanish turi</translation>
 <translation id="2389832672041313158">Birma/Myanma</translation>
 <translation id="2392369802118427583">Faollashtirish</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb b/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
index 2979812..f030d2c7 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
@@ -159,6 +159,7 @@
 <translation id="2377319039870049694">切换到列表视图</translation>
 <translation id="2377590462528165447">与 Linux 共享了 <ph name="NUMBER_OF_ITEMS" /> 个文件夹</translation>
 <translation id="2378075407703503998">已选择 <ph name="SELCTED_FILE_COUNT" /> 个文件</translation>
+<translation id="2387120140441437063">无法打开回收站中的文件。请先恢复相应文件,然后再打开。</translation>
 <translation id="2387458720915042159">代理连接类型</translation>
 <translation id="2389832672041313158">缅甸语</translation>
 <translation id="2392369802118427583">激活</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zu.xtb b/ui/chromeos/translations/ui_chromeos_strings_zu.xtb
index e12929c..74821e6 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zu.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zu.xtb
@@ -9,8 +9,8 @@
 <translation id="1062407476771304334">Faka esikhundleni</translation>
 <translation id="1119447706177454957">Iphutha langaphakathi</translation>
 <translation id="1120073797882051782">I-Hangul Romaja</translation>
-<translation id="112387589102719461">I-English (US) enekhibhodi yomhleli we-Dvorak</translation>
-<translation id="1134697384939541955">I-English (US) enekhibhodi enwetshiwe</translation>
+<translation id="112387589102719461">English (US) enekhibhodi yomhleli we-Dvorak</translation>
+<translation id="1134697384939541955">English (US) enekhibhodi enwetshiwe</translation>
 <translation id="1148097584170732637"><ph name="FILE_COUNT" /> itholakele.
     <ph name="LINE_BREAK1" />
     Asikho isikhala esanele esitholakalayo kusitoreji sendawo. U-<ph name="FILE_SIZE" /> ngaphezulu uyadingeka.
@@ -48,7 +48,7 @@
 <translation id="1383876407941801731">Sesha</translation>
 <translation id="1395262318152388157">Funa isilayida</translation>
 <translation id="1399511500114202393">Asikho isitifiketi somsebenzisi</translation>
-<translation id="1404323374378969387">Isi-Norwegian</translation>
+<translation id="1404323374378969387">Norwegian</translation>
 <translation id="1433628812591023318">Ukuze udedele amafayela ku-Parallels Desktop, ifayela kufanele lihanjiswe kumafayela e-Windows.</translation>
 <translation id="1435838927755162558">Yabelana ngefolda ne-Parallels Desktop</translation>
 <translation id="1439919885608649279">Umuntu onezimbali</translation>
@@ -57,7 +57,7 @@
 <translation id="1482884275703521657">Isi-Finnish</translation>
 <translation id="148466539719134488">I-Swiss</translation>
 <translation id="1497522201463361063">Ayikwazi ukuqamba kabusha i-"<ph name="FILE_NAME" />". <ph name="ERROR_MESSAGE" /></translation>
-<translation id="1499943022354839699">I-English (US) enekhibhodi ye-Dvorak</translation>
+<translation id="1499943022354839699">English (US) enekhibhodi ye-Dvorak</translation>
 <translation id="1515909359182093592"><ph name="INPUT_LABEL" /> - Umsingathi</translation>
 <translation id="1521655867290435174">Amashidi we-Google</translation>
 <translation id="1538729222189715449">Ivula amafayela e-Linux...</translation>
@@ -71,7 +71,7 @@
 <translation id="1620510694547887537">Ikhamela</translation>
 <translation id="162175252992296058">Isi-Portuguese nge-US International keyboard</translation>
 <translation id="1629521517399325891">Isitifiketi somsebenzisi asitholakali ukufakazela ubuqiniso inethiwekhi.</translation>
-<translation id="1641780993263690097">Isi-Chinese Pinyin</translation>
+<translation id="1641780993263690097">Chinese Pinyin</translation>
 <translation id="1646019627374511909">Yenza amafayela angu-<ph name="NUMBER_OF_ITEMS" /> atholakale ngokungaxhunyiwe kwi-inthanethi</translation>
 <translation id="164969095109328410">Idivivayisi ye-Chrome</translation>
 <translation id="1661867754829461514">Iphinikhodi ayikho</translation>
@@ -84,7 +84,7 @@
 <translation id="1722687688096767818">Ingeza Iphrofayela...</translation>
 <translation id="1726100011689679555">Amagama wamasevisi</translation>
 <translation id="1729953886957086472">Isi-German (Germany)</translation>
-<translation id="1730235522912993863">Isi-Chinese Cangjie</translation>
+<translation id="1730235522912993863">Chinese Cangjie</translation>
 <translation id="1731889557567069540">izinto ezingu-<ph name="NUMBER_OF_ITEMS" /> zikopishiwe.</translation>
 <translation id="174173592514158117">Bonisa onke amafolda e-Google Play</translation>
 <translation id="1742316578210444689">Ukugugulwa kwamaletha kwesi-Hebrew</translation>
@@ -119,7 +119,7 @@
 <translation id="1995337122023280937">Iya endaweni yefayela</translation>
 <translation id="2001796770603320721">Phatha kuDrayivu</translation>
 <translation id="2009067268969781306">Ukufometha idrayivu kuzosula yonke idatha elondolozwe kuyo. Lesi senzo asikwazi ukuhlehliswa.</translation>
-<translation id="2025955442973426285">Isi-Tigrinya</translation>
+<translation id="2025955442973426285">Tigrinya</translation>
 <translation id="2037845485764049925">Isi-Russian</translation>
 <translation id="2044023416777079300">Imodemu ayibhaliswanga</translation>
 <translation id="2046702855113914483">I-Ramen</translation>
@@ -138,7 +138,7 @@
 <translation id="2163152940313951844">Inhlamvu engavumelekile: <ph name="CHARACTER_NAME" /></translation>
 <translation id="2184934335987813305">Isi-Portuguese nge-US International PC keyboard</translation>
 <translation id="2198315389084035571">isi-Sipmlified Chinese</translation>
-<translation id="22085916256174561">Isi-Korean</translation>
+<translation id="22085916256174561">Korean</translation>
 <translation id="2208919847696382164">Faka nge-Linux</translation>
 <translation id="2225536596944493418">Ingabe ufuna ukususa izinto ze-<ph name="NUMBER_OF_ITEMS" />?</translation>
 <translation id="2230062665678605299">Ayikwazi ukudala ifolda le-"<ph name="FOLDER_NAME" />". <ph name="ERROR_MESSAGE" /></translation>
@@ -153,7 +153,7 @@
 <translation id="2305020378527873881"><ph name="VOLUME_NAME" /> ikhishiwe.</translation>
 <translation id="2307462900900812319">Lungiselela inethiwekhi</translation>
 <translation id="2325650632570794183">Uhlobo lwefayela alusekelwe. Sicela uvakashele isitolo sewebhu se-Chrome ukuze uthole uhlelo lokusebenza olungavula lolu hlobo lwefayela.</translation>
-<translation id="2326539130272988168">Isi-Bulgaria</translation>
+<translation id="2326539130272988168">Bulgarian</translation>
 <translation id="2352947182261340447">Asikho isikhala esanele kusitoreji sendawo.</translation>
 <translation id="23721837607121582">Landa iphroayela yeselula, Inethiwekhi engu-<ph name="NETWORK_INDEX" /> kwezingu-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" /></translation>
 <translation id="2377319039870049694">Shintshela ekubukeni kohlu</translation>
@@ -196,7 +196,7 @@
 <translation id="2664412712123763093">Indawo yefayela</translation>
 <translation id="2718540689505416944">Faka uhlelo lokusebenza nge-Linux</translation>
 <translation id="2719020180254996569">Inethiwekhi <ph name="NETWORK_INDEX" /> ye-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="CONNECTION_STATUS" />, imininingwane</translation>
-<translation id="2724954091494693138">Isi-Turkish esinekhibhodi ye-F</translation>
+<translation id="2724954091494693138">Turkish esinekhibhodi ye-F</translation>
 <translation id="2732839045120506979">I-Vietnamese VNI</translation>
 <translation id="2735623501230989521">Nikeza i-Parallels Desktop imvume yokufinyelela amafayela kufolda ye-<ph name="FOLDER_NAME" /></translation>
 <translation id="2771816809568414714">Ushizi</translation>
@@ -213,9 +213,9 @@
 <translation id="2888807692577297075">Azikho izinto ezifana ne-&lt;b&gt;"<ph name="SEARCH_STRING" />"&lt;/b&gt;</translation>
 <translation id="2894654529758326923">Ulwazi</translation>
 <translation id="2902734494705624966">Inwetshwelwe i-US</translation>
-<translation id="290843123675549676">Isi-Marathi</translation>
+<translation id="290843123675549676">Marathi</translation>
 <translation id="2923240520113693977">Isi-Estonian</translation>
-<translation id="2938685643439809023">Isi-Mongolian</translation>
+<translation id="2938685643439809023">Mongolian</translation>
 <translation id="2943503720238418293">Sebenzisa igama elifushane</translation>
 <translation id="2949781154072577687">Ifometha i-<ph name="DRIVE_NAME" />...</translation>
 <translation id="2951236788251446349">I-Jellyfish</translation>
@@ -223,13 +223,13 @@
 <translation id="2984337792991268709">Namhlanje ngo-<ph name="TODAY_DAYTIME" /></translation>
 <translation id="2994320653639462337">Ibuyisela izinto ezingu-<ph name="COUNT" />...</translation>
 <translation id="2994669386200004489">Ayikwazanga ukwenza isipele i-<ph name="FILE_NAME" /></translation>
-<translation id="299638574917407533">Isi-French (Canada)</translation>
+<translation id="299638574917407533">French (Canada)</translation>
 <translation id="3003189754374775221">Inethiwekhi <ph name="NETWORK_INDEX" /> ye-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="NETWORK_PROVIDER_NAME" />, amandla esignali <ph name="SIGNAL_STRENGTH" />%, Xhuma</translation>
 <translation id="3003633581067744647">Shintshela ekubukeni kwesithonjana</translation>
 <translation id="3016566519832145558">Isexwayiso: Lamafayela awesikhashana futhi angase asuswe ngokuzenzekelayo ukukhulula isikhala sediski.</translation>
 <translation id="3029114385395636667">Nika amandla i-Google Amadokhumenti angaxhumekile ku-inthanethi ukwenza Amadokhumenti, AmaSpredishithi namaSlayidi kutholakale ngokungaxhunyiwe kwi-inthanethi.</translation>
 <translation id="303198083543495566">Ukuma komhlaba</translation>
-<translation id="3047197340186497470">Isi-Chinese Dayi</translation>
+<translation id="3047197340186497470">Chinese Dayi</translation>
 <translation id="3057861065630527966">Yenza isipele izithombe zakho namavidiyo</translation>
 <translation id="3067790092342515856">Amafayela e-Windows</translation>
 <translation id="3078461028045006476">Yabelana nge-<ph name="EXTENSION_NAME" /></translation>
@@ -248,13 +248,13 @@
 <translation id="3205852408225871810">Isi-Portuguese (Brazil)</translation>
 <translation id="3224239078034945833">Izilimi eziningi ze-Canadian</translation>
 <translation id="3236289833370040187">Ubunikazi buzodluliselwa ku-<ph name="DESTINATION_DOMAIN" />.</translation>
-<translation id="3241720467332021590">Isi-Irish</translation>
+<translation id="3241720467332021590">Irish</translation>
 <translation id="3245321423178950146">Umculi ongaziwa</translation>
 <translation id="3248185426436836442">Ilindile</translation>
-<translation id="3252266817569339921">Isi-French</translation>
+<translation id="3252266817569339921">French</translation>
 <translation id="3253225298092156258">Ayitholakali</translation>
 <translation id="3254434849914415189">Khetha uhlelo lokusebenza oluzenzakalelayo lwamafayela we-<ph name="FILE_TYPE" />:</translation>
-<translation id="3255159654094949700">Isi-Arabic</translation>
+<translation id="3255159654094949700">Arabic</translation>
 <translation id="3264582393905923483">Okuqukethwe</translation>
 <translation id="3272909651715601089">Ayikwazanga ukuvula i-"<ph name="PATH" />"</translation>
 <translation id="3280431534455935878">Iyalungiselela</translation>
@@ -262,15 +262,15 @@
 <translation id="3290356915286466215">Okungaphephanga</translation>
 <translation id="3291218047831493686">Xhuma kule nethiwekhi ukuze ushintshe amasethingi wokukhiya i-SIM</translation>
 <translation id="3295357220137379386">Idivayisi imatasa</translation>
-<translation id="3296763833017966289">Isi-Georgian</translation>
-<translation id="3307875152560779385">Isi-Ukrain</translation>
+<translation id="3296763833017966289">Georgian</translation>
+<translation id="3307875152560779385">Ukrainian</translation>
 <translation id="3326821416087822643">Izipha i-<ph name="FILE_NAME" />...</translation>
 <translation id="3335337277364016868">Unyaka okurekhodwe ngawo</translation>
 <translation id="3353984535370177728">Khetha ifolda okumele uyilayishe</translation>
 <translation id="3356580349448036450">Qedile</translation>
 <translation id="3358452157379365236">Isiginci</translation>
 <translation id="3368922792935385530">Ixhunyiwe</translation>
-<translation id="3382143449143186018">Isi-Nepali ngekhibhodi ye-InScript</translation>
+<translation id="3382143449143186018">Nepali ngekhibhodi ye-InScript</translation>
 <translation id="338691029516748599">Inethiwekhi <ph name="NETWORK_INDEX" /> ye-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="SECURITY_STATUS" />, amandla esignali <ph name="SIGNAL_STRENGTH" />%, kuphethwe umlawuli wakho, xhuma</translation>
 <translation id="3408072735282270043">Yenza kusebenze, i-<ph name="NETWORK_NAME" /></translation>
 <translation id="3408236822532681288">Isi-German (Germany) esinekhibhodi ye-Neo 2</translation>
@@ -282,7 +282,7 @@
 <translation id="3468522857997926824"><ph name="FILE_COUNT" /> izithombe zenziwe isipele ku-<ph name="BEGIN_LINK" />Google Drayivu<ph name="END_LINK" /></translation>
 <translation id="3475447146579922140">Isipredishithi se-Google</translation>
 <translation id="3479552764303398839">Hhayi manje</translation>
-<translation id="3486821258960016770">Isi-Mongolian</translation>
+<translation id="3486821258960016770">Mongolian</translation>
 <translation id="3495304270784461826"><ph name="COUNT" /> amaphutha.</translation>
 <translation id="3509680540198371098">Inethiwkehi <ph name="NETWORK_INDEX" /> ye-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, amandla esignali <ph name="SIGNAL_STRENGTH" />%, imininingwane</translation>
 <translation id="3522708245912499433">Isi-Portuguese</translation>
@@ -290,9 +290,9 @@
 <translation id="3527085408025491307">Ifolda</translation>
 <translation id="3549797760399244642">Hamba ku-drive.google.com...</translation>
 <translation id="3553048479571901246">Ukuze uvule amafayela nge-<ph name="APP_NAME" />, kukopishe kuqala kufolda lamafayela we-Windows.</translation>
-<translation id="3556731189587832921">I-English (US) enekhibhodi yamazwe ngamazwe ye-PC</translation>
+<translation id="3556731189587832921">English (US) enekhibhodi yamazwe ngamazwe ye-PC</translation>
 <translation id="3567221313191587603">Khetha ifayela, bese uguqula ukuvula i-<ph name="OFFLINE_CHECKBOX_NAME" /> yokufinyelela ungaxhunyiwe ku-inthanethi</translation>
-<translation id="357479282490346887">Isi-Lithuanian</translation>
+<translation id="357479282490346887">Lithuanian</translation>
 <translation id="3587482841069643663">Konke</translation>
 <translation id="3592251141500063301">Ayikwazanga ukwenza i-<ph name="FILE_NAME" /> itholakale ngokungaxhunyiwe kwi-inthanethi</translation>
 <translation id="3601151620448429694"><ph name="NETWORK_NAME" /> · <ph name="CARRIER_NAME" /></translation>
@@ -331,7 +331,7 @@
 <translation id="3858860766373142691">Igama</translation>
 <translation id="386548886866354912">Pakisha nge-<ph name="EXTENSION_NAME" /></translation>
 <translation id="3866249974567520381">Incazelo</translation>
-<translation id="3899991606604168269">Isi-French (Canada) esinekhibhodi Yezilimi eziningi</translation>
+<translation id="3899991606604168269">French (Canada) esinekhibhodi Yezilimi eziningi</translation>
 <translation id="3901991538546252627">Ixhumeka ku-<ph name="NAME" /></translation>
 <translation id="3906232975181435906">Ifaka iphrofayela leselula, Inethiwekhi engu-<ph name="NETWORK_INDEX" /> kwangu-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" /></translation>
 <translation id="3924145049010392604">I-Meta</translation>
@@ -340,21 +340,21 @@
 <translation id="3958548648197196644">I-Kiwi</translation>
 <translation id="3966388904776714213">Isidlali somsindo</translation>
 <translation id="3971140002794351170">Landa iphrofayela yeselula, Inethiwekhi engu-<ph name="NETWORK_INDEX" /> kwezingu-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="NETWORK_PROVIDER_NAME" /></translation>
-<translation id="3973925058222872294">I-English (UK)</translation>
+<translation id="3973925058222872294">English (UK)</translation>
 <translation id="3975895378829046965">I-Bangla Phonetic</translation>
 <translation id="4002066346123236978">Isihloko</translation>
-<translation id="4017788180641807848">I-English (US) enekhibhodi ye-Workman</translation>
+<translation id="4017788180641807848">English (US) enekhibhodi ye-Workman</translation>
 <translation id="4040753847560036377">I-PUK engalungile</translation>
 <translation id="4057991113334098539">Yenza kusebenze...</translation>
-<translation id="4092890906744441904">Isi-Irish</translation>
+<translation id="4092890906744441904">Irish</translation>
 <translation id="4124935795427217608">I-Unicorn</translation>
 <translation id="4158739975813877944">Vula uhlu lwadlalayo</translation>
 <translation id="4159731583141908892">kuhanjiswe okungu-<ph name="FILE_NAME" />.</translation>
 <translation id="4186579485882418952">Nika Amandla Ungaxhumekile Ku-inthanethi</translation>
 <translation id="4193154014135846272">I-Google dokhumenti</translation>
 <translation id="4197674956721858839">Ukukhethwa kweziphu</translation>
-<translation id="4202378258276439759">Isi-Spanish (Latin America)</translation>
-<translation id="4202977638116331303">Isi-Georgian</translation>
+<translation id="4202378258276439759">Spanish (Latin America)</translation>
+<translation id="4202977638116331303">Georgian</translation>
 <translation id="421017592316736757">Kumele ube ku-inthanethi ukuze ufinyelele kule fayela.</translation>
 <translation id="4212740939091998969">Ifolda enegama "<ph name="FOLDER_NAME" />" isivele ikhona. Sicela ukhethe igama elihlukile.</translation>
 <translation id="4215448920900139318">Yenza isipele <ph name="FILE_COUNT" /></translation>
@@ -366,7 +366,7 @@
 <translation id="4302605047395093221">Noma ubani osebenzisa le divayisi kuzodingeka afake Iphinikhodi ukuze axhumeke kule nethiwekhi yeselula</translation>
 <translation id="4309915981827077375">Ulwazi oluvamile</translation>
 <translation id="432252891123397018">Isi-Romanian esinekhibhodi Evamile</translation>
-<translation id="4325128273762811722">Isi-Slovenian</translation>
+<translation id="4325128273762811722">Slovenian</translation>
 <translation id="4326142238881453352">Ingcweti yezitshalo</translation>
 <translation id="4326192123064055915">Ikhofi</translation>
 <translation id="4336032328163998280">Ukusebenza kwekhophi kuhlulekile. <ph name="ERROR_MESSAGE" /></translation>
@@ -390,7 +390,7 @@
 <translation id="4477002475007461989">Isi-Romanian</translation>
 <translation id="4477219268485577442">Ifonethikhi yesi-Bulgarian</translation>
 <translation id="4508265954913339219">Ukwenza kusebenze kuhlulekile</translation>
-<translation id="4509667233588080747">I-English (US) enekhibhodi yamazwe ngamazwe ye-Workman</translation>
+<translation id="4509667233588080747">English (US) enekhibhodi yamazwe ngamazwe ye-Workman</translation>
 <translation id="4522570452068850558">Imininingwane</translation>
 <translation id="4527800702232535228">Le folda yabiwa Nedeskithophu ye-Parallels</translation>
 <translation id="4552678318981539154">Thenga isitoreji esiningi</translation>
@@ -413,17 +413,17 @@
 <translation id="4690246192099372265">Isi-Swedish</translation>
 <translation id="4693155481716051732">I-Sushi</translation>
 <translation id="4694604912444486114">Inkawu</translation>
-<translation id="469612310041132144">Isi-Chinese Esisheshayo</translation>
+<translation id="469612310041132144">Chinese Esisheshayo</translation>
 <translation id="4697043402264950621">Uhlu lwefayela luhlungwe nge-<ph name="COLUMN_NAME" /> nge-oda elikhuphukayo.</translation>
 <translation id="469897186246626197">Leli fayela liklanyelwe i-PC esebenzisa isofthiwe ye-Windows. Lokhu akuhambelani nedivayisi yakho esebenzisa i-ChromeOS. <ph name="BEGIN_LINK_HELP" />Funda Kabanzi<ph name="END_LINK_HELP" /> ngokuvula amafayela ku-ChromeOS.</translation>
 <translation id="4706042980341760088">Isi-Tamil esinekhibhodi ye-Typewriter</translation>
-<translation id="4711094779914110278">Isi-Turkish</translation>
+<translation id="4711094779914110278">Turkish</translation>
 <translation id="4712283082407695269">Ivula i-"<ph name="PATH" />"</translation>
 <translation id="4720185134442950733">Inethiwekhi yedatha yeselula</translation>
 <translation id="4724850507808590449"><ph name="FILE_COUNT" /> izithombe ezenziwe isipele</translation>
 <translation id="4725511304875193254">I-Corgi</translation>
 <translation id="4737050008115666127">Ukufika</translation>
-<translation id="4747271164117300400">Isi-Macedonian</translation>
+<translation id="4747271164117300400"> Macedonian</translation>
 <translation id="4759238208242260848">Ukulanda</translation>
 <translation id="4779041693283480986">Isi-Portuguese (Portugal)</translation>
 <translation id="4779136857077979611">I-Onigiri</translation>
@@ -452,7 +452,7 @@
 <translation id="4969785127455456148">Albhamu</translation>
 <translation id="4973523518332075481">Sebenzisa igama elinezinhlamvu ezingu-<ph name="MAX_LENGTH" /> noma ngaphansi</translation>
 <translation id="4973970068702235170">Ukuzipha kwehlulekile, iphutha elingalindelekile livelile: <ph name="ERROR_MESSAGE" /></translation>
-<translation id="4984616446166309645">Isi-Japanese</translation>
+<translation id="4984616446166309645">Japanese</translation>
 <translation id="4988205478593450158">Ingabe uqinisekile ukuthi ufuna ukususa i-"<ph name="FILE_NAME" />"?</translation>
 <translation id="498902553138568924">Uvemvame obomvu</translation>
 <translation id="4992066212339426712">Susa ukuthula</translation>
@@ -462,7 +462,7 @@
 <translation id="5024856940085636730">Umsebenzi uthatha isikhathi eside kunokulindelekile. Ingabe ufuna ukuwukhansela?</translation>
 <translation id="5036159836254554629">Phatha ukwabelana ne-Parallels Desktop</translation>
 <translation id="5038625366300922036">Bona okuningi...</translation>
-<translation id="5044852990838351217">Isi-Armenian</translation>
+<translation id="5044852990838351217">Armenian</translation>
 <translation id="5045550434625856497">Iphasiwedi engalungile</translation>
 <translation id="5059127710849015030">Ukuguqulwa kwamaletha esi-Nepali</translation>
 <translation id="5068919226082848014">I-Pizza</translation>
@@ -471,7 +471,7 @@
 <translation id="509429900233858213">Kuvele iphutha.</translation>
 <translation id="5098629044894065541">Isi-Hebrew</translation>
 <translation id="5109254780565519649">Kuvele iphutha. Ezinye zezinto kungenzeka azibuyiselwanga.</translation>
-<translation id="5110329002213341433">I-English (Canada)</translation>
+<translation id="5110329002213341433">English (Canada)</translation>
 <translation id="5123433949759960244">I-Basketball</translation>
 <translation id="5129662217315786329">Isi-Polish</translation>
 <translation id="5144820558584035333">Isethi ye-Hangul 3 (390)</translation>
@@ -516,16 +516,16 @@
 <translation id="5411472733320185105">Ungasebenzisi izilungiselelo zommeleli zalaba basingathi nezizinda:</translation>
 <translation id="541890217011173530">Isi-Sorani Kurdish esinekhibhodi esekelwe ku-English</translation>
 <translation id="5422221874247253874">Iphoyinti lokufinyelela</translation>
-<translation id="5428105026674456456">Isi-Spanish</translation>
+<translation id="5428105026674456456">Spanish</translation>
 <translation id="5438282218546237410">Ayikho imiphumela ye-<ph name="SEARCH_TERM" />.</translation>
 <translation id="5449551289610225147">Iphasiwedi engavumelekile</translation>
 <translation id="5463231940765244860">Faka</translation>
 <translation id="5469868506864199649">Isi-Italian</translation>
 <translation id="5473333559083690127">Phinda ufake iphinikhodi entsha</translation>
-<translation id="5489067830765222292">Isi-Latvian</translation>
+<translation id="5489067830765222292">Latvian</translation>
 <translation id="5489965683297092283">Isihlungi esithi <ph name="FILTER_NAME" /> sivaliwe.</translation>
 <translation id="5494920125229734069">Khetha konke</translation>
-<translation id="5500122897333236901">Isi-Icelandic</translation>
+<translation id="5500122897333236901">Icelandic</translation>
 <translation id="5508696409934741614">Amachashazi</translation>
 <translation id="5522908512596376669">Uhlu lwefayela lushintshele kuhlu lokubuka.</translation>
 <translation id="5524517123096967210">Ifayela alikwazanga ukufundwa.</translation>
@@ -558,11 +558,11 @@
 <translation id="5776325638577448643">Susa futhi ufomethe</translation>
 <translation id="57838592816432529">Thulisa</translation>
 <translation id="5788127256798019331">Amafayela e-Google Play</translation>
-<translation id="5790193330357274855">Isi-Kazakh</translation>
+<translation id="5790193330357274855">Kazakh</translation>
 <translation id="5804245609861364054">Ukuguqulwa kwamaletha kwesi-Kannada</translation>
 <translation id="5814126672212206791">Uhlobo lokuxhumeka</translation>
-<translation id="5817397429773072584">Isi-Chinese Sosiko</translation>
-<translation id="5818003990515275822">Isi-Korean</translation>
+<translation id="5817397429773072584">Chinese Sosiko</translation>
+<translation id="5818003990515275822">Korean</translation>
 <translation id="5819442873484330149">Isethi ye-Hangul 3 (Kokugcina)</translation>
 <translation id="5832976493438355584">Ikhiyiwe</translation>
 <translation id="5833610766403489739">Leli fayela selilibele kwenye indawo. Sicela uhlole ukulungiselelwa kwendawo yakho yokulanda uphinde uzame futhi.</translation>
@@ -588,20 +588,20 @@
 <translation id="6040143037577758943">Vala</translation>
 <translation id="6055907707645252013">Inethiwekhi ye-<ph name="NETWORK_TYPE" /> ayixhunyiwe</translation>
 <translation id="6074825444536523002">Ifomu le-Google</translation>
-<translation id="6079871810119356840">Isi-Hungarian esinekhibhodi ye-Qwerty</translation>
+<translation id="6079871810119356840">Hungarian esinekhibhodi ye-Qwerty</translation>
 <translation id="6096979789310008754">Umbhalo wosesho usuliwe, kuboniswa wonke amafaela namafolda.</translation>
 <translation id="610101264611565198">Ihambisa i-<ph name="FILE_NAME" /> ku-<ph name="FOLDER_NAME" /></translation>
 <translation id="61118516107968648">Umbhalo we-CSV</translation>
 <translation id="6129953537138746214">Isikhala</translation>
 <translation id="6133173853026656527">Ihambisa i-<ph name="FILE_NAME" />...</translation>
-<translation id="613750717151263950">Isi-Japanese esinekhibhodi yase-US</translation>
+<translation id="613750717151263950">Japanese esinekhibhodi yase-US</translation>
 <translation id="6138894911715675297"><ph name="NETWORK_TYPE" />, ayikho inethiwekhi</translation>
 <translation id="6146563240635539929">Amavidiyo</translation>
 <translation id="6150853954427645995">Ukuze ulondoloze leli fayela ukuthi ulisebenzise ngokungaxhunyiwe, buyela emuva ku-inthanethi, chofoza ngakwesokudla ifayela, bese ukhethe inketho ye-<ph name="OFFLINE_CHECKBOX_NAME" />.</translation>
 <translation id="6164412158936057769">Izimvemvane</translation>
 <translation id="6165508094623778733">Funda kabanzi</translation>
 <translation id="6170470584681422115">Isemishi</translation>
-<translation id="6187719147498869044">Isi-Hungarian</translation>
+<translation id="6187719147498869044">Hungarian</translation>
 <translation id="6189412234224385711">Vula nge-<ph name="EXTENSION_NAME" /></translation>
 <translation id="6198252989419008588">Guqula iphinikhodi</translation>
 <translation id="6199801702437275229">Ilindele ulwazi lesikhala...</translation>
@@ -612,7 +612,7 @@
 <translation id="6227235786875481728">Leli fayela alikwazanga ukudlalwa.</translation>
 <translation id="6241349547798190358">Isi-Dutch (Belgium)</translation>
 <translation id="6267547857941397424">Inethiwekhi <ph name="NETWORK_INDEX" /> ye-<ph name="NETWORK_COUNT" />, <ph name="PHONE_NAME" />, amandla esignali <ph name="SIGNAL_STRENGTH" />%, Ibhethri lefoni <ph name="BATTERY_STATUS" />%, xhuma</translation>
-<translation id="6269630227984243955">Isi-Malay</translation>
+<translation id="6269630227984243955">Malay</translation>
 <translation id="6287852322318138013">Khetha uhlelo lokusebenza ukuze livule leli fayela</translation>
 <translation id="6296410173147755564">I-PUK engavumelekile</translation>
 <translation id="6312403991423642364">Iphutha elingaziwa lenethiwekhi</translation>
@@ -635,7 +635,7 @@
 <translation id="6495925982925244349">Inethiwekhi <ph name="NETWORK_INDEX" /> ye-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="SECURITY_STATUS" />, <ph name="CONNECTION_STATUS" />, amandla esignali <ph name="SIGNAL_STRENGTH" />%, kuphethwe umlawuli wakho, imininingwane</translation>
 <translation id="649877868557234318">Ikhipha i-<ph name="FILE_NAME" /> ku-<ph name="FOLDER_NAME" /></translation>
 <translation id="6499681088828539489">Ungavumeli abammeleli kumanethiwekhi abiwe</translation>
-<translation id="6509122719576673235">Isi-Norwegian</translation>
+<translation id="6509122719576673235">Norwegian</translation>
 <translation id="6528513914570774834">Vumela abanye abasebenzisi bale divayisi ukuthi basebenzise le nethiwekhi</translation>
 <translation id="653019979737152879">Ivumelanisa i-<ph name="FILE_NAME" />...</translation>
 <translation id="6549689063733911810">Okwakamuva</translation>
@@ -666,7 +666,7 @@
 <translation id="6825883775269213504">Isi-Russian</translation>
 <translation id="6847101934483209767">Isusiwe i-<ph name="ENTRY_NAME" /> kusuka okhethweni.</translation>
 <translation id="6856459657722366306">Inethiwkehi <ph name="NETWORK_INDEX" /> ye-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="NETWORK_PROVIDER_NAME" />, <ph name="CONNECTION_STATUS" />, amandla esignali <ph name="SIGNAL_STRENGTH" />%, imininingwane</translation>
-<translation id="6861394552169064235">Isi-Persian</translation>
+<translation id="6861394552169064235">Persian</translation>
 <translation id="6862635236584086457">Wonke amafayela alondolozwe kule folda enziwa isipele ngokuzenzakalelayo ku-inthanethi</translation>
 <translation id="6864328437977279120">Isi-Sanskrit</translation>
 <translation id="6874758081814639712">Umuntu owenza i-tai chi</translation>
@@ -698,7 +698,7 @@
 <translation id="6998711733709403587"><ph name="SELCTED_FOLDERS_COUNT" /> amafolda akhethiwe</translation>
 <translation id="7012943028104619157"><ph name="ROOT_TITLE" /> (<ph name="ROOT_SUMMARY" />)</translation>
 <translation id="7014174261166285193">Ukufakwa kuhlulekile.</translation>
-<translation id="7031639531908619281">Isi-Turkish</translation>
+<translation id="7031639531908619281">Turkish</translation>
 <translation id="7037472120706603960">Isi-Tamil (Ukuguqulwa kwamaletha)</translation>
 <translation id="7040138676081995583">Vula nge...</translation>
 <translation id="7048024426273850086">Inethiwekhi ye-<ph name="NETWORK_INDEX" /> kwangu-<ph name="NETWORK_COUNT" />, <ph name="PHONE_NAME" />, <ph name="PROVIDER_NAME" />, Amandla Esignali <ph name="SIGNAL_STRENGTH" />%, Ibhethri Lefoni <ph name="BATTERY_STATUS" />%, Xhuma</translation>
@@ -706,7 +706,7 @@
 <translation id="7075931588889865715">Isi-Thai esinekhibhodi ye-TIS 820-2531</translation>
 <translation id="708278670402572152">Nqamula ukuze unike amandla ukuskena</translation>
 <translation id="7086590977277044826">Isi-Tamil esinekhibhodi ye-InScript</translation>
-<translation id="7103992300314999525">Isi-Macedonian</translation>
+<translation id="7103992300314999525"> Macedonian</translation>
 <translation id="7106346894903675391">Thenga isitoreji esiningi...</translation>
 <translation id="7126604456862387217">'&lt;b&gt;<ph name="SEARCH_STRING" />&lt;/b&gt;' - &lt;em&gt;iDrayivu yokusesha&lt;/em&gt;</translation>
 <translation id="7135561821015524160">I-Kannada Phonetic</translation>
@@ -747,7 +747,7 @@
 <translation id="7495372004724182530">I-Malayalam Phonetic</translation>
 <translation id="7505167922889582512">Bonisa amafayela afihliwe</translation>
 <translation id="7514365320538308">Landa</translation>
-<translation id="751507702149411736">Isi-Belarusian</translation>
+<translation id="751507702149411736">Belarusian</translation>
 <translation id="7532029025027028521">Ukuguqulwa kwamaletha esi-Persian</translation>
 <translation id="7544830582642184299">Nikeza i-Linux imvume yezinhlelo zokusebenza ukufinyelela amafayela ku-Google Drayivu yakho. Izinguquko zizovumelanisa kwamanye amadivayisi akho.</translation>
 <translation id="7544853251252956727">Shova</translation>
@@ -767,17 +767,17 @@
 <translation id="7654209398114106148">Ihambisa izinto ezingu-<ph name="NUMBER_OF_ITEMS" />...</translation>
 <translation id="7655441028674523381">Finyelela kalula kokuthi Izithombe ze-Google</translation>
 <translation id="7658239707568436148">Khansela</translation>
-<translation id="7663224033570512922">Isi-Hindi</translation>
+<translation id="7663224033570512922">Hindi</translation>
 <translation id="7693909743393669729">Ukufometha idrayivu kuzosula yonke idatha egcinwe kuyo kuphinde kususe zonke izingxenye ezikhona, okufaka zonke izingxenye okungenzeka zingabonakali. Lesi senzo asikwazi ukuhlehliswa.</translation>
 <translation id="7695430100978772476">Ayikwazanga ukufometha i-<ph name="DRIVE_NAME" /></translation>
-<translation id="770015031906360009">Isi-Greek</translation>
+<translation id="770015031906360009">Greek</translation>
 <translation id="7705251383879779343">kukopishwe okungu-<ph name="FILE_NAME" />.</translation>
 <translation id="7711920809702896782">Ulwazi lwesithombe</translation>
 <translation id="7724603315864178912">Sika</translation>
 <translation id="7730494089396812859">Bonisa imininingwane yesipele samafu</translation>
 <translation id="7732111077498238432">Inethiwekhi ilawulwa inqubomgomo</translation>
 <translation id="7748626145866214022">Izinketho eziningi ezitholakala kubha yesenzo. Cindezela ku-Alt + A ukuze ugxilise ibha yesenzo.</translation>
-<translation id="7760449188139285140">Isi-Chinese Wubi</translation>
+<translation id="7760449188139285140">Chinese Wubi</translation>
 <translation id="7765158879357617694">Hambisa</translation>
 <translation id="7774365994322694683">Inyoni</translation>
 <translation id="7788080748068240085">Ukuze ulondoloze i-"<ph name="FILE_NAME" />" ngokungaxhunyiwe ku-inthanethi kuzomele ukhulule ngokungeziwe okungu-<ph name="TOTAL_FILE_SIZE" /> kwesikhala:<ph name="MARKUP_1" />
@@ -811,10 +811,10 @@
 <translation id="7928710562641958568">Khipha idivayisi</translation>
 <translation id="7943385054491506837">I-US Colemak</translation>
 <translation id="7953739707111622108">Idivayisi ayikwazi ukuvulwa ngoba isistimu yefayela ayiboniwe.</translation>
-<translation id="7969525169268594403">Isi-Slovenian</translation>
-<translation id="7972920761225148017">Isi-French (Switzerland)</translation>
+<translation id="7969525169268594403">Slovenian</translation>
+<translation id="7972920761225148017">French (Switzerland)</translation>
 <translation id="7973962044839454485">Ukuqinisekisa kwe-PPP kuhlulekile ngenxa yegama lomsebenzisi elingalungile noma iphasiwedi</translation>
-<translation id="7980421588063892270">I-English (US) enekhibhodi ye-Colemak</translation>
+<translation id="7980421588063892270">English (US) enekhibhodi ye-Colemak</translation>
 <translation id="8000066093800657092">Ayikho inethiwekhi</translation>
 <translation id="8008366997883261463">I-Jack Russell Terrier</translation>
 <translation id="8028993641010258682">Usayizi</translation>
@@ -828,14 +828,14 @@
 <translation id="8087576439476816834">Dawuniloda, <ph name="PROFILE_NAME" /></translation>
 <translation id="8106045200081704138">Kwabiwe nami</translation>
 <translation id="8116072619078571545">Amanzi e-ice</translation>
-<translation id="8128733386027980860">I-English (UK enekhibhodi ye-Dvorak</translation>
+<translation id="8128733386027980860">English (UK enekhibhodi ye-Dvorak</translation>
 <translation id="8137331602592933310">I-"<ph name="FILENAME" />" yabiwe nawe. Awukwazi ukuyisusa ngoba akuyona eyakho.</translation>
 <translation id="813913629614996137">Iyaqalisa...</translation>
 <translation id="8147028810663464959">Ububanzi bezinhlamvu Bugcwele</translation>
 <translation id="8151638057146502721">Lungiselela</translation>
 <translation id="8154842056504218462">Ukhethe konke okungenayo.</translation>
 <translation id="8157684860301034423">Yehlulekile ukubuyisa ulwazi lohlelo lokusebenza.</translation>
-<translation id="8175731104491895765">Isi-French (Belgium)</translation>
+<translation id="8175731104491895765">French (Belgium)</translation>
 <translation id="8179976553408161302">Faka</translation>
 <translation id="8193175696669055101">Imodeli yedivayisi</translation>
 <translation id="8208580316430297579">Umsebenzi wobuciko</translation>
@@ -849,7 +849,7 @@
 <translation id="8280151743281770066">Ifonethikhi yesi-Armenian</translation>
 <translation id="8294431847097064396">Umthombo</translation>
 <translation id="8297012244086013755">Isethi ye-Hangul 3 (Akekho u-Shift)</translation>
-<translation id="8299269255470343364">Isi-Japanese</translation>
+<translation id="8299269255470343364">Japanese</translation>
 <translation id="8300849813060516376">I-OTASP ihlulekile</translation>
 <translation id="8312871300878166382">Namathisela kufolda</translation>
 <translation id="8329978297633540474">Umbhalo osobala</translation>
@@ -858,7 +858,7 @@
 <translation id="8336153091935557858">Izolo ngo-<ph name="YESTERDAY_DAYTIME" /></translation>
 <translation id="8342318071240498787">Ifayela noma uhla lwemibhalo olunegama elifanayo seluvele likhona</translation>
 <translation id="8372369524088641025">Ukhiye omubi we-WEP</translation>
-<translation id="8372852072747894550">Isi-Greek</translation>
+<translation id="8372852072747894550">Greek</translation>
 <translation id="8386903983509584791">Ukuskena kuphelile</translation>
 <translation id="8387733224523483503">I-<ph name="FILE_NAME" /> ithukululiwe.</translation>
 <translation id="8395901698320285466">Ubukhulu</translation>
@@ -879,29 +879,29 @@
 <translation id="8492972329130824181">Inethiwekhi yasekhaya ayitholakali. Ukuzulazula kwedatha yeselula kufanele kunikwe amandla ukuze kuxhume.</translation>
 <translation id="8499098729323186194">Ikhipha izinto ezingu-<ph name="NUMBER_OF_ITEMS" />...</translation>
 <translation id="8521441079177373948">I-UK</translation>
-<translation id="853494022971700746">Isi-French (France)</translation>
+<translation id="853494022971700746">French (France)</translation>
 <translation id="8540608333167683902">Inethiwekhi <ph name="NETWORK_INDEX" /> ye-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="CONNECTION_STATUS" />, amandla esignali <ph name="SIGNAL_STRENGTH" />%, imininingwane</translation>
-<translation id="8545476925160229291">I-English(US)</translation>
+<translation id="8545476925160229291">English(US)</translation>
 <translation id="854655314928502177">I-URL yokutholakala kommeleli ozenzakalelayo wewebhu</translation>
 <translation id="8549186985808798022">Isi-Italian</translation>
-<translation id="8551494947769799688">Isi-Latvian</translation>
+<translation id="8551494947769799688">Latvian</translation>
 <translation id="8560515948038859357">Isi-Cantonese</translation>
 <translation id="8561206103590473338">Indlovu</translation>
 <translation id="8566466896628108558">Inethiwekhi engu-<ph name="NETWORK_INDEX" /> kwezingu-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="SECURITY_STATUS" />, Amandla Wesinglai<ph name="SIGNAL_STRENGTH" />%, Kuvinjelwe Umphathi wakho, Imininingwane</translation>
 <translation id="8569764466147087991">Khetha ifayela okumele ulivule</translation>
-<translation id="8577897833047451336">Isi-Croatia</translation>
-<translation id="8578308463707544055">Isi-Indonesia</translation>
+<translation id="8577897833047451336">Croatian</translation>
+<translation id="8578308463707544055">Indonesian</translation>
 <translation id="8579285237314169903">Ivumelanisa izinto ezingu-<ph name="NUMBER_OF_FILES" />...</translation>
 <translation id="8600173386174225982">Uhlu lwefayela lushintshele ekubukeni kwesithonjana.</translation>
 <translation id="8601932370724196034">Ifayela lesithombe se-Crostini</translation>
-<translation id="8609695766746872526">Isi-Icelandic</translation>
+<translation id="8609695766746872526">Icelandic</translation>
 <translation id="863903787380594467">Iphinikhodi engalungile. Unemizamo engu-<ph name="RETRIES" /> esele.</translation>
 <translation id="8639391553632924850"><ph name="INPUT_LABEL" /> - Imbobo</translation>
 <translation id="8656768832129462377">Ungahloli</translation>
 <translation id="8688591111840995413">Iphasiwedi embi</translation>
 <translation id="8698464937041809063">Ukudweba kwe-Google</translation>
 <translation id="8712637175834984815">Ngiyitholile</translation>
-<translation id="8713112442029511308">Isi-Maltese</translation>
+<translation id="8713112442029511308">Maltese</translation>
 <translation id="8714406895390098252">Ibhayisikili</translation>
 <translation id="8719721339511222681">Okukhethiwe <ph name="ENTRY_NAME" />.</translation>
 <translation id="872537912056138402">Isi-Croatian</translation>
@@ -913,18 +913,18 @@
 <translation id="8802459921616481935">Hambisa Kudoti</translation>
 <translation id="8808686172382650546">Ikati</translation>
 <translation id="8810671769985673465">Ukuzipha kwehlulekile, into ikhona: "<ph name="FILE_NAME" />"</translation>
-<translation id="8813284582615685103">Isi-Spanish (I-Spain)</translation>
+<translation id="8813284582615685103">Spanish (I-Spain)</translation>
 <translation id="8834164572807951958">Amalungu e-'<ph name="DESTINATION_NAME" />' azothola ukufinyelela kwikhophi yalezi zinto.</translation>
-<translation id="8857149712089373752">Isi-Nepali ngekhibhodi ye-Phonetic</translation>
+<translation id="8857149712089373752">Nepali ngekhibhodi ye-Phonetic</translation>
 <translation id="8860454412039442620">Isipredishithi se-Excel</translation>
 <translation id="8866284467018526531">Ukuguqulwa kwamaletha we-Arabic</translation>
 <translation id="8874184842967597500">Ayixhunyiwe</translation>
-<translation id="8900820606136623064">Isi-Hungarian</translation>
+<translation id="8900820606136623064">Hungarian</translation>
 <translation id="8903931173357132290">Thola iziqu</translation>
 <translation id="8912078710089354287">Inja enyakazisa umsila</translation>
 <translation id="8919081441417203123">Isi-Danish</translation>
 <translation id="8965697826696209160">Asikho isikhala esanele.</translation>
-<translation id="8997962250644902079">Isi-Chinese (Traditional) Pinyin</translation>
+<translation id="8997962250644902079">Chinese (Traditional) Pinyin</translation>
 <translation id="9003940392834790328">Inethiwekhi <ph name="NETWORK_INDEX" /> ye-<ph name="NETWORK_COUNT" />, <ph name="NETWORK_NAME" />, <ph name="CONNECTION_STATUS" />, amandla esignali <ph name="SIGNAL_STRENGTH" />%, kuphethwe umlawuli wakho, imininingwane</translation>
 <translation id="9017798300203431059">Ifonethiki yesi-Russian</translation>
 <translation id="9034924485347205037">Amafayela e-Linux</translation>
@@ -947,10 +947,10 @@
 <translation id="9153934054460603056">Londoloza ubunikazi nephasiwedi</translation>
 <translation id="9171921933192916600">Othanda izincwadi</translation>
 <translation id="9172592259078059678">Ukuguqulwa kwamaletha kwesi-Gujarati</translation>
-<translation id="9173120999827300720">I-English (US enekhibhodi yamazwe ngamazwe</translation>
+<translation id="9173120999827300720">English (US enekhibhodi yamazwe ngamazwe</translation>
 <translation id="9174050671906956834">Izinto ezikudoti zisuswa ingunaphakade ngemva kwezinsuku ezingama-30.</translation>
 <translation id="9183302530794969518">Google Amadokhumenti</translation>
-<translation id="9189836632794948435">Isi-Kazakh</translation>
+<translation id="9189836632794948435">Kazakh</translation>
 <translation id="9200427192836333033">Izinto ezingu-<ph name="NUMBER_OF_ITEMS" /> zithukululiwe.</translation>
 <translation id="9213073329713032541">Ukufaka kuqaliswe ngempumelelo.</translation>
 <translation id="9219103736887031265">Izithombe</translation>
@@ -960,7 +960,7 @@
 <translation id="943972244133411984">Kushintshwe ngu-</translation>
 <translation id="945522503751344254">Thumela impendulo</translation>
 <translation id="947144732524271678">Ibanga elikhethiwe lokungenayo kwe-<ph name="ENTRY_COUNT" /> kusuka ku-<ph name="FROM_ENTRY_NAME" /> kuya ku-<ph name="TO_ENTRY_NAME" />.</translation>
-<translation id="965477715979482472">I-English (South Africa)</translation>
+<translation id="965477715979482472">English (South Africa)</translation>
 <translation id="981121421437150478">Ayixhunyiwe ku-inthanethi</translation>
 <translation id="988685240266037636">Ifayela elinegama "<ph name="FILE_NAME" />" selivele likhona. Ingabe ufuna ukuyimiselela?</translation>
 <translation id="992401651319295351">Unemizamo engu-<ph name="RETRIES" /> esele. Ngeke ukwazi ukusebenzisa le nethiwekhi kuze kube yilapho usetha Iphinikhodi entsha.</translation>
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn
index 18cce0c..c3ba41b 100644
--- a/ui/display/BUILD.gn
+++ b/ui/display/BUILD.gn
@@ -184,6 +184,8 @@
     sources += [
       "mac/test/test_screen_mac.h",
       "mac/test/test_screen_mac.mm",
+      "mac/test/virtual_display_mac_util.h",
+      "mac/test/virtual_display_mac_util.mm",
     ]
   }
 
diff --git a/ui/display/mac/test/virtual_display_mac_util.h b/ui/display/mac/test/virtual_display_mac_util.h
new file mode 100644
index 0000000..829c918c
--- /dev/null
+++ b/ui/display/mac/test/virtual_display_mac_util.h
@@ -0,0 +1,27 @@
+// 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 UI_DISPLAY_MAC_TEST_VIRTUAL_DISPLAY_MAC_UTIL_H_
+#define UI_DISPLAY_MAC_TEST_VIRTUAL_DISPLAY_MAC_UTIL_H_
+
+namespace gfx {
+class Size;
+}  // namespace gfx
+
+namespace display::test {
+
+// This interface creates system-level virtual displays to support the automated
+// integration testing of display information and window placement APIs in
+// multi-screen device environments. It updates the displays that the normal mac
+// screen impl sees, but not `TestScreenMac`.
+class VirtualDisplayMacUtil {
+ public:
+  static void AddDisplay(int display_id, const gfx::Size& size);
+  static void RemoveDisplay(int display_id);
+  static bool ShouldSkip();
+};
+
+}  // namespace display::test
+
+#endif  // UI_DISPLAY_MAC_TEST_VIRTUAL_DISPLAY_MAC_UTIL_H_
diff --git a/ui/display/mac/test/virtual_display_mac_util.mm b/ui/display/mac/test/virtual_display_mac_util.mm
new file mode 100644
index 0000000..717f869
--- /dev/null
+++ b/ui/display/mac/test/virtual_display_mac_util.mm
@@ -0,0 +1,247 @@
+// 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 "ui/display/mac/test/virtual_display_mac_util.h"
+
+#include <CoreGraphics/CoreGraphics.h>
+#import <Foundation/Foundation.h>
+
+#include <map>
+
+#include "base/check.h"
+#include "base/mac/scoped_nsobject.h"
+#include "ui/gfx/geometry/size.h"
+
+// These interfaces were generated from CoreGraphics binaries.
+API_AVAILABLE(macos(10.14))
+@interface CGVirtualDisplay : NSObject {
+  unsigned int _vendorID;
+  unsigned int _productID;
+  unsigned int _serialNum;
+  NSString* _name;
+  struct CGSize _sizeInMillimeters;
+  unsigned int _maxPixelsWide;
+  unsigned int _maxPixelsHigh;
+  struct CGPoint _redPrimary;
+  struct CGPoint _greenPrimary;
+  struct CGPoint _bluePrimary;
+  struct CGPoint _whitePoint;
+  id _queue;
+  id _terminationHandler;
+  unsigned int _displayID;
+  unsigned int _hiDPI;
+  NSArray* _modes;
+}
+
+@property(readonly, nonatomic)
+    unsigned int vendorID;  // @synthesize vendorID=_vendorID;
+@property(readonly, nonatomic)
+    unsigned int productID;  // @synthesize productID=_productID;
+@property(readonly, nonatomic)
+    unsigned int serialNum;  // @synthesize serialNum=_serialNum;
+@property(readonly, nonatomic) NSString* name;  // @synthesize name=_name;
+@property(readonly, nonatomic) struct CGSize
+    sizeInMillimeters;  // @synthesize sizeInMillimeters=_sizeInMillimeters;
+@property(readonly, nonatomic)
+    unsigned int maxPixelsWide;  // @synthesize maxPixelsWide=_maxPixelsWide;
+@property(readonly, nonatomic)
+    unsigned int maxPixelsHigh;  // @synthesize maxPixelsHigh=_maxPixelsHigh;
+@property(readonly, nonatomic)
+    struct CGPoint redPrimary;  // @synthesize redPrimary=_redPrimary;
+@property(readonly, nonatomic)
+    struct CGPoint greenPrimary;  // @synthesize greenPrimary=_greenPrimary;
+@property(readonly, nonatomic)
+    struct CGPoint bluePrimary;  // @synthesize bluePrimary=_bluePrimary;
+@property(readonly, nonatomic)
+    struct CGPoint whitePoint;            // @synthesize whitePoint=_whitePoint;
+@property(readonly, nonatomic) id queue;  // @synthesize queue=_queue;
+@property(readonly, nonatomic) id
+    terminationHandler;  // @synthesize terminationHandler=_terminationHandler;
+@property(readonly, nonatomic)
+    unsigned int displayID;  // @synthesize displayID=_displayID;
+@property(readonly, nonatomic) unsigned int hiDPI;  // @synthesize hiDPI=_hiDPI;
+@property(readonly, nonatomic) NSArray* modes;      // @synthesize modes=_modes;
+- (BOOL)applySettings:(id)arg1;
+- (void)dealloc;
+- (id)initWithDescriptor:(id)arg1;
+
+@end
+
+// These interfaces were generated from CoreGraphics binaries.
+API_AVAILABLE(macos(10.14))
+@interface CGVirtualDisplayDescriptor : NSObject {
+  unsigned int _vendorID;
+  unsigned int _productID;
+  unsigned int _serialNum;
+  NSString* _name;
+  struct CGSize _sizeInMillimeters;
+  unsigned int _maxPixelsWide;
+  unsigned int _maxPixelsHigh;
+  struct CGPoint _redPrimary;
+  struct CGPoint _greenPrimary;
+  struct CGPoint _bluePrimary;
+  struct CGPoint _whitePoint;
+  id _queue;
+  id _terminationHandler;
+}
+
+@property(nonatomic) unsigned int vendorID;  // @synthesize vendorID=_vendorID;
+@property(nonatomic)
+    unsigned int productID;  // @synthesize productID=_productID;
+@property(nonatomic)
+    unsigned int serialNum;  // @synthesize serialNum=_serialNum;
+@property(strong, nonatomic) NSString* name;  // @synthesize name=_name;
+@property(nonatomic) struct CGSize
+    sizeInMillimeters;  // @synthesize sizeInMillimeters=_sizeInMillimeters;
+@property(nonatomic)
+    unsigned int maxPixelsWide;  // @synthesize maxPixelsWide=_maxPixelsWide;
+@property(nonatomic)
+    unsigned int maxPixelsHigh;  // @synthesize maxPixelsHigh=_maxPixelsHigh;
+@property(nonatomic)
+    struct CGPoint redPrimary;  // @synthesize redPrimary=_redPrimary;
+@property(nonatomic)
+    struct CGPoint greenPrimary;  // @synthesize greenPrimary=_greenPrimary;
+@property(nonatomic)
+    struct CGPoint bluePrimary;  // @synthesize bluePrimary=_bluePrimary;
+@property(nonatomic)
+    struct CGPoint whitePoint;          // @synthesize whitePoint=_whitePoint;
+@property(retain, nonatomic) id queue;  // @synthesize queue=_queue;
+@property(copy, nonatomic) id
+    terminationHandler;  // @synthesize terminationHandler=_terminationHandler;
+- (void)dealloc;
+- (id)init;
+- (id)dispatchQueue;
+- (void)setDispatchQueue:(id)arg1;
+
+@end
+
+// These interfaces were generated from CoreGraphics binaries.
+API_AVAILABLE(macos(10.14))
+@interface CGVirtualDisplayMode : NSObject {
+  unsigned int _width;
+  unsigned int _height;
+  double _refreshRate;
+}
+
+@property(readonly, nonatomic) unsigned int width;  // @synthesize width=_width;
+@property(readonly, nonatomic)
+    unsigned int height;  // @synthesize height=_height;
+@property(readonly, nonatomic)
+    double refreshRate;  // @synthesize refreshRate=_refreshRate;
+- (id)initWithWidth:(unsigned int)arg1
+             height:(unsigned int)arg2
+        refreshRate:(double)arg3;
+
+@end
+
+// These interfaces were generated from CoreGraphics binaries.
+API_AVAILABLE(macos(10.14))
+@interface CGVirtualDisplaySettings : NSObject {
+  NSArray* _modes;
+  unsigned int _hiDPI;
+}
+
+@property(strong, nonatomic) NSArray* modes;  // @synthesize modes=_modes;
+@property(nonatomic) unsigned int hiDPI;      // @synthesize hiDPI=_hiDPI;
+- (void)dealloc;
+- (id)init;
+
+@end
+
+namespace {
+
+static constexpr int kRetinaPPI = 220;
+
+// A global singleton that tracks the current set of mocked displays.
+std::map<int, base::scoped_nsobject<CGVirtualDisplay>> g_display_map
+    API_AVAILABLE(macos(10.14));
+
+// A helper function for creating virtual display and return CGVirtualDisplay
+// object.
+base::scoped_nsobject<CGVirtualDisplay> createVirtualDisplay(int width,
+                                                             int height,
+                                                             int ppi,
+                                                             BOOL hiDPI,
+                                                             NSString* name)
+    API_AVAILABLE(macos(10.14)) {
+  base::scoped_nsobject<CGVirtualDisplaySettings> settings(
+      [[CGVirtualDisplaySettings alloc] init]);
+  [settings setHiDPI:hiDPI];
+
+  base::scoped_nsobject<CGVirtualDisplayDescriptor> descriptor(
+      [[CGVirtualDisplayDescriptor alloc] init]);
+  [descriptor
+      setQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)];
+  [descriptor setName:name];
+
+  // See System Preferences > Displays > Color > Open Profile > Apple display
+  // native information
+  [descriptor setWhitePoint:CGPointMake(0.3125, 0.3291)];
+  [descriptor setBluePrimary:CGPointMake(0.1494, 0.0557)];
+  [descriptor setGreenPrimary:CGPointMake(0.2559, 0.6983)];
+  [descriptor setRedPrimary:CGPointMake(0.6797, 0.3203)];
+  [descriptor setMaxPixelsHigh:height];
+  [descriptor setMaxPixelsWide:width];
+  [descriptor
+      setSizeInMillimeters:CGSizeMake(25.4 * width / ppi, 25.4 * height / ppi)];
+  [descriptor setSerialNum:0];
+  [descriptor setProductID:0];
+  [descriptor setVendorID:0];
+
+  base::scoped_nsobject<CGVirtualDisplay> display(
+      [[CGVirtualDisplay alloc] initWithDescriptor:descriptor]);
+
+  if ([settings hiDPI]) {
+    width /= 2;
+    height /= 2;
+  }
+  base::scoped_nsobject<CGVirtualDisplayMode> mode([[CGVirtualDisplayMode alloc]
+      initWithWidth:width
+             height:height
+        refreshRate:60]);
+  [settings setModes:@[ mode ]];
+
+  if (![display applySettings:settings])
+    return base::scoped_nsobject<CGVirtualDisplay>();
+
+  return display;
+}
+
+}  // namespace
+
+namespace display::test {
+
+// static
+void VirtualDisplayMacUtil::AddDisplay(int display_id, const gfx::Size& size) {
+  if (@available(macos 10.14, *)) {
+    NSString* display_name =
+        [NSString stringWithFormat:@"Virtual Display #%d", display_id];
+    base::scoped_nsobject<CGVirtualDisplay> display =
+        createVirtualDisplay(size.width(), size.height(), kRetinaPPI,
+                             /*hiDPI=*/false, display_name);
+
+    DCHECK(!g_display_map[display_id]);
+    g_display_map[display_id] = display;
+  }
+}
+
+// static
+void VirtualDisplayMacUtil::RemoveDisplay(int display_id) {
+  if (@available(macos 10.14, *)) {
+    auto it = g_display_map.find(display_id);
+
+    DCHECK(it != g_display_map.end());
+    g_display_map.erase(it);
+  }
+}
+
+// static
+bool VirtualDisplayMacUtil::ShouldSkip() {
+  if (@available(macos 10.14, *)) {
+    return false;
+  }
+  return true;
+}
+
+}  // namespace display::test
diff --git a/ui/display/manager/managed_display_info.cc b/ui/display/manager/managed_display_info.cc
index 306b019..78e7167a 100644
--- a/ui/display/manager/managed_display_info.cc
+++ b/ui/display/manager/managed_display_info.cc
@@ -168,10 +168,10 @@
   const int kDefaultHostWindowHeight = 768;
   gfx::Rect bounds_in_native(kDefaultHostWindowX, kDefaultHostWindowY,
                              kDefaultHostWindowWidth, kDefaultHostWindowHeight);
-  std::string main_spec = spec;
+  base::StringPiece main_spec = spec;
 
   float zoom_factor = 1.0f;
-  std::vector<std::string> parts = base::SplitString(
+  std::vector<base::StringPiece> parts = base::SplitStringPiece(
       main_spec, "@", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
   if (parts.size() == 2) {
     double scale_in_double = 0;
@@ -180,17 +180,16 @@
     main_spec = parts[0];
   }
 
-  parts = base::SplitString(main_spec, "/", base::KEEP_WHITESPACE,
-                            base::SPLIT_WANT_NONEMPTY);
+  parts = base::SplitStringPiece(main_spec, "/", base::KEEP_WHITESPACE,
+                                 base::SPLIT_WANT_NONEMPTY);
   Display::Rotation rotation(Display::ROTATE_0);
   bool has_overscan = false;
   bool has_hdr = false;
   if (!parts.empty()) {
     main_spec = parts[0];
     if (parts.size() >= 2) {
-      std::string options = parts[1];
-      for (size_t i = 0; i < options.size(); ++i) {
-        char c = options[i];
+      base::StringPiece options = parts[1];
+      for (char c : options) {
         switch (c) {
           case 'o':
             has_overscan = true;
@@ -216,32 +215,37 @@
   ManagedDisplayModeList display_modes;
 
   if (!main_spec.empty()) {
-    GetDisplayBounds(main_spec, &bounds_in_native, &device_scale_factor);
+    GetDisplayBounds(std::string(main_spec), &bounds_in_native,
+                     &device_scale_factor);
 
-    parts = base::SplitString(main_spec, "#", base::KEEP_WHITESPACE,
-                              base::SPLIT_WANT_NONEMPTY);
+    parts = base::SplitStringPiece(main_spec, "#", base::KEEP_WHITESPACE,
+                                   base::SPLIT_WANT_NONEMPTY);
     if (parts.size() == 2) {
       size_t native_mode = 0;
       int largest_area = -1;
       float highest_refresh_rate = -1.0f;
       main_spec = parts[0];
-      std::string resolution_list = parts[1];
-      parts = base::SplitString(resolution_list, "|", base::KEEP_WHITESPACE,
-                                base::SPLIT_WANT_NONEMPTY);
+      base::StringPiece resolution_list = parts[1];
+      parts =
+          base::SplitStringPiece(resolution_list, "|", base::KEEP_WHITESPACE,
+                                 base::SPLIT_WANT_NONEMPTY);
       for (size_t i = 0; i < parts.size(); ++i) {
         gfx::Size size;
         float refresh_rate = 60.0f;
         bool is_interlaced = false;
 
         gfx::Rect mode_bounds;
-        std::vector<std::string> resolution = base::SplitString(
+        std::vector<base::StringPiece> resolution = base::SplitStringPiece(
             parts[i], "%", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
         float device_scale_factor_for_mode = device_scale_factor;
-        GetDisplayBounds(resolution[0], &mode_bounds,
+        GetDisplayBounds(std::string(resolution[0]), &mode_bounds,
                          &device_scale_factor_for_mode);
         size = mode_bounds.size();
-        if (resolution.size() > 1)
-          sscanf(resolution[1].c_str(), "%f", &refresh_rate);
+        if (resolution.size() > 1) {
+          double refresh_rate_in_double = 0.0;
+          if (base::StringToDouble(resolution[1], &refresh_rate_in_double))
+            refresh_rate = refresh_rate_in_double;
+        }
         if (size.GetArea() >= largest_area &&
             refresh_rate > highest_refresh_rate) {
           // Use mode with largest area and highest refresh rate as native.
diff --git a/ui/events/ozone/evdev/BUILD.gn b/ui/events/ozone/evdev/BUILD.gn
index ffb0749..93eff65 100644
--- a/ui/events/ozone/evdev/BUILD.gn
+++ b/ui/events/ozone/evdev/BUILD.gn
@@ -215,7 +215,7 @@
 
   visibility += [
     "//ash/webui/diagnostics_ui/backend:*",
-    "//chromeos/services/cros_healthd/*",
+    "//chromeos/ash/services/cros_healthd/*",
     "//ui/chromeos/*",
   ]
 }
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn
index e42c5db9..2f7f49f7 100644
--- a/ui/file_manager/BUILD.gn
+++ b/ui/file_manager/BUILD.gn
@@ -57,14 +57,14 @@
 group("unit_test_data") {
   testonly = true
   deps = [
-    "file_manager/background/js:js_test_gen_html_modules",
-    "file_manager/common/js:js_test_gen_html_modules",
-    "file_manager/foreground/elements:js_test_gen_html_modules",
-    "file_manager/foreground/js:js_test_gen_html_modules",
-    "file_manager/foreground/js/metadata:js_test_gen_html_modules",
-    "file_manager/foreground/js/ui:js_test_gen_html_modules",
-    "file_manager/foreground/js/ui/banners:js_test_gen_html_modules",
-    "image_loader:js_test_gen_html_modules",
+    "file_manager/background/js:js_test_type_check",
+    "file_manager/common/js:js_test_type_check",
+    "file_manager/foreground/elements:js_test_type_check",
+    "file_manager/foreground/js:js_test_type_check",
+    "file_manager/foreground/js/metadata:js_test_type_check",
+    "file_manager/foreground/js/ui:js_test_type_check",
+    "file_manager/foreground/js/ui/banners:js_test_type_check",
+    "image_loader:js_test_type_check",
   ]
   data_deps = [ "image_loader:copy_from_filesapp" ]
 }
@@ -83,10 +83,10 @@
 
   deps = [
     "//ui/file_manager/file_manager/background/js:js_modules",
-    "//ui/file_manager/file_manager/background/js:main_background.m",
+    "//ui/file_manager/file_manager/background/js:main_background",
     "//ui/file_manager/file_manager/common/js:js_modules",
     "//ui/file_manager/file_manager/foreground/elements:web_components",
-    "//ui/file_manager/file_manager/foreground/js:deferred_elements.m",
+    "//ui/file_manager/file_manager/foreground/js:deferred_elements",
     "//ui/file_manager/file_manager/foreground/js:main",
   ]
 }
@@ -100,7 +100,7 @@
 
   deps = [
     "//ui/file_manager/audio_player/js:js_modules",
-    "//ui/file_manager/image_loader:background.m",
+    "//ui/file_manager/image_loader:background",
     "//ui/file_manager/image_loader:js_modules",
   ]
 }
@@ -164,7 +164,7 @@
     "audio_player/js/main.rollup.js",
     "audio_player/js/main_background.rollup.js",
     "audio_player/js/metadata_worker.rollup.js",
-    "audio_player/js/shared.m.rollup.js",
+    "audio_player/js/shared.rollup.js",
     "audio_player/js/runtime_loaded_test_util.rollup.js",
 
     # Fix broken images:
@@ -173,7 +173,7 @@
     "file_manager/images/files/ui/warning_banner_icon.svg",
     "file_manager/images/files/ui/menu_ng.svg",
 
-    "image_loader/background.m.rollup.js",
+    "image_loader/background.rollup.js",
   ]
 
   resource_path_rewrites = [
@@ -181,18 +181,18 @@
     "audio_player/js/main_background.rollup.js|audio_player/js/main_background.js",
     "audio_player/js/metadata_worker.rollup.js|audio_player/js/metadata_worker.js",
     "audio_player/js/runtime_loaded_test_util.rollup.js|audio_player/js/runtime_loaded_test_util.js",
-    "image_loader/background.m.rollup.js|image_loader/background.m.js",
+    "image_loader/background.rollup.js|image_loader/background.js",
   ]
 
   if (optimize_webui) {
     input_files += [
-      "file_manager/background/js/main_background.m.rollup.js",
+      "file_manager/background/js/main_background.rollup.js",
       "file_manager/background/js/runtime_loaded_test_util.rollup.js",
-      "file_manager/background/js/shared.m.rollup.js",
-      "file_manager/foreground/js/deferred_elements.m.rollup.js",
+      "file_manager/background/js/shared.rollup.js",
+      "file_manager/foreground/js/deferred_elements.rollup.js",
       "file_manager/foreground/js/main.rollup.js",
       "file_manager/foreground/js/metadata_dispatcher.rollup.js",
-      "file_manager/foreground/js/shared.m.rollup.js",
+      "file_manager/foreground/js/shared.rollup.js",
 
       "image_loader/image_orientation.js",
       "image_loader/lru_cache.js",
@@ -201,9 +201,9 @@
     ]
 
     resource_path_rewrites += [
-      "file_manager/background/js/main_background.m.rollup.js|file_manager/background/js/main_background.m.js",
+      "file_manager/background/js/main_background.rollup.js|file_manager/background/js/main_background.js",
       "file_manager/background/js/runtime_loaded_test_util.rollup.js|file_manager/background/js/runtime_loaded_test_util.js",
-      "file_manager/foreground/js/deferred_elements.m.rollup.js|file_manager/foreground/js/deferred_elements.m.js",
+      "file_manager/foreground/js/deferred_elements.rollup.js|file_manager/foreground/js/deferred_elements.js",
       "file_manager/foreground/js/main.rollup.js|file_manager/foreground/js/main.js",
       "file_manager/foreground/js/metadata_dispatcher.rollup.js|file_manager/foreground/js/metadata/metadata_dispatcher.js",
     ]
@@ -288,7 +288,6 @@
 
   input_files_base_dir = rebase_path(".", "//")
   input_files = unittest_files
-  deps = [ ":unit_test_data" ]
 }
 
 # GRD for the actual application files that are processed by TS compiler.
@@ -297,11 +296,6 @@
   grd_prefix = "file_manager_test"
   out_grd = "$target_gen_dir/tests_gen_resources.grdp"
 
-  input_files_base_dir = rebase_path(target_gen_dir, root_build_dir)
-  input_files = generated_test_htmls
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
-  deps = [
-    ":build_ts",
-    ":unit_test_data",
-  ]
+  deps = [ ":build_ts" ]
 }
diff --git a/ui/file_manager/audio_player/js/BUILD.gn b/ui/file_manager/audio_player/js/BUILD.gn
index 0185e68..c6b763b3 100644
--- a/ui/file_manager/audio_player/js/BUILD.gn
+++ b/ui/file_manager/audio_player/js/BUILD.gn
@@ -178,7 +178,7 @@
   js_out_files = [
     "main_background.rollup.js",
     "runtime_loaded_test_util.rollup.js",
-    "shared.m.rollup.js",
+    "shared.rollup.js",
   ]
 
   external_paths = [
diff --git a/ui/file_manager/base/gn/js_test_gen_html.gni b/ui/file_manager/base/gn/js_test_gen_html.gni
deleted file mode 100644
index c97899a9..0000000
--- a/ui/file_manager/base/gn/js_test_gen_html.gni
+++ /dev/null
@@ -1,107 +0,0 @@
-# Copyright 2019 The Chromium Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/js_unit_tests.gni")
-
-# Describes a list of js_unittest targets that will each have a generated HTML
-# file that imports the test JS module and adds the test* functions to the
-# window to be consumed by the test harness.
-#
-# A companion group target with a "_type_check_auto" suffix is also generated
-# with this template. This depends on a list of js_type_check(..) targets -- one
-# for # each test -- that will type check the test js file and its dependency
-# subtree.
-#
-# Must be declared after the js_library targets it depends on.
-#
-# Note js_type_check() is only in effect if `closure_compile` is set in gn args.
-#
-# Variables:
-#   deps:
-#     List of js_unittest targets to depend on
-#
-#   is_polymer3:
-#     Boolean indicating that it's a test for a Polymer 3 element, the only
-#     difference is the js_type_check() rule also has the is_polymer3=true.
-#
-#
-# Non-Polymer example:
-#   js_test_gen_html("folder_tests") {
-#     deps = [
-#       ":foo_unittest",
-#       ":bar_unittest",
-#       ":baz_unittest",
-#     ]
-#   }
-#
-#   group("closure_compile") {
-#     # ...
-#     ":folder_tests_type_check_auto".
-#   }
-#
-#   test("browser_tests") {
-#     # ...
-#     data_deps += [ "//folder:folder_tests" ]
-#   }
-#
-# Polymer example:
-#   js_test_gen_html("polymer_tests") {
-#     is_polymer3 = true
-#     deps = [
-#       ":element1_unittest",
-#     ]
-#   }
-#
-template("js_test_gen_html") {
-  html_gen_target_name = target_name + "_gen_html"
-  action_foreach(html_gen_target_name) {
-    script_path = "//ui/file_manager/base/gn/"
-    script = "$script_path/js_test_gen_html.py"
-    forward_variables_from(invoker, [ "deps" ])
-
-    testonly = true
-    sources = []
-    foreach(dep, deps) {
-      sources += get_target_outputs(dep)
-    }
-
-    outputs = [ "$target_gen_dir/{{source_name_part}}_gen.html" ]
-    args = [ "--output" ] + rebase_path(outputs, root_build_dir)
-    args += [
-      "--src_path",
-      rebase_path("//"),
-    ]
-    args += [ "--input" ] + [ "{{source}}" ]
-  }
-
-  type_check_deps = []
-  foreach(dep, invoker.deps) {
-    type_check_target_name = target_name + "_" + dep + "_type_check_auto"
-    type_check_deps += [ ":$type_check_target_name" ]
-    js_type_check(type_check_target_name) {
-      testonly = true
-      forward_variables_from(invoker,
-                             [
-                               "closure_flags",
-                               "is_polymer3",
-                             ])
-      deps = [ dep ]
-      if (defined(invoker.extra_deps)) {
-        deps += invoker.extra_deps
-      }
-    }
-  }
-
-  type_check_group_name = target_name + "_type_check_auto"
-  group(type_check_group_name) {
-    testonly = true
-    deps = type_check_deps
-  }
-
-  group(target_name) {
-    data = get_target_outputs(":$html_gen_target_name")
-    testonly = true
-    deps = [ ":$html_gen_target_name" ]
-  }
-}
diff --git a/ui/file_manager/base/gn/js_test_gen_html.py b/ui/file_manager/base/gn/js_test_gen_html.py
deleted file mode 100644
index 0454e2d0..0000000
--- a/ui/file_manager/base/gn/js_test_gen_html.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2019 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.
-"""Generates HTML file with all dependencies from a js_unittest build target."""
-
-import os
-import sys
-from argparse import ArgumentParser
-
-_HTML_FILE_START = r'''<!DOCTYPE html>'''
-_JS_MODULE = r'<script type="module" src="%s"></script>'
-_JS_MODULE_REGISTER_TESTS = r'''
-<script>
-  // Push all entities to global namespace to be visible to the test harness:
-  // ui/webui/resources/js/webui_resource_test.js
-  const js_module_url = '%s';
-  import(js_module_url).then(TestModule => {
-    for (const name in TestModule) {
-      window[name] = TestModule[name];
-    }
-  });
-</script>
-'''
-
-
-def _process_js_module(input_file, output_filename):
-    """Generates the HTML for a unittest based on JS Modules.
-
-  Args:
-    input_file: The path for the unittest JS module.
-    output_filename: The path/filename for HTML to be generated.
-  """
-
-    # Map //ui/file_manager files to test URL:
-    js_module_url = input_file.replace('ui/file_manager/',
-                                       'chrome://webui-test/', 1)
-
-    with open(output_filename, 'w') as out:
-        out.write(_HTML_FILE_START + '\n')
-
-        line = _JS_MODULE % (js_module_url)
-        out.write(line + '\n')
-
-        line = _JS_MODULE_REGISTER_TESTS % (js_module_url)
-        out.write(line + '\n')
-
-
-def main():
-    parser = ArgumentParser()
-    parser.add_argument('-s',
-                        '--src_path',
-                        help='Path to //src/ directory',
-                        required=True)
-    parser.add_argument(
-        '-i',
-        '--input',
-        help='Input dependency file generated by js_library.py',
-        required=True)
-    parser.add_argument(
-        '-o',
-        '--output',
-        help='Generated html output with flattened dependencies',
-        required=True)
-    parser.add_argument('-t', '--target_name', help='Test target name')
-    args = parser.parse_args()
-
-    # Convert from:
-    # gen/ui/file_manager/file_manager/common/js/example_unittest.m.js_library
-    # To:
-    # ui/file_manager/file_manager/common/js/example_unittest.m.js
-    path_test_file = args.input.replace('gen/', '', 1)
-    path_test_file = path_test_file.replace('.js_library', '.js')
-    _process_js_module(path_test_file, args.output)
-    return
-
-
-if __name__ == '__main__':
-    main()
diff --git a/ui/file_manager/base/gn/js_test_type_check.gni b/ui/file_manager/base/gn/js_test_type_check.gni
new file mode 100644
index 0000000..35454ac6
--- /dev/null
+++ b/ui/file_manager/base/gn/js_test_type_check.gni
@@ -0,0 +1,74 @@
+# Copyright 2019 The Chromium Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/js_unit_tests.gni")
+
+# Generates one target that depends on a list of `js_type_check(...)` targets --
+# one for each test -- that will type check the test js file and its dependency
+# subtree.
+#
+# Must be declared after the js_library targets it depends on.
+#
+# Note js_type_check() is only in effect if `enable_js_type_check` is set in gn
+# args.
+#
+# Variables:
+#   deps:
+#     List of js_unittest() targets to depend on.
+#
+#   extra_deps:
+#     List of other deps that aren't js_unittest().
+#
+#   is_polymer3:
+#     Boolean indicating that it's a test for a Polymer 3 element, the only
+#     difference is the js_type_check() rule also has the is_polymer3=true.
+#
+#
+# Non-Polymer example:
+#   js_test_type_check("folder_tests") {
+#     deps = [
+#       ":foo_unittest",
+#       ":bar_unittest",
+#       ":baz_unittest",
+#     ]
+#   }
+#
+#   group("closure_compile") {
+#     # ...
+#     ":folder_tests".
+#   }
+#
+# Polymer example:
+#   js_test_type_check("polymer_tests") {
+#     is_polymer3 = true
+#     deps = [
+#       ":element1_unittest",
+#     ]
+#   }
+#
+template("js_test_type_check") {
+  type_check_deps = []
+  foreach(dep, invoker.deps) {
+    type_check_target_name = target_name + "_" + dep
+    type_check_deps += [ ":$type_check_target_name" ]
+    js_type_check(type_check_target_name) {
+      testonly = true
+      forward_variables_from(invoker,
+                             [
+                               "closure_flags",
+                               "is_polymer3",
+                             ])
+      deps = [ dep ]
+      if (defined(invoker.extra_deps)) {
+        deps += invoker.extra_deps
+      }
+    }
+  }
+
+  type_check_group_name = target_name
+  group(type_check_group_name) {
+    testonly = true
+    deps = type_check_deps
+  }
+}
diff --git a/ui/file_manager/base/js/test_harness.html b/ui/file_manager/base/js/test_harness.html
new file mode 100644
index 0000000..80f5395
--- /dev/null
+++ b/ui/file_manager/base/js/test_harness.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<script type="module" src="./test_harness.js"></script>
diff --git a/ui/file_manager/base/js/test_harness.js b/ui/file_manager/base/js/test_harness.js
new file mode 100644
index 0000000..328df0a6
--- /dev/null
+++ b/ui/file_manager/base/js/test_harness.js
@@ -0,0 +1,21 @@
+// 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.
+
+async function run() {
+  // Grab the JS module to test from the GET params.
+  const params = new URLSearchParams(window.location.search);
+  const jsModuleUrl = params.get('test_module');
+
+  // Push all entities to global namespace to be visible to the test harness:
+  // ui/webui/resources/js/webui_resource_test.js
+  const TestModule = await import(jsModuleUrl);
+  for (const name in TestModule) {
+    window[name] = TestModule[name];
+  }
+
+  // Notify the BrowserTest to continue.
+  window.domAutomationController.send('LOADED');
+}
+
+run();
diff --git a/ui/file_manager/file_manager/background.html b/ui/file_manager/file_manager/background.html
index 95b12478..3707308 100644
--- a/ui/file_manager/file_manager/background.html
+++ b/ui/file_manager/file_manager/background.html
@@ -1,4 +1,4 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 
-<script type="module" src="background/js/main_background.m.js"></script>
+<script type="module" src="background/js/main_background.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn
index 7173b66..7af06c0 100644
--- a/ui/file_manager/file_manager/background/js/BUILD.gn
+++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -5,7 +5,7 @@
 import("//chrome/browser/resources/tools/optimize_webui.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//third_party/closure_compiler/js_unit_tests.gni")
-import("//ui/file_manager/base/gn/js_test_gen_html.gni")
+import("//ui/file_manager/base/gn/js_test_type_check.gni")
 import("//ui/webui/resources/js/cr.gni")
 
 # TODO(tapted): This folder should be restricted to file_manager, but related
@@ -17,15 +17,13 @@
 related_apps = [
   "//ui/file_manager/audio_player/*",
   "//ui/file_manager/file_manager/*",
-  "//ui/file_manager/gallery/*",
-  "//ui/file_manager/video_player/*",
 ]
 
 group("closure_compile") {
   testonly = true
   deps = [
     ":closure_compile_jsmodules",
-    ":js_test_gen_html_modules_type_check_auto",
+    ":js_test_type_check",
     ":test_support_modules_type_check",
   ]
 }
@@ -169,7 +167,7 @@
   ]
 }
 
-js_library("main_background.m") {
+js_library("main_background") {
   visibility = []
   visibility = [
     ":*",
@@ -213,12 +211,12 @@
     "//ui/file_manager/file_manager/externs/background:crostini",
   ]
   visibility += [
-    "//ui/file_manager/file_manager/foreground/js:file_tasks_unittest.m",
-    "//ui/file_manager/file_manager/foreground/js:task_controller_unittest.m",
+    "//ui/file_manager/file_manager/foreground/js:file_tasks_unittest",
+    "//ui/file_manager/file_manager/foreground/js:task_controller_unittest",
   ]
 }
 
-js_unittest("crostini_unittest.m") {
+js_unittest("crostini_unittest") {
   deps = [
     ":mock_crostini",
     "//chrome/test/data/webui:chai_assert",
@@ -247,7 +245,7 @@
   ]
 }
 
-js_unittest("device_handler_unittest.m") {
+js_unittest("device_handler_unittest") {
   deps = [
     ":device_handler",
     ":mock_progress_center",
@@ -271,9 +269,8 @@
     "//ui/file_manager/file_manager/externs/background:drive_sync_handler",
     "//ui/webui/resources/js/cr:event_target.m",
   ]
-  visibility += [
-    "//ui/file_manager/file_manager/foreground/js:actions_model_unittest.m",
-  ]
+  visibility +=
+      [ "//ui/file_manager/file_manager/foreground/js:actions_model_unittest" ]
 }
 
 js_library("drive_sync_handler") {
@@ -291,7 +288,7 @@
   ]
 }
 
-js_unittest("drive_sync_handler_unittest.m") {
+js_unittest("drive_sync_handler_unittest") {
   deps = [
     ":drive_sync_handler",
     ":mock_progress_center",
@@ -317,7 +314,7 @@
   ]
 }
 
-js_unittest("duplicate_finder_unittest.m") {
+js_unittest("duplicate_finder_unittest") {
   deps = [
     ":duplicate_finder",
     ":mock_volume_manager",
@@ -352,7 +349,7 @@
   ]
 }
 
-js_unittest("file_operation_handler_unittest.m") {
+js_unittest("file_operation_handler_unittest") {
   deps = [
     ":file_operation_handler",
     ":file_operation_util",
@@ -373,7 +370,7 @@
     "//ui/webui/resources/js/cr:event_target.m",
   ]
   visibility += [
-    "//ui/file_manager/file_manager/foreground/js:directory_model_unittest.m",
+    "//ui/file_manager/file_manager/foreground/js:directory_model_unittest",
   ]
 }
 
@@ -398,7 +395,7 @@
   ]
 }
 
-js_unittest("file_operation_manager_unittest.m") {
+js_unittest("file_operation_manager_unittest") {
   deps = [
     ":file_operation_manager",
     ":file_operation_util",
@@ -432,7 +429,7 @@
   deps = [ "//ui/file_manager/file_manager/common/js:lru_cache" ]
 }
 
-js_unittest("metadata_proxy_unittest.m") {
+js_unittest("metadata_proxy_unittest") {
   deps = [
     ":metadata_proxy",
     "//chrome/test/data/webui:chai_assert",
@@ -455,7 +452,7 @@
   ]
 }
 
-js_unittest("import_history_unittest.m") {
+js_unittest("import_history_unittest") {
   deps = [
     ":import_history",
     "//chrome/test/data/webui:chai_assert",
@@ -499,7 +496,7 @@
   ]
 }
 
-js_unittest("media_import_handler_unittest.m") {
+js_unittest("media_import_handler_unittest") {
   deps = [
     ":file_operation_util",
     ":media_import_handler",
@@ -530,7 +527,7 @@
     "//ui/file_manager/file_manager/externs/background:media_scanner",
   ]
   visibility += [
-    "//ui/file_manager/file_manager/foreground/js:import_controller_unittest.m",
+    "//ui/file_manager/file_manager/foreground/js:import_controller_unittest",
   ]
 }
 
@@ -543,11 +540,11 @@
     "//ui/webui/resources/js:assert.m",
   ]
   visibility += [
-    "//ui/file_manager/file_manager/foreground/js:import_controller_unittest.m",
+    "//ui/file_manager/file_manager/foreground/js:import_controller_unittest",
   ]
 }
 
-js_unittest("media_scanner_unittest.m") {
+js_unittest("media_scanner_unittest") {
   deps = [
     ":file_operation_util",
     ":media_scanner",
@@ -587,7 +584,7 @@
     "//ui/file_manager/file_manager/externs/background:progress_center",
   ]
   visibility +=
-      [ "//ui/file_manager/file_manager/foreground/js:file_tasks_unittest.m" ]
+      [ "//ui/file_manager/file_manager/foreground/js:file_tasks_unittest" ]
 }
 
 js_library("progress_center") {
@@ -629,12 +626,12 @@
     "//ui/webui/resources/js:assert.m",
   ]
   visibility += [
-    "//ui/file_manager/file_manager/foreground/js:navigation_list_model_unittest.m",
-    "//ui/file_manager/file_manager/foreground/js:providers_model_unittest.m",
+    "//ui/file_manager/file_manager/foreground/js:navigation_list_model_unittest",
+    "//ui/file_manager/file_manager/foreground/js:providers_model_unittest",
   ]
 }
 
-js_unittest("task_queue_unittest.m") {
+js_unittest("task_queue_unittest") {
   deps = [
     ":task_queue",
     "//chrome/test/data/webui:chai_assert",
@@ -693,7 +690,7 @@
   ]
 }
 
-js_unittest("trash_unittest.m") {
+js_unittest("trash_unittest") {
   deps = [
     ":mock_volume_manager",
     ":trash",
@@ -714,7 +711,7 @@
   ]
 }
 
-js_unittest("mount_metrics_unittest.m") {
+js_unittest("mount_metrics_unittest") {
   deps = [
     ":mount_metrics",
     "//chrome/test/data/webui:chai_assert",
@@ -755,7 +752,7 @@
   ]
 }
 
-js_unittest("volume_manager_unittest.m") {
+js_unittest("volume_manager_unittest") {
   deps = [
     ":volume_info_impl",
     ":volume_manager_factory",
@@ -779,22 +776,22 @@
   ]
 }
 
-js_test_gen_html("js_test_gen_html_modules") {
+js_test_type_check("js_test_type_check") {
   deps = [
-    ":crostini_unittest.m",
-    ":device_handler_unittest.m",
-    ":drive_sync_handler_unittest.m",
-    ":duplicate_finder_unittest.m",
-    ":file_operation_handler_unittest.m",
-    ":file_operation_manager_unittest.m",
-    ":import_history_unittest.m",
-    ":media_import_handler_unittest.m",
-    ":media_scanner_unittest.m",
-    ":metadata_proxy_unittest.m",
-    ":mount_metrics_unittest.m",
-    ":task_queue_unittest.m",
-    ":trash_unittest.m",
-    ":volume_manager_unittest.m",
+    ":crostini_unittest",
+    ":device_handler_unittest",
+    ":drive_sync_handler_unittest",
+    ":duplicate_finder_unittest",
+    ":file_operation_handler_unittest",
+    ":file_operation_manager_unittest",
+    ":import_history_unittest",
+    ":media_import_handler_unittest",
+    ":media_scanner_unittest",
+    ":metadata_proxy_unittest",
+    ":mount_metrics_unittest",
+    ":task_queue_unittest",
+    ":trash_unittest",
+    ":volume_manager_unittest",
   ]
 
   closure_flags =
@@ -819,14 +816,14 @@
 
   input = tsc_folder
   js_module_in_files = [
-    "main_background.m.js",
+    "main_background.js",
     "runtime_loaded_test_util.js",
   ]
 
   js_out_files = [
-    "main_background.m.rollup.js",
+    "main_background.rollup.js",
     "runtime_loaded_test_util.rollup.js",
-    "shared.m.rollup.js",
+    "shared.rollup.js",
   ]
 
   external_paths = [
diff --git a/ui/file_manager/file_manager/background/js/crostini_unittest.m.js b/ui/file_manager/file_manager/background/js/crostini_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/crostini_unittest.m.js
rename to ui/file_manager/file_manager/background/js/crostini_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/device_handler_unittest.m.js b/ui/file_manager/file_manager/background/js/device_handler_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/device_handler_unittest.m.js
rename to ui/file_manager/file_manager/background/js/device_handler_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.m.js b/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.m.js
rename to ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.m.js b/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/duplicate_finder_unittest.m.js
rename to ui/file_manager/file_manager/background/js/duplicate_finder_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/file_operation_handler.js b/ui/file_manager/file_manager/background/js/file_operation_handler.js
index aef3718..11eedec8 100644
--- a/ui/file_manager/file_manager/background/js/file_operation_handler.js
+++ b/ui/file_manager/file_manager/background/js/file_operation_handler.js
@@ -62,6 +62,12 @@
    * @private
    */
   async onIOTaskProgressStatus_(event) {
+    // The trash event will return progress, but this will be handled by a toast
+    // which shows an Undo button instead. Ignore the trash event here.
+    if (event.type === chrome.fileManagerPrivate.IOTaskType.TRASH) {
+      return;
+    }
+
     const taskId = String(event.taskId);
     let newItem = false;
     /** @type {ProgressCenterItem} */
@@ -441,10 +447,14 @@
       return ProgressItemType.COPY;
     case chrome.fileManagerPrivate.IOTaskType.DELETE:
       return ProgressItemType.DELETE;
+    case chrome.fileManagerPrivate.IOTaskType.EMPTY_TRASH:
+      return ProgressItemType.EMPTY_TRASH;
     case chrome.fileManagerPrivate.IOTaskType.EXTRACT:
       return ProgressItemType.EXTRACT;
     case chrome.fileManagerPrivate.IOTaskType.MOVE:
       return ProgressItemType.MOVE;
+    case chrome.fileManagerPrivate.IOTaskType.RESTORE:
+      return ProgressItemType.RESTORE;
     case chrome.fileManagerPrivate.IOTaskType.ZIP:
       return ProgressItemType.ZIP;
     default:
diff --git a/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.m.js b/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/file_operation_handler_unittest.m.js
rename to ui/file_manager/file_manager/background/js/file_operation_handler_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.m.js b/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/file_operation_manager_unittest.m.js
rename to ui/file_manager/file_manager/background/js/file_operation_manager_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/import_history_unittest.m.js b/ui/file_manager/file_manager/background/js/import_history_unittest.js
similarity index 98%
rename from ui/file_manager/file_manager/background/js/import_history_unittest.m.js
rename to ui/file_manager/file_manager/background/js/import_history_unittest.js
index 428a30c..60d6d15d 100644
--- a/ui/file_manager/file_manager/background/js/import_history_unittest.m.js
+++ b/ui/file_manager/file_manager/background/js/import_history_unittest.js
@@ -6,7 +6,7 @@
 
 import {importer} from '../../common/js/importer_common.js';
 import {MockChromeStorageAPI} from '../../common/js/mock_chrome.js';
-import {MockFileEntry,MockFileSystem} from '../../common/js/mock_entry.js';
+import {MockFileEntry, MockFileSystem} from '../../common/js/mock_entry.js';
 import {reportPromise} from '../../common/js/test_error_reporting.js';
 import {importerTest} from '../../common/js/test_importer_common.js';
 import {TestCallRecorder} from '../../common/js/unittest_util.js';
diff --git a/ui/file_manager/file_manager/background/js/main_background.m.js b/ui/file_manager/file_manager/background/js/main_background.js
similarity index 99%
rename from ui/file_manager/file_manager/background/js/main_background.m.js
rename to ui/file_manager/file_manager/background/js/main_background.js
index 4cb5e4d..c15d89e 100644
--- a/ui/file_manager/file_manager/background/js/main_background.m.js
+++ b/ui/file_manager/file_manager/background/js/main_background.js
@@ -8,6 +8,5 @@
 
 import './metrics_start.js';
 import '../../common/js/error_counter.js';
-
 import './background.js';
 import './test_util.js';
diff --git a/ui/file_manager/file_manager/background/js/media_import_handler_unittest.m.js b/ui/file_manager/file_manager/background/js/media_import_handler_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/media_import_handler_unittest.m.js
rename to ui/file_manager/file_manager/background/js/media_import_handler_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/media_scanner_unittest.m.js b/ui/file_manager/file_manager/background/js/media_scanner_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/media_scanner_unittest.m.js
rename to ui/file_manager/file_manager/background/js/media_scanner_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/metadata_proxy_unittest.m.js b/ui/file_manager/file_manager/background/js/metadata_proxy_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/metadata_proxy_unittest.m.js
rename to ui/file_manager/file_manager/background/js/metadata_proxy_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/mount_metrics_unittest.m.js b/ui/file_manager/file_manager/background/js/mount_metrics_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/mount_metrics_unittest.m.js
rename to ui/file_manager/file_manager/background/js/mount_metrics_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/task_queue_unittest.m.js b/ui/file_manager/file_manager/background/js/task_queue_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/task_queue_unittest.m.js
rename to ui/file_manager/file_manager/background/js/task_queue_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/trash_unittest.m.js b/ui/file_manager/file_manager/background/js/trash_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/trash_unittest.m.js
rename to ui/file_manager/file_manager/background/js/trash_unittest.js
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_unittest.m.js b/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/background/js/volume_manager_unittest.m.js
rename to ui/file_manager/file_manager/background/js/volume_manager_unittest.js
diff --git a/ui/file_manager/file_manager/common/js/BUILD.gn b/ui/file_manager/file_manager/common/js/BUILD.gn
index f1d66162..9cbec4b 100644
--- a/ui/file_manager/file_manager/common/js/BUILD.gn
+++ b/ui/file_manager/file_manager/common/js/BUILD.gn
@@ -4,7 +4,7 @@
 
 import("//third_party/closure_compiler/compile_js.gni")
 import("//third_party/closure_compiler/js_unit_tests.gni")
-import("//ui/file_manager/base/gn/js_test_gen_html.gni")
+import("//ui/file_manager/base/gn/js_test_type_check.gni")
 import("//ui/webui/resources/js/cr.gni")
 
 visibility = [
@@ -16,7 +16,7 @@
   testonly = true
   deps = [
     ":closure_compile_jsmodules",
-    ":js_test_gen_html_modules_type_check_auto",
+    ":js_test_type_check",
     ":test_support_modules_type_check",
   ]
 }
@@ -136,7 +136,7 @@
 js_library("dialog_type") {
 }
 
-js_unittest("files_app_entry_types_unittest.m") {
+js_unittest("files_app_entry_types_unittest") {
   deps = [
     ":files_app_entry_types",
     ":mock_entry",
@@ -177,7 +177,7 @@
   ]
 }
 
-js_unittest("file_type_unittest.m") {
+js_unittest("file_type_unittest") {
   deps = [
     ":file_type",
     ":mock_entry",
@@ -210,7 +210,7 @@
   ]
 }
 
-js_unittest("filtered_volume_manager_unittest.m") {
+js_unittest("filtered_volume_manager_unittest") {
   deps = [
     ":filtered_volume_manager",
     "//chrome/test/data/webui:chai_assert",
@@ -242,7 +242,7 @@
   ]
 }
 
-js_unittest("importer_common_unittest.m") {
+js_unittest("importer_common_unittest") {
   deps = [
     ":importer_common",
     ":mock_entry",
@@ -259,7 +259,7 @@
 js_library("lru_cache") {
 }
 
-js_unittest("lru_cache_unittest.m") {
+js_unittest("lru_cache_unittest") {
   deps = [
     ":lru_cache",
     "//chrome/test/data/webui:chai_assert",
@@ -309,7 +309,7 @@
   ]
 }
 
-js_unittest("recent_date_bucket_unittest.m") {
+js_unittest("recent_date_bucket_unittest") {
   deps = [
     ":mock_chrome",
     ":recent_date_bucket",
@@ -322,7 +322,7 @@
   externs_list = [ "$externs_path/chrome_extensions.js" ]
 }
 
-js_unittest("storage_adapter_unittest.m") {
+js_unittest("storage_adapter_unittest") {
   deps = [
     ":storage_adapter",
     "//chrome/test/data/webui:chai_assert",
@@ -381,7 +381,7 @@
   ]
 }
 
-js_unittest("util_unittest.m") {
+js_unittest("util_unittest") {
   deps = [
     ":files_app_entry_types",
     ":mock_entry",
@@ -392,7 +392,7 @@
   ]
 }
 
-js_unittest("volume_manager_types_unittest.m") {
+js_unittest("volume_manager_types_unittest") {
   deps = [ ":volume_manager_types" ]
 }
 
@@ -407,17 +407,17 @@
   deps = [ "//ui/file_manager/file_manager/externs:file_manager_private" ]
 }
 
-js_test_gen_html("js_test_gen_html_modules") {
+js_test_type_check("js_test_type_check") {
   deps = [
-    ":file_type_unittest.m",
-    ":files_app_entry_types_unittest.m",
-    ":filtered_volume_manager_unittest.m",
-    ":importer_common_unittest.m",
-    ":lru_cache_unittest.m",
-    ":recent_date_bucket_unittest.m",
-    ":storage_adapter_unittest.m",
-    ":util_unittest.m",
-    ":volume_manager_types_unittest.m",
+    ":file_type_unittest",
+    ":files_app_entry_types_unittest",
+    ":filtered_volume_manager_unittest",
+    ":importer_common_unittest",
+    ":lru_cache_unittest",
+    ":recent_date_bucket_unittest",
+    ":storage_adapter_unittest",
+    ":util_unittest",
+    ":volume_manager_types_unittest",
   ]
 
   closure_flags =
diff --git a/ui/file_manager/file_manager/common/js/file_type_unittest.m.js b/ui/file_manager/file_manager/common/js/file_type_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/common/js/file_type_unittest.m.js
rename to ui/file_manager/file_manager/common/js/file_type_unittest.js
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.m.js b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
similarity index 99%
rename from ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.m.js
rename to ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
index 78313eb3..301fc65 100644
--- a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.m.js
+++ b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
@@ -422,7 +422,7 @@
     label: 'Fake Filesystem label',
     volumeType: VolumeManagerCommon.VolumeType.DOWNLOADS,
     resolveDisplayRoot: (successCallback, errorCallback) => {
-      // Do nothing here.
+        // Do nothing here.
     },
   });
 
diff --git a/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.m.js b/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.m.js
rename to ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.js
diff --git a/ui/file_manager/file_manager/common/js/importer_common_unittest.m.js b/ui/file_manager/file_manager/common/js/importer_common_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/common/js/importer_common_unittest.m.js
rename to ui/file_manager/file_manager/common/js/importer_common_unittest.js
diff --git a/ui/file_manager/file_manager/common/js/lru_cache_unittest.m.js b/ui/file_manager/file_manager/common/js/lru_cache_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/common/js/lru_cache_unittest.m.js
rename to ui/file_manager/file_manager/common/js/lru_cache_unittest.js
diff --git a/ui/file_manager/file_manager/common/js/progress_center_common.js b/ui/file_manager/file_manager/common/js/progress_center_common.js
index 66edf56..7b256f4 100644
--- a/ui/file_manager/file_manager/common/js/progress_center_common.js
+++ b/ui/file_manager/file_manager/common/js/progress_center_common.js
@@ -23,6 +23,8 @@
   COPY: 'copy',
   // The item is file delete operation.
   DELETE: 'delete',
+  // The item is emptying the trash operation.
+  EMPTY_TRASH: 'empty-trash',
   // The item is file extract operation.
   EXTRACT: 'extract',
   // The item is file move operation.
@@ -31,6 +33,8 @@
   ZIP: 'zip',
   // The item is drive sync operation.
   SYNC: 'sync',
+  // The item is restoring the trash.
+  RESTORE: 'restore',
   // The item is general file transfer operation.
   // This is used for the mixed operation of summarized item.
   TRANSFER: 'transfer',
diff --git a/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.m.js b/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.m.js
rename to ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.js
diff --git a/ui/file_manager/file_manager/common/js/storage_adapter_unittest.m.js b/ui/file_manager/file_manager/common/js/storage_adapter_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/common/js/storage_adapter_unittest.m.js
rename to ui/file_manager/file_manager/common/js/storage_adapter_unittest.js
diff --git a/ui/file_manager/file_manager/common/js/util_unittest.m.js b/ui/file_manager/file_manager/common/js/util_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/common/js/util_unittest.m.js
rename to ui/file_manager/file_manager/common/js/util_unittest.js
diff --git a/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.m.js b/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/common/js/volume_manager_types_unittest.m.js
rename to ui/file_manager/file_manager/common/js/volume_manager_types_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/elements/BUILD.gn b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
index 5fbcf2ec..6745010 100644
--- a/ui/file_manager/file_manager/foreground/elements/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
@@ -5,7 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 import("//third_party/closure_compiler/js_unit_tests.gni")
 import("//tools/polymer/html_to_js.gni")
-import("//ui/file_manager/base/gn/js_test_gen_html.gni")
+import("//ui/file_manager/base/gn/js_test_type_check.gni")
 
 visibility = [ "//ui/file_manager/file_manager/foreground/*" ]
 
@@ -20,7 +20,7 @@
   visibility += [ "//ui/file_manager:closure_compile" ]
   deps = [
     ":closure_compile_jsmodules",
-    ":js_test_gen_html_modules_type_check_auto",
+    ":js_test_type_check",
   ]
 }
 
@@ -112,7 +112,7 @@
   ]
 }
 
-js_unittest("files_password_dialog_unittest.m") {
+js_unittest("files_password_dialog_unittest") {
   deps = [
     ":files_password_dialog",
     "//chrome/test/data/webui:chai_assert",
@@ -186,7 +186,7 @@
 }
 
 # TODO(tapted): Move this to //ui/file_manager/base.
-js_unittest("files_tooltip_unittest.m") {
+js_unittest("files_tooltip_unittest") {
   deps = [
     ":files_tooltip",
     "//chrome/test/data/webui:chai_assert",
@@ -200,14 +200,14 @@
   ]
 }
 
-js_unittest("files_toast_unittest.m") {
+js_unittest("files_toast_unittest") {
   deps = [
     ":files_toast",
     "//chrome/test/data/webui:chai_assert",
   ]
 }
 
-js_unittest("files_xf_elements_unittest.m") {
+js_unittest("files_xf_elements_unittest") {
   deps = [
     ":xf_display_panel",
     "//chrome/test/data/webui:chai_assert",
@@ -237,13 +237,13 @@
   ]
 }
 
-js_test_gen_html("js_test_gen_html_modules") {
+js_test_type_check("js_test_type_check") {
   is_polymer3 = true
   deps = [
-    ":files_password_dialog_unittest.m",
-    ":files_toast_unittest.m",
-    ":files_tooltip_unittest.m",
-    ":files_xf_elements_unittest.m",
+    ":files_password_dialog_unittest",
+    ":files_toast_unittest",
+    ":files_tooltip_unittest",
+    ":files_xf_elements_unittest",
   ]
 
   closure_flags =
diff --git a/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.m.js b/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.m.js
rename to ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.m.js b/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/elements/files_toast_unittest.m.js
rename to ui/file_manager/file_manager/foreground/elements/files_toast_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.m.js b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.m.js
rename to ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.m.js b/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.m.js
rename to ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn
index 836bebf..70d16ea4 100644
--- a/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -5,7 +5,7 @@
 import("//chrome/browser/resources/tools/optimize_webui.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//third_party/closure_compiler/js_unit_tests.gni")
-import("//ui/file_manager/base/gn/js_test_gen_html.gni")
+import("//ui/file_manager/base/gn/js_test_type_check.gni")
 import("//ui/webui/resources/js/cr.gni")
 
 visibility = [
@@ -19,7 +19,7 @@
   visibility += [ "//ui/file_manager:closure_compile" ]
   deps = [
     ":closure_compile_jsmodules",
-    ":js_test_gen_html_modules_type_check_auto",
+    ":js_test_type_check",
   ]
 }
 
@@ -110,7 +110,7 @@
     ":constants",
     ":crossover_search_utils",
     ":crostini_controller",
-    ":deferred_elements.m",
+    ":deferred_elements",
     ":dialog_action_controller",
     ":directory_contents",
     ":directory_model",
@@ -221,7 +221,7 @@
   ]
 }
 
-js_unittest("banner_controller_unittest.m") {
+js_unittest("banner_controller_unittest") {
   deps = [
     ":banner_controller",
     ":directory_model",
@@ -239,7 +239,7 @@
   ]
 }
 
-js_unittest("banner_util_unittest.m") {
+js_unittest("banner_util_unittest") {
   deps = [
     ":banner_controller",
     ":directory_model",
@@ -264,7 +264,7 @@
   ]
 }
 
-js_unittest("actions_model_unittest.m") {
+js_unittest("actions_model_unittest") {
   deps = [
     ":actions_model",
     ":folder_shortcuts_data_model",
@@ -413,7 +413,7 @@
   ]
 }
 
-js_unittest("directory_contents_unittest.m") {
+js_unittest("directory_contents_unittest") {
   deps = [
     ":directory_contents",
     "//chrome/test/data/webui:chai_assert",
@@ -450,7 +450,7 @@
   ]
 }
 
-js_unittest("directory_model_unittest.m") {
+js_unittest("directory_model_unittest") {
   deps = [
     ":directory_contents",
     ":directory_model",
@@ -497,10 +497,10 @@
 }
 
 js_library("elements_importer") {
-  deps = [ ":deferred_elements.m" ]
+  deps = [ ":deferred_elements" ]
 }
 
-js_library("deferred_elements.m") {
+js_library("deferred_elements") {
   visibility += [ "//ui/file_manager:*" ]
   deps = [
     "//ui/file_manager/file_manager/foreground/elements:files_format_dialog",
@@ -529,7 +529,7 @@
   ]
 }
 
-js_unittest("file_list_model_unittest.m") {
+js_unittest("file_list_model_unittest") {
   deps = [
     ":file_list_model",
     "metadata:metadata_model",
@@ -662,7 +662,7 @@
   ]
 }
 
-js_unittest("file_manager_commands_unittest.m") {
+js_unittest("file_manager_commands_unittest") {
   deps = [
     ":file_manager_commands",
     ":file_tasks",
@@ -726,7 +726,7 @@
   ]
 }
 
-js_unittest("file_tasks_unittest.m") {
+js_unittest("file_tasks_unittest") {
   deps = [
     ":directory_model",
     ":file_tasks",
@@ -781,7 +781,7 @@
   ]
 }
 
-js_unittest("file_transfer_controller_unittest.m") {
+js_unittest("file_transfer_controller_unittest") {
   deps = [
     ":fake_file_selection_handler",
     ":file_list_model",
@@ -825,7 +825,7 @@
   ]
 }
 
-js_unittest("file_type_filters_controller_unittest.m") {
+js_unittest("file_type_filters_controller_unittest") {
   deps = [
     ":directory_model",
     ":file_type_filters_controller",
@@ -917,7 +917,7 @@
   ]
 }
 
-js_unittest("import_controller_unittest.m") {
+js_unittest("import_controller_unittest") {
   deps = [
     ":import_controller",
     "//chrome/test/data/webui:chai_assert",
@@ -965,7 +965,7 @@
   ]
 }
 
-js_unittest("list_thumbnail_loader_unittest.m") {
+js_unittest("list_thumbnail_loader_unittest") {
   deps = [
     ":directory_model",
     ":file_list_model",
@@ -1074,7 +1074,7 @@
   ]
 }
 
-js_unittest("navigation_list_model_unittest.m") {
+js_unittest("navigation_list_model_unittest") {
   deps = [
     ":android_app_list_model",
     ":directory_model",
@@ -1103,7 +1103,7 @@
   ]
 }
 
-js_unittest("path_component_unittest.m") {
+js_unittest("path_component_unittest") {
   deps = [
     ":path_component",
     "//chrome/test/data/webui:chai_assert",
@@ -1122,7 +1122,7 @@
   ]
 }
 
-js_unittest("providers_model_unittest.m") {
+js_unittest("providers_model_unittest") {
   deps = [
     ":providers_model",
     "//chrome/test/data/webui:chai_assert",
@@ -1232,7 +1232,7 @@
 js_library("spinner_controller") {
 }
 
-js_unittest("spinner_controller_unittest.m") {
+js_unittest("spinner_controller_unittest") {
   deps = [
     ":spinner_controller",
     "//chrome/test/data/webui:chai_assert",
@@ -1264,7 +1264,7 @@
   ]
 }
 
-js_unittest("task_controller_unittest.m") {
+js_unittest("task_controller_unittest") {
   deps = [
     ":directory_model",
     ":fake_file_selection_handler",
@@ -1310,7 +1310,7 @@
   ]
 }
 
-js_unittest("thumbnail_loader_unittest.m") {
+js_unittest("thumbnail_loader_unittest") {
   deps = [
     ":thumbnail_loader",
     "//chrome/test/data/webui:chai_assert",
@@ -1344,27 +1344,27 @@
   ]
 }
 
-js_test_gen_html("js_test_gen_html_modules") {
+js_test_type_check("js_test_type_check") {
   is_polymer3 = true
   deps = [
-    ":actions_model_unittest.m",
-    ":banner_controller_unittest.m",
-    ":banner_util_unittest.m",
-    ":directory_contents_unittest.m",
-    ":directory_model_unittest.m",
-    ":file_list_model_unittest.m",
-    ":file_manager_commands_unittest.m",
-    ":file_tasks_unittest.m",
-    ":file_transfer_controller_unittest.m",
-    ":file_type_filters_controller_unittest.m",
-    ":import_controller_unittest.m",
-    ":list_thumbnail_loader_unittest.m",
-    ":navigation_list_model_unittest.m",
-    ":path_component_unittest.m",
-    ":providers_model_unittest.m",
-    ":spinner_controller_unittest.m",
-    ":task_controller_unittest.m",
-    ":thumbnail_loader_unittest.m",
+    ":actions_model_unittest",
+    ":banner_controller_unittest",
+    ":banner_util_unittest",
+    ":directory_contents_unittest",
+    ":directory_model_unittest",
+    ":file_list_model_unittest",
+    ":file_manager_commands_unittest",
+    ":file_tasks_unittest",
+    ":file_transfer_controller_unittest",
+    ":file_type_filters_controller_unittest",
+    ":import_controller_unittest",
+    ":list_thumbnail_loader_unittest",
+    ":navigation_list_model_unittest",
+    ":path_component_unittest",
+    ":providers_model_unittest",
+    ":spinner_controller_unittest",
+    ":task_controller_unittest",
+    ":thumbnail_loader_unittest",
   ]
 
   closure_flags = strict_error_checking_closure_args + [
@@ -1397,13 +1397,13 @@
   input = tsc_folder
   js_module_in_files = [
     "main.js",
-    "deferred_elements.m.js",
+    "deferred_elements.js",
   ]
 
   js_out_files = [
     "main.rollup.js",
-    "deferred_elements.m.rollup.js",
-    "shared.m.rollup.js",
+    "deferred_elements.rollup.js",
+    "shared.rollup.js",
   ]
 
   external_paths = [
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/actions_model_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/banner_controller_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/banner_util_unittest.m.js b/ui/file_manager/file_manager/foreground/js/banner_util_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/banner_util_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/banner_util_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/deferred_elements.m.js b/ui/file_manager/file_manager/foreground/js/deferred_elements.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/deferred_elements.m.js
rename to ui/file_manager/file_manager/foreground/js/deferred_elements.js
diff --git a/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.m.js b/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/directory_contents_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/directory_contents_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/directory_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/directory_model_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/directory_model_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/directory_model_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/elements_importer.js b/ui/file_manager/file_manager/foreground/js/elements_importer.js
index e54eca11..d5e15b51 100644
--- a/ui/file_manager/file_manager/foreground/js/elements_importer.js
+++ b/ui/file_manager/file_manager/foreground/js/elements_importer.js
@@ -8,7 +8,7 @@
   return new Promise((resolve, reject) => {
     const script = document.createElement('script');
     script.type = 'module';
-    script.src = './foreground/js/deferred_elements.m.js';
+    script.src = './foreground/js/deferred_elements.js';
 
     script.onload = () => {
       console.log('Elements imported.');
diff --git a/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/file_list_model_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/file_tasks_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/import_controller_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/import_controller_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.m.js b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
index 8e0e58a..e0d31a96 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
@@ -4,7 +4,7 @@
 
 import("//third_party/closure_compiler/compile_js.gni")
 import("//third_party/closure_compiler/js_unit_tests.gni")
-import("//ui/file_manager/base/gn/js_test_gen_html.gni")
+import("//ui/file_manager/base/gn/js_test_type_check.gni")
 import("//ui/webui/resources/js/cr.gni")
 
 # TODO(tapted): This entire folder should move to //ui/file_manager/base.
@@ -14,7 +14,7 @@
   testonly = true
   deps = [
     ":closure_compile_jsmodules",
-    ":js_test_gen_html_modules_type_check_auto",
+    ":js_test_type_check",
   ]
 }
 
@@ -99,7 +99,7 @@
   ]
 }
 
-js_unittest("content_metadata_provider_unittest.m") {
+js_unittest("content_metadata_provider_unittest") {
   deps = [
     ":content_metadata_provider",
     ":metadata_request",
@@ -129,7 +129,7 @@
   ]
 }
 
-js_unittest("exif_parser_unittest.m") {
+js_unittest("exif_parser_unittest") {
   deps = [
     ":byte_reader",
     ":exif_constants",
@@ -150,7 +150,7 @@
   ]
 }
 
-js_unittest("external_metadata_provider_unittest.m") {
+js_unittest("external_metadata_provider_unittest") {
   deps = [
     ":external_metadata_provider",
     ":metadata_request",
@@ -167,7 +167,7 @@
   ]
 }
 
-js_unittest("file_system_metadata_provider_unittest.m") {
+js_unittest("file_system_metadata_provider_unittest") {
   deps = [
     ":file_system_metadata_provider",
     ":metadata_request",
@@ -197,7 +197,7 @@
 js_library("image_orientation") {
 }
 
-js_unittest("image_orientation_unittest.m") {
+js_unittest("image_orientation_unittest") {
   deps = [
     ":image_orientation",
     "//chrome/test/data/webui:chai_assert",
@@ -219,7 +219,7 @@
   ]
 }
 
-js_unittest("metadata_cache_item_unittest.m") {
+js_unittest("metadata_cache_item_unittest") {
   deps = [
     ":metadata_cache_item",
     ":metadata_item",
@@ -237,7 +237,7 @@
   ]
 }
 
-js_unittest("metadata_cache_set_unittest.m") {
+js_unittest("metadata_cache_set_unittest") {
   deps = [
     ":metadata_cache_set",
     "//chrome/test/data/webui:chai_assert",
@@ -273,7 +273,7 @@
   ]
 }
 
-js_unittest("metadata_model_unittest.m") {
+js_unittest("metadata_model_unittest") {
   deps = [
     ":metadata_model",
     ":metadata_provider",
@@ -327,7 +327,7 @@
   ]
 }
 
-js_unittest("multi_metadata_provider_unittest.m") {
+js_unittest("multi_metadata_provider_unittest") {
   deps = [
     ":content_metadata_provider",
     ":dlp_metadata_provider",
@@ -349,7 +349,7 @@
   ]
 }
 
-js_unittest("thumbnail_model_unittest.m") {
+js_unittest("thumbnail_model_unittest") {
   deps = [
     ":metadata_item",
     ":metadata_model",
@@ -359,18 +359,18 @@
   ]
 }
 
-js_test_gen_html("js_test_gen_html_modules") {
+js_test_type_check("js_test_type_check") {
   deps = [
-    ":content_metadata_provider_unittest.m",
-    ":exif_parser_unittest.m",
-    ":external_metadata_provider_unittest.m",
-    ":file_system_metadata_provider_unittest.m",
-    ":image_orientation_unittest.m",
-    ":metadata_cache_item_unittest.m",
-    ":metadata_cache_set_unittest.m",
-    ":metadata_model_unittest.m",
-    ":multi_metadata_provider_unittest.m",
-    ":thumbnail_model_unittest.m",
+    ":content_metadata_provider_unittest",
+    ":exif_parser_unittest",
+    ":external_metadata_provider_unittest",
+    ":file_system_metadata_provider_unittest",
+    ":image_orientation_unittest",
+    ":metadata_cache_item_unittest",
+    ":metadata_cache_set_unittest",
+    ":metadata_model_unittest",
+    ":multi_metadata_provider_unittest",
+    ":thumbnail_model_unittest",
   ]
 
   closure_flags = strict_error_checking_closure_args + [
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
similarity index 98%
rename from ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
index b0c413c..d0dc1eab 100644
--- a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.m.js
+++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
@@ -6,9 +6,9 @@
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
 import {VolumeInfoImpl} from '../../background/js/volume_info_impl.js';
-import { EntryList,FakeEntryImpl} from '../../common/js/files_app_entry_types.js';
+import {EntryList, FakeEntryImpl} from '../../common/js/files_app_entry_types.js';
 import {MockCommandLinePrivate} from '../../common/js/mock_chrome.js';
-import { MockFileEntry,MockFileSystem} from '../../common/js/mock_entry.js';
+import {MockFileEntry, MockFileSystem} from '../../common/js/mock_entry.js';
 import {reportPromise, waitUntil} from '../../common/js/test_error_reporting.js';
 import {util} from '../../common/js/util.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
@@ -19,7 +19,7 @@
 import {createFakeAndroidAppListModel} from './fake_android_app_list_model.js';
 import {createFakeDirectoryModel} from './mock_directory_model.js';
 import {MockFolderShortcutDataModel} from './mock_folder_shortcut_data_model.js';
-import { NavigationListModel, NavigationModelAndroidAppItem,NavigationModelFakeItem, NavigationModelItemType, NavigationModelShortcutItem, NavigationModelVolumeItem, NavigationSection} from './navigation_list_model.js';
+import {NavigationListModel, NavigationModelAndroidAppItem, NavigationModelFakeItem, NavigationModelItemType, NavigationModelShortcutItem, NavigationModelVolumeItem, NavigationSection} from './navigation_list_model.js';
 
 /**
  * Mock Recent fake entry.
diff --git a/ui/file_manager/file_manager/foreground/js/path_component_unittest.m.js b/ui/file_manager/file_manager/foreground/js/path_component_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/path_component_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/path_component_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/providers_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/providers_model_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/providers_model_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/providers_model_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/task_controller_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.m.js b/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
index 217853d..6962711b 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -5,7 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 import("//third_party/closure_compiler/js_unit_tests.gni")
 import("//tools/polymer/html_to_js.gni")
-import("//ui/file_manager/base/gn/js_test_gen_html.gni")
+import("//ui/file_manager/base/gn/js_test_type_check.gni")
 import("//ui/webui/resources/js/cr.gni")
 
 visibility = [ "//ui/file_manager/file_manager/foreground/*" ]
@@ -15,7 +15,7 @@
   visibility += [ "//ui/file_manager:closure_compile" ]
   deps = [
     ":closure_compile_jsmodules",
-    ":js_test_gen_html_modules_type_check_auto",
+    ":js_test_type_check",
   ]
 }
 
@@ -141,7 +141,7 @@
   ]
 }
 
-js_unittest("actions_submenu_unittest.m") {
+js_unittest("actions_submenu_unittest") {
   deps = [
     ":actions_submenu",
     "//chrome/test/data/webui:chai_assert",
@@ -158,7 +158,7 @@
   ]
 }
 
-js_unittest("breadcrumb_unittest.m") {
+js_unittest("breadcrumb_unittest") {
   deps = [
     ":breadcrumb",
     "//chrome/test/data/webui:chai_assert",
@@ -239,7 +239,7 @@
       [ "//ui/file_manager/file_manager/externs:command_handler_deps" ]
 }
 
-js_unittest("directory_tree_unittest.m") {
+js_unittest("directory_tree_unittest") {
   deps = [
     ":directory_tree",
     "//chrome/test/data/webui:chai_assert",
@@ -299,7 +299,7 @@
   ]
 }
 
-js_unittest("file_list_selection_model_unittest.m") {
+js_unittest("file_list_selection_model_unittest") {
   deps = [
     ":file_list_selection_model",
     "//chrome/test/data/webui:chai_assert",
@@ -314,7 +314,7 @@
   ]
 }
 
-js_unittest("file_manager_dialog_base_unittest.m") {
+js_unittest("file_manager_dialog_base_unittest") {
   deps = [
     ":file_manager_dialog_base",
     "//chrome/test/data/webui:chai_assert",
@@ -408,7 +408,7 @@
   ]
 }
 
-js_unittest("file_table_unittest.m") {
+js_unittest("file_table_unittest") {
   deps = [
     ":file_table",
     "table:table_column",
@@ -436,7 +436,7 @@
   ]
 }
 
-js_unittest("file_table_list_unittest.m") {
+js_unittest("file_table_list_unittest") {
   deps = [
     ":a11y_announce",
     ":file_list_selection_model",
@@ -458,7 +458,7 @@
   deps = [ "//ui/webui/resources/js:assert.m" ]
 }
 
-js_unittest("file_tap_handler_unittest.m") {
+js_unittest("file_tap_handler_unittest") {
   deps = [
     ":file_tap_handler",
     "//chrome/test/data/webui:chai_assert",
@@ -510,7 +510,7 @@
   ]
 }
 
-js_unittest("install_linux_package_dialog_unittest.m") {
+js_unittest("install_linux_package_dialog_unittest") {
   deps = [
     ":install_linux_package_dialog",
     "//chrome/test/data/webui:chai_assert",
@@ -580,7 +580,7 @@
   ]
 }
 
-js_unittest("multi_menu_unittest.m") {
+js_unittest("multi_menu_unittest") {
   deps = [
     ":multi_menu_button",
     "//chrome/test/data/webui:chai_assert",
@@ -660,18 +660,18 @@
   ]
 }
 
-js_test_gen_html("js_test_gen_html_modules") {
+js_test_type_check("js_test_type_check") {
   deps = [
-    ":actions_submenu_unittest.m",
-    ":breadcrumb_unittest.m",
-    ":directory_tree_unittest.m",
-    ":file_list_selection_model_unittest.m",
-    ":file_manager_dialog_base_unittest.m",
-    ":file_table_list_unittest.m",
-    ":file_table_unittest.m",
-    ":file_tap_handler_unittest.m",
-    ":install_linux_package_dialog_unittest.m",
-    ":multi_menu_unittest.m",
+    ":actions_submenu_unittest",
+    ":breadcrumb_unittest",
+    ":directory_tree_unittest",
+    ":file_list_selection_model_unittest",
+    ":file_manager_dialog_base_unittest",
+    ":file_table_list_unittest",
+    ":file_table_unittest",
+    ":file_tap_handler_unittest",
+    ":install_linux_package_dialog_unittest",
+    ":multi_menu_unittest",
     ":splitter_unittest",
   ]
   is_polymer3 = true
diff --git a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn
index f8b6ba2a..43d206fe 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn
@@ -5,7 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 import("//third_party/closure_compiler/js_unit_tests.gni")
 import("//tools/polymer/html_to_js.gni")
-import("//ui/file_manager/base/gn/js_test_gen_html.gni")
+import("//ui/file_manager/base/gn/js_test_type_check.gni")
 
 visibility = [ "//ui/file_manager/file_manager/foreground/*" ]
 
@@ -14,7 +14,7 @@
   visibility += [ "//ui/file_manager:closure_compile" ]
   deps = [
     ":closure_compile_jsmodules",
-    ":js_test_gen_html_modules_type_check_auto",
+    ":js_test_type_check",
   ]
 }
 
@@ -121,7 +121,7 @@
   ]
 }
 
-js_unittest("educational_banner_unittest.m") {
+js_unittest("educational_banner_unittest") {
   deps = [
     ":educational_banner",
     "//chrome/test/data/webui:chai_assert",
@@ -156,7 +156,7 @@
   ]
 }
 
-js_unittest("state_banner_unittest.m") {
+js_unittest("state_banner_unittest") {
   deps = [
     ":state_banner",
     "//chrome/test/data/webui:chai_assert",
@@ -180,7 +180,7 @@
   ]
 }
 
-js_unittest("warning_banner_unittest.m") {
+js_unittest("warning_banner_unittest") {
   deps = [
     ":warning_banner",
     "//chrome/test/data/webui:chai_assert",
@@ -189,11 +189,11 @@
   ]
 }
 
-js_test_gen_html("js_test_gen_html_modules") {
+js_test_type_check("js_test_type_check") {
   deps = [
-    ":educational_banner_unittest.m",
-    ":state_banner_unittest.m",
-    ":warning_banner_unittest.m",
+    ":educational_banner_unittest",
+    ":state_banner_unittest",
+    ":warning_banner_unittest",
   ]
   is_polymer3 = true
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js
similarity index 100%
rename from ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.m.js
rename to ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js
diff --git a/ui/file_manager/file_names.gni b/ui/file_manager/file_names.gni
index ddb3f20c..af5f097 100644
--- a/ui/file_manager/file_names.gni
+++ b/ui/file_manager/file_names.gni
@@ -10,7 +10,7 @@
 ]
 
 image_loader_static_js_files = [
-  "image_loader/background.m.js",
+  "image_loader/background.js",
   "image_loader/cache.js",
   "image_loader/image_loader.js",
   "image_loader/image_loader_client.js",
@@ -37,7 +37,7 @@
   "file_manager/background/js/file_operation_util.js",
   "file_manager/background/js/import_history.js",
   "file_manager/background/js/launcher.js",
-  "file_manager/background/js/main_background.m.js",
+  "file_manager/background/js/main_background.js",
   "file_manager/background/js/media_import_handler.js",
   "file_manager/background/js/media_scanner.js",
   "file_manager/background/js/metadata_proxy.js",
@@ -137,7 +137,7 @@
   "file_manager/foreground/js/constants.js",
   "file_manager/foreground/js/crossover_search_utils.js",
   "file_manager/foreground/js/crostini_controller.js",
-  "file_manager/foreground/js/deferred_elements.m.js",
+  "file_manager/foreground/js/deferred_elements.js",
   "file_manager/foreground/js/dialog_action_controller.js",
   "file_manager/foreground/js/directory_contents.js",
   "file_manager/foreground/js/directory_model.js",
@@ -338,86 +338,87 @@
 
 # Test files:
 unittest_files = [
-  "file_manager/common/js/util_unittest.m.js",
-  "file_manager/common/js/filtered_volume_manager_unittest.m.js",
-  "file_manager/common/js/file_type_unittest.m.js",
-  "file_manager/common/js/lru_cache_unittest.m.js",
-  "file_manager/common/js/importer_common_unittest.m.js",
-  "file_manager/common/js/files_app_entry_types_unittest.m.js",
-  "file_manager/common/js/recent_date_bucket_unittest.m.js",
-  "file_manager/common/js/storage_adapter_unittest.m.js",
-  "file_manager/common/js/volume_manager_types_unittest.m.js",
-  "file_manager/background/js/mount_metrics_unittest.m.js",
-  "file_manager/background/js/drive_sync_handler_unittest.m.js",
-  "file_manager/background/js/media_import_handler_unittest.m.js",
-  "file_manager/background/js/task_queue_unittest.m.js",
-  "file_manager/background/js/file_operation_handler_unittest.m.js",
-  "file_manager/background/js/file_operation_manager_unittest.m.js",
-  "file_manager/background/js/trash_unittest.m.js",
-  "file_manager/background/js/duplicate_finder_unittest.m.js",
-  "file_manager/background/js/volume_manager_unittest.m.js",
-  "file_manager/background/js/media_scanner_unittest.m.js",
-  "file_manager/background/js/import_history_unittest.m.js",
-  "file_manager/background/js/metadata_proxy_unittest.m.js",
-  "file_manager/background/js/crostini_unittest.m.js",
-  "file_manager/background/js/device_handler_unittest.m.js",
-  "file_manager/foreground/elements/files_password_dialog_unittest.m.js",
-  "file_manager/foreground/elements/files_xf_elements_unittest.m.js",
-  "file_manager/foreground/elements/files_toast_unittest.m.js",
-  "file_manager/foreground/elements/files_tooltip_unittest.m.js",
-  "file_manager/foreground/js/metadata/image_orientation_unittest.m.js",
-  "file_manager/foreground/js/metadata/metadata_cache_item_unittest.m.js",
-  "file_manager/foreground/js/metadata/exif_parser_unittest.m.js",
-  "file_manager/foreground/js/metadata/thumbnail_model_unittest.m.js",
-  "file_manager/foreground/js/metadata/metadata_model_unittest.m.js",
-  "file_manager/foreground/js/metadata/content_metadata_provider_unittest.m.js",
-  "file_manager/foreground/js/metadata/external_metadata_provider_unittest.m.js",
-  "file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.m.js",
-  "file_manager/foreground/js/metadata/metadata_cache_set_unittest.m.js",
-  "file_manager/foreground/js/metadata/multi_metadata_provider_unittest.m.js",
-  "file_manager/foreground/js/file_manager_commands_unittest.m.js",
-  "file_manager/foreground/js/task_controller_unittest.m.js",
-  "file_manager/foreground/js/thumbnail_loader_unittest.m.js",
-  "file_manager/foreground/js/directory_contents_unittest.m.js",
-  "file_manager/foreground/js/file_list_model_unittest.m.js",
-  "file_manager/foreground/js/banner_controller_unittest.m.js",
-  "file_manager/foreground/js/providers_model_unittest.m.js",
-  "file_manager/foreground/js/spinner_controller_unittest.m.js",
-  "file_manager/foreground/js/banner_util_unittest.m.js",
-  "file_manager/foreground/js/list_thumbnail_loader_unittest.m.js",
-  "file_manager/foreground/js/file_type_filters_controller_unittest.m.js",
-  "file_manager/foreground/js/path_component_unittest.m.js",
-  "file_manager/foreground/js/actions_model_unittest.m.js",
-  "file_manager/foreground/js/ui/file_manager_dialog_base_unittest.m.js",
-  "file_manager/foreground/js/ui/actions_submenu_unittest.m.js",
-  "file_manager/foreground/js/ui/file_table_unittest.m.js",
-  "file_manager/foreground/js/ui/file_tap_handler_unittest.m.js",
-  "file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js",
-  "file_manager/foreground/js/ui/file_table_list_unittest.m.js",
-  "file_manager/foreground/js/ui/multi_menu_unittest.m.js",
+  "file_manager/common/js/util_unittest.js",
+  "file_manager/common/js/filtered_volume_manager_unittest.js",
+  "file_manager/common/js/file_type_unittest.js",
+  "file_manager/common/js/lru_cache_unittest.js",
+  "file_manager/common/js/importer_common_unittest.js",
+  "file_manager/common/js/files_app_entry_types_unittest.js",
+  "file_manager/common/js/recent_date_bucket_unittest.js",
+  "file_manager/common/js/storage_adapter_unittest.js",
+  "file_manager/common/js/volume_manager_types_unittest.js",
+  "file_manager/background/js/mount_metrics_unittest.js",
+  "file_manager/background/js/drive_sync_handler_unittest.js",
+  "file_manager/background/js/media_import_handler_unittest.js",
+  "file_manager/background/js/task_queue_unittest.js",
+  "file_manager/background/js/file_operation_handler_unittest.js",
+  "file_manager/background/js/file_operation_manager_unittest.js",
+  "file_manager/background/js/trash_unittest.js",
+  "file_manager/background/js/duplicate_finder_unittest.js",
+  "file_manager/background/js/volume_manager_unittest.js",
+  "file_manager/background/js/media_scanner_unittest.js",
+  "file_manager/background/js/import_history_unittest.js",
+  "file_manager/background/js/metadata_proxy_unittest.js",
+  "file_manager/background/js/crostini_unittest.js",
+  "file_manager/background/js/device_handler_unittest.js",
+  "file_manager/foreground/elements/files_password_dialog_unittest.js",
+  "file_manager/foreground/elements/files_xf_elements_unittest.js",
+  "file_manager/foreground/elements/files_toast_unittest.js",
+  "file_manager/foreground/elements/files_tooltip_unittest.js",
+  "file_manager/foreground/js/metadata/image_orientation_unittest.js",
+  "file_manager/foreground/js/metadata/metadata_cache_item_unittest.js",
+  "file_manager/foreground/js/metadata/exif_parser_unittest.js",
+  "file_manager/foreground/js/metadata/thumbnail_model_unittest.js",
+  "file_manager/foreground/js/metadata/metadata_model_unittest.js",
+  "file_manager/foreground/js/metadata/content_metadata_provider_unittest.js",
+  "file_manager/foreground/js/metadata/external_metadata_provider_unittest.js",
+  "file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js",
+  "file_manager/foreground/js/metadata/metadata_cache_set_unittest.js",
+  "file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js",
+  "file_manager/foreground/js/file_manager_commands_unittest.js",
+  "file_manager/foreground/js/task_controller_unittest.js",
+  "file_manager/foreground/js/thumbnail_loader_unittest.js",
+  "file_manager/foreground/js/directory_contents_unittest.js",
+  "file_manager/foreground/js/file_list_model_unittest.js",
+  "file_manager/foreground/js/banner_controller_unittest.js",
+  "file_manager/foreground/js/providers_model_unittest.js",
+  "file_manager/foreground/js/spinner_controller_unittest.js",
+  "file_manager/foreground/js/banner_util_unittest.js",
+  "file_manager/foreground/js/list_thumbnail_loader_unittest.js",
+  "file_manager/foreground/js/file_type_filters_controller_unittest.js",
+  "file_manager/foreground/js/path_component_unittest.js",
+  "file_manager/foreground/js/actions_model_unittest.js",
+  "file_manager/foreground/js/ui/file_manager_dialog_base_unittest.js",
+  "file_manager/foreground/js/ui/actions_submenu_unittest.js",
+  "file_manager/foreground/js/ui/file_table_unittest.js",
+  "file_manager/foreground/js/ui/file_tap_handler_unittest.js",
+  "file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js",
+  "file_manager/foreground/js/ui/file_table_list_unittest.js",
+  "file_manager/foreground/js/ui/multi_menu_unittest.js",
   "file_manager/foreground/js/ui/splitter_unittest.js",
-  "file_manager/foreground/js/ui/banners/state_banner_unittest.m.js",
-  "file_manager/foreground/js/ui/banners/educational_banner_unittest.m.js",
-  "file_manager/foreground/js/ui/banners/warning_banner_unittest.m.js",
-  "file_manager/foreground/js/ui/breadcrumb_unittest.m.js",
-  "file_manager/foreground/js/ui/file_list_selection_model_unittest.m.js",
-  "file_manager/foreground/js/ui/directory_tree_unittest.m.js",
-  "file_manager/foreground/js/navigation_list_model_unittest.m.js",
-  "file_manager/foreground/js/directory_model_unittest.m.js",
-  "file_manager/foreground/js/file_tasks_unittest.m.js",
-  "file_manager/foreground/js/file_transfer_controller_unittest.m.js",
-  "file_manager/foreground/js/import_controller_unittest.m.js",
-  "image_loader/scheduler_unittest.m.js",
-  "image_loader/image_loader_unittest.m.js",
-  "image_loader/cache_unittest.m.js",
-  "image_loader/image_loader_client_unittest.m.js",
+  "file_manager/foreground/js/ui/banners/state_banner_unittest.js",
+  "file_manager/foreground/js/ui/banners/educational_banner_unittest.js",
+  "file_manager/foreground/js/ui/banners/warning_banner_unittest.js",
+  "file_manager/foreground/js/ui/breadcrumb_unittest.js",
+  "file_manager/foreground/js/ui/file_list_selection_model_unittest.js",
+  "file_manager/foreground/js/ui/directory_tree_unittest.js",
+  "file_manager/foreground/js/navigation_list_model_unittest.js",
+  "file_manager/foreground/js/directory_model_unittest.js",
+  "file_manager/foreground/js/file_tasks_unittest.js",
+  "file_manager/foreground/js/file_transfer_controller_unittest.js",
+  "file_manager/foreground/js/import_controller_unittest.js",
+  "image_loader/scheduler_unittest.js",
+  "image_loader/image_loader_unittest.js",
+  "image_loader/cache_unittest.js",
+  "image_loader/image_loader_client_unittest.js",
 ]
 
-generated_test_htmls = []
-foreach(_t, unittest_files) {
-  generated_test_htmls += [ string_replace(_t, ".js", "_gen.html") ]
-}
-
 # Files that don't have the generated HTML, but are used for tests.
-unittest_files += [ "file_manager/common/js/mock_util.js" ]
+unittest_files += [
+  # Test harness
+  "base/js/test_harness.html",
+  "base/js/test_harness.js",
+
+  "file_manager/common/js/mock_util.js",
+]
 # END: Test files.
diff --git a/ui/file_manager/image_loader/BUILD.gn b/ui/file_manager/image_loader/BUILD.gn
index e55ba3a..ed00f96 100644
--- a/ui/file_manager/image_loader/BUILD.gn
+++ b/ui/file_manager/image_loader/BUILD.gn
@@ -5,7 +5,7 @@
 import("//chrome/browser/resources/tools/optimize_webui.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//third_party/closure_compiler/js_unit_tests.gni")
-import("//ui/file_manager/base/gn/js_test_gen_html.gni")
+import("//ui/file_manager/base/gn/js_test_type_check.gni")
 
 js_type_check("closure_compile_jsmodules") {
   closure_flags = default_closure_args + [
@@ -15,7 +15,7 @@
                     "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"",
                   ]
   deps = [
-    ":background.m",
+    ":background",
     ":cache",
     ":image_loader_client",
     ":image_loader_util",
@@ -26,13 +26,13 @@
   ]
 }
 
-js_library("background.m") {
+js_library("background") {
 }
 
 js_library("cache") {
 }
 
-js_unittest("cache_unittest.m") {
+js_unittest("cache_unittest") {
   deps = [
     ":load_image_request",
     "//chrome/test/data/webui:chai_assert",
@@ -70,7 +70,7 @@
   ]
 }
 
-js_unittest("image_loader_unittest.m") {
+js_unittest("image_loader_unittest") {
   deps = [
     ":image_loader_util",
     ":image_orientation",
@@ -106,7 +106,7 @@
   ]
 }
 
-js_unittest("image_loader_client_unittest.m") {
+js_unittest("image_loader_client_unittest") {
   deps = [
     ":image_loader_client",
     ":load_image_request",
@@ -141,7 +141,7 @@
   deps = [ ":image_request_task" ]
 }
 
-js_unittest("scheduler_unittest.m") {
+js_unittest("scheduler_unittest") {
   deps = [
     ":image_request_task",
     ":scheduler",
@@ -149,12 +149,12 @@
   ]
 }
 
-js_test_gen_html("js_test_gen_html_modules") {
+js_test_type_check("js_test_type_check") {
   deps = [
-    ":cache_unittest.m",
-    ":image_loader_client_unittest.m",
-    ":image_loader_unittest.m",
-    ":scheduler_unittest.m",
+    ":cache_unittest",
+    ":image_loader_client_unittest",
+    ":image_loader_unittest",
+    ":scheduler_unittest",
   ]
 
   closure_flags = strict_error_checking_closure_args + [
@@ -170,7 +170,7 @@
   testonly = true
   deps = [
     ":closure_compile_jsmodules",
-    ":js_test_gen_html_modules_type_check_auto",
+    ":js_test_type_check",
   ]
 }
 
@@ -203,9 +203,9 @@
   host = "image_loader"
 
   input = preprocess_folder
-  js_module_in_files = [ "background.m.js" ]
+  js_module_in_files = [ "background.js" ]
 
-  js_out_files = [ "background.m.rollup.js" ]
+  js_out_files = [ "background.rollup.js" ]
 
   external_paths = [
     "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path",
@@ -213,7 +213,7 @@
   ]
 
   deps = [
-    ":background.m",
+    ":background",
     "//ui/file_manager:preprocess_generated",
     "//ui/file_manager:preprocess_generated_image_loader",
     "//ui/file_manager:preprocess_static",
diff --git a/ui/file_manager/image_loader/background.html b/ui/file_manager/image_loader/background.html
index ffd7fa5..51bb786 100644
--- a/ui/file_manager/image_loader/background.html
+++ b/ui/file_manager/image_loader/background.html
@@ -2,4 +2,4 @@
 <meta charset="utf-8">
 
 <script src="piex/piex.js.wasm"></script>
-<script type="module" src="background.m.js"></script>
+<script type="module" src="background.js"></script>
diff --git a/ui/file_manager/image_loader/background.m.js b/ui/file_manager/image_loader/background.js
similarity index 100%
rename from ui/file_manager/image_loader/background.m.js
rename to ui/file_manager/image_loader/background.js
diff --git a/ui/file_manager/image_loader/cache_unittest.m.js b/ui/file_manager/image_loader/cache_unittest.js
similarity index 100%
rename from ui/file_manager/image_loader/cache_unittest.m.js
rename to ui/file_manager/image_loader/cache_unittest.js
diff --git a/ui/file_manager/image_loader/image_loader_client_unittest.m.js b/ui/file_manager/image_loader/image_loader_client_unittest.js
similarity index 100%
rename from ui/file_manager/image_loader/image_loader_client_unittest.m.js
rename to ui/file_manager/image_loader/image_loader_client_unittest.js
diff --git a/ui/file_manager/image_loader/image_loader_unittest.m.js b/ui/file_manager/image_loader/image_loader_unittest.js
similarity index 100%
rename from ui/file_manager/image_loader/image_loader_unittest.m.js
rename to ui/file_manager/image_loader/image_loader_unittest.js
diff --git a/ui/file_manager/image_loader/scheduler_unittest.m.js b/ui/file_manager/image_loader/scheduler_unittest.js
similarity index 100%
rename from ui/file_manager/image_loader/scheduler_unittest.m.js
rename to ui/file_manager/image_loader/scheduler_unittest.js
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
index 45bfff9..6584e72a 100644
--- a/ui/gl/gl_context.cc
+++ b/ui/gl/gl_context.cc
@@ -304,8 +304,6 @@
     case kGLImplementationEGLGLES2:
     case kGLImplementationEGLANGLE:
       return true;
-    case kGLImplementationAppleGL:
-      return false;
     case kGLImplementationMockGL:
     case kGLImplementationStubGL:
       return false;
diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc
index 7aa2655..2ced049 100644
--- a/ui/gl/gl_context_cgl.cc
+++ b/ui/gl/gl_context_cgl.cc
@@ -45,11 +45,6 @@
     attribs.push_back(kCGLPFAAllowOfflineRenderers);
     g_support_renderer_switching = true;
   }
-  if (GetGLImplementation() == kGLImplementationAppleGL) {
-    attribs.push_back(kCGLPFARendererID);
-    attribs.push_back((CGLPixelFormatAttribute) kCGLRendererGenericFloatID);
-    g_support_renderer_switching = false;
-  }
   if (GetGLImplementation() == kGLImplementationDesktopGLCoreProfile) {
     attribs.push_back(kCGLPFAOpenGLProfile);
     attribs.push_back((CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core);
diff --git a/ui/gl/gl_image_native_pixmap.cc b/ui/gl/gl_image_native_pixmap.cc
index c539c8e..b68eb27 100644
--- a/ui/gl/gl_image_native_pixmap.cc
+++ b/ui/gl/gl_image_native_pixmap.cc
@@ -158,20 +158,20 @@
     if (format_ == gfx::BufferFormat::YUV_420_BIPLANAR ||
         format_ == gfx::BufferFormat::YVU_420) {
       // TODO(b/233667677): since https://crrev.com/c/3662252, the only NV12
-      // quads that we allow to be promoted to overlays are those that use the
-      // BT.709 primaries (approximately the same as the BT.601 primaries) with
-      // limited range. Furthermore, since https://crrev.com/c/2336347, we force
-      // the DRM/KMS driver to use BT.601 with limited range. Therefore, for
-      // compositing purposes, we need to a) use EGL_ITU_REC601_EXT for any
-      // video frames that might be promoted to overlays - we shouldn't use
-      // EGL_ITU_REC709_EXT because we might then see a slight difference in
+      // quads that we allow to be promoted to overlays are those that use
+      // non-BT.2020 primaries with non-full range. Furthermore, since
+      // https://crrev.com/c/2336347, we force the DRM/KMS driver to use BT.601
+      // with limited range. Therefore, for compositing purposes, we need to
+      // a) use EGL_ITU_REC601_EXT for any video frames that might be promoted
+      // to overlays - e.g., we shouldn't use EGL_ITU_REC709_EXT for BT709
+      // frames because we might then see a slight difference in
       // compositing vs. overlays (note that the BT.601 and BT.709 primaries are
       // very close to each other, so this shouldn't be a huge correctness
       // issue); b) use EGL_ITU_REC2020_EXT for BT.2020 frames in order to
       // composite them correctly (and we won't need to worry about a difference
       // in compositing vs. overlays in this case since those frames won't be
       // promoted to overlays). We'll need to revisit this once we plumb the
-      // color space and range to DRM/KMS.
+      // YUV color encoding and range to DRM/KMS.
       attrs.push_back(EGL_YUV_COLOR_SPACE_HINT_EXT);
       switch (color_space_.GetPrimaryID()) {
         case gfx::ColorSpace::PrimaryID::BT2020:
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc
index a3cec15..66651fa 100644
--- a/ui/gl/gl_implementation.cc
+++ b/ui/gl/gl_implementation.cc
@@ -68,9 +68,6 @@
     case GLImplementation::kGLImplementationDesktopGLCoreProfile:
       s << "desktop-gl-core-profile";
       break;
-    case GLImplementation::kGLImplementationAppleGL:
-      s << "apple-gl";
-      break;
     case GLImplementation::kGLImplementationEGLGLES2:
       s << "egl-gles2";
       break;
@@ -133,10 +130,6 @@
 } kGLImplementationNamePairs[] = {
     {kGLImplementationDesktopName, kANGLEImplementationNoneName,
      GLImplementationParts(kGLImplementationDesktopGL)},
-#if BUILDFLAG(IS_APPLE)
-    {kGLImplementationAppleName, kANGLEImplementationNoneName,
-     GLImplementationParts(kGLImplementationAppleGL)},
-#endif
     {kGLImplementationEGLName, kANGLEImplementationNoneName,
      GLImplementationParts(kGLImplementationEGLGLES2)},
     {kGLImplementationANGLEName, kANGLEImplementationNoneName,
@@ -365,8 +358,7 @@
 
 bool HasDesktopGLFeatures() {
   return kGLImplementationDesktopGL == g_gl_implementation.gl ||
-         kGLImplementationDesktopGLCoreProfile == g_gl_implementation.gl ||
-         kGLImplementationAppleGL == g_gl_implementation.gl;
+         kGLImplementationDesktopGLCoreProfile == g_gl_implementation.gl;
 }
 
 void AddGLNativeLibrary(base::NativeLibrary library) {
diff --git a/ui/gl/gl_implementation.h b/ui/gl/gl_implementation.h
index 497152c..fa82bed 100644
--- a/ui/gl/gl_implementation.h
+++ b/ui/gl/gl_implementation.h
@@ -34,9 +34,9 @@
   kGLImplementationNone = 0,
   kGLImplementationDesktopGL = 1,
   kGLImplementationDesktopGLCoreProfile = 2,
-  // Note: 3 used to be legacy SwiftShader, so 3 is skipped and should not be
-  // reused.
-  kGLImplementationAppleGL = 4,
+  // Note: 3 and 4 are skipped and should not be reused.
+  // 3 used to be legacy SwiftShader.
+  // 4 used to be Apple's software GL.
   kGLImplementationEGLGLES2 = 5,  // Native EGL/GLES2
   kGLImplementationMockGL = 6,
   kGLImplementationStubGL = 7,
diff --git a/ui/gl/init/gl_factory_mac.cc b/ui/gl/init/gl_factory_mac.cc
index 4de2742..95a53815 100644
--- a/ui/gl/init/gl_factory_mac.cc
+++ b/ui/gl/init/gl_factory_mac.cc
@@ -66,7 +66,6 @@
   impls.emplace_back(
       GLImplementationParts(kGLImplementationDesktopGLCoreProfile));
   impls.emplace_back(GLImplementationParts(kGLImplementationDesktopGL));
-  impls.emplace_back(GLImplementationParts(kGLImplementationAppleGL));
 #if defined(USE_EGL)
   impls.emplace_back(GLImplementationParts(kGLImplementationEGLGLES2));
   impls.emplace_back(GLImplementationParts(kGLImplementationEGLANGLE));
@@ -86,7 +85,6 @@
   switch (GetGLImplementation()) {
     case kGLImplementationDesktopGL:
     case kGLImplementationDesktopGLCoreProfile:
-    case kGLImplementationAppleGL:
       return InitializeGLContext(new GLContextCGL(share_group),
                                  compatible_surface, attribs);
 #if defined(USE_EGL)
@@ -114,7 +112,6 @@
   switch (GetGLImplementation()) {
     case kGLImplementationDesktopGL:
     case kGLImplementationDesktopGLCoreProfile:
-    case kGLImplementationAppleGL:
     case kGLImplementationEGLGLES2:
     case kGLImplementationEGLANGLE: {
       NOTIMPLEMENTED() << "No onscreen support on Mac.";
@@ -135,7 +132,6 @@
   switch (GetGLImplementation()) {
     case kGLImplementationDesktopGL:
     case kGLImplementationDesktopGLCoreProfile:
-    case kGLImplementationAppleGL:
       return InitializeGLSurfaceWithFormat(
           new NoOpGLSurface(size), format);
 #if defined(USE_EGL)
diff --git a/ui/gl/init/gl_initializer_mac.cc b/ui/gl/init/gl_initializer_mac.cc
index fa9771391..edbbaed 100644
--- a/ui/gl/init/gl_initializer_mac.cc
+++ b/ui/gl/init/gl_initializer_mac.cc
@@ -52,11 +52,6 @@
     // format selection.
     attribs.push_back(kCGLPFAAllowOfflineRenderers);
   }
-  if (GetGLImplementation() == kGLImplementationAppleGL) {
-    attribs.push_back(kCGLPFARendererID);
-    attribs.push_back(
-        static_cast<CGLPixelFormatAttribute>(kCGLRendererGenericFloatID));
-  }
   attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
 
   CGLPixelFormatObj format;
@@ -175,7 +170,6 @@
   switch (GetGLImplementation()) {
     case kGLImplementationDesktopGL:
     case kGLImplementationDesktopGLCoreProfile:
-    case kGLImplementationAppleGL:
       if (!InitializeOneOffForSandbox()) {
         LOG(ERROR) << "GLSurfaceCGL::InitializeOneOff failed.";
       }
@@ -212,7 +206,6 @@
   switch (implementation.gl) {
     case kGLImplementationDesktopGL:
     case kGLImplementationDesktopGLCoreProfile:
-    case kGLImplementationAppleGL:
       return InitializeStaticCGLInternal(implementation.gl);
 #if defined(USE_EGL)
     case kGLImplementationEGLGLES2:
diff --git a/ui/ozone/common/gl_ozone_egl.cc b/ui/ozone/common/gl_ozone_egl.cc
index 45bf416..7fd7fea 100644
--- a/ui/ozone/common/gl_ozone_egl.cc
+++ b/ui/ozone/common/gl_ozone_egl.cc
@@ -65,10 +65,11 @@
     gfx::BufferFormat plane_format,
     gfx::BufferPlane plane,
     gfx::Size plane_size,
+    const gfx::ColorSpace& color_space,
     GLenum target,
     GLuint texture_id) {
   return NativePixmapEGLBinding::Create(pixmap, plane_format, plane, plane_size,
-                                        target, texture_id);
+                                        color_space, target, texture_id);
 }
 
 bool GLOzoneEGL::GetGLWindowSystemBindingInfo(
diff --git a/ui/ozone/common/gl_ozone_egl.h b/ui/ozone/common/gl_ozone_egl.h
index a3ebdca..0560d835 100644
--- a/ui/ozone/common/gl_ozone_egl.h
+++ b/ui/ozone/common/gl_ozone_egl.h
@@ -38,6 +38,7 @@
       gfx::BufferFormat plane_format,
       gfx::BufferPlane plane,
       gfx::Size plane_size,
+      const gfx::ColorSpace& color_space,
       GLenum target,
       GLuint texture_id) override;
   bool GetGLWindowSystemBindingInfo(
diff --git a/ui/ozone/common/native_pixmap_egl_binding.cc b/ui/ozone/common/native_pixmap_egl_binding.cc
index 5e99f68..4ce29fe 100644
--- a/ui/ozone/common/native_pixmap_egl_binding.cc
+++ b/ui/ozone/common/native_pixmap_egl_binding.cc
@@ -19,10 +19,13 @@
     gfx::BufferFormat plane_format,
     gfx::BufferPlane plane,
     gfx::Size plane_size,
+    const gfx::ColorSpace& color_space,
     GLenum target,
     GLuint texture_id) {
   auto gl_image = base::MakeRefCounted<gl::GLImageNativePixmap>(
       plane_size, plane_format, plane);
+  if (color_space.IsValid())
+    gl_image->SetColorSpace(color_space);
   if (!gl_image->Initialize(std::move(pixmap))) {
     LOG(ERROR) << "Unable to initialize GL image from pixmap";
     return nullptr;
diff --git a/ui/ozone/common/native_pixmap_egl_binding.h b/ui/ozone/common/native_pixmap_egl_binding.h
index b6e8af3..5a1bf1c 100644
--- a/ui/ozone/common/native_pixmap_egl_binding.h
+++ b/ui/ozone/common/native_pixmap_egl_binding.h
@@ -20,6 +20,7 @@
       gfx::BufferFormat plane_format,
       gfx::BufferPlane plane,
       gfx::Size plane_size,
+      const gfx::ColorSpace& color_space,
       GLenum target,
       GLuint texture_id);
 };
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_factory.cc b/ui/ozone/platform/wayland/host/wayland_buffer_factory.cc
index 29fe9c1..bad5a26 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_factory.cc
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_factory.cc
@@ -69,4 +69,14 @@
 #endif
 }
 
+bool WaylandBufferFactory::CanCreateDmabufImmed() const {
+#if defined(WAYLAND_GBM)
+  if (wayland_zwp_dmabuf_)
+    return wayland_zwp_dmabuf_->CanCreateBufferImmed();
+  else if (wayland_drm_)
+    return wayland_drm_->CanCreateBufferImmed();
+#endif
+  return false;
+}
+
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_factory.h b/ui/ozone/platform/wayland/host/wayland_buffer_factory.h
index 36ceb55..25b93f16 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_factory.h
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_factory.h
@@ -32,7 +32,10 @@
   // Requests to create a wl_buffer backed by the dmabuf prime |fd| descriptor.
   // The result is sent back via the |callback|. If buffer creation failed,
   // nullptr is sent back via the callback. Otherwise, a pointer to the
-  // |wl_buffer| is sent.
+  // |wl_buffer| is sent. Depending on the result of |CanCreateDmabufImmed|,
+  // a buffer can be created immediately which means the callback will be fired
+  // immediately and the client will not have to wait until the buffer is
+  // created.
   void CreateDmabufBuffer(const base::ScopedFD& fd,
                           const gfx::Size& size,
                           const std::vector<uint32_t>& strides,
@@ -60,6 +63,10 @@
   // Returns true if dmabuf is supported.
   bool SupportsDmabuf() const;
 
+  // Returns true if a dmabuf buffer can be created immediately. If not, a
+  // dmabuf backed buffer is created asynchronously.
+  bool CanCreateDmabufImmed() const;
+
   // Returns wl_shm. This has to be unfortunately exposed as
   // WaylandCursorFactory uses wl_cursor_theme_load to load a cursor theme,
   // which requires to pass the wl_shm object as a parameter when called.
diff --git a/ui/ozone/platform/wayland/host/wayland_drm.cc b/ui/ozone/platform/wayland/host/wayland_drm.cc
index 47ce683..12cd565 100644
--- a/ui/ozone/platform/wayland/host/wayland_drm.cc
+++ b/ui/ozone/platform/wayland/host/wayland_drm.cc
@@ -95,6 +95,12 @@
   std::move(callback).Run(std::move(buffer));
 }
 
+bool WaylandDrm::CanCreateBufferImmed() const {
+  // Unlike the WaylandZwpLinuxDmabuf, the WaylandDrm always creates wl_buffers
+  // immediately.
+  return true;
+}
+
 void WaylandDrm::HandleDrmFailure(const std::string& error) {
   LOG(WARNING) << error;
   wl_drm_.reset();
diff --git a/ui/ozone/platform/wayland/host/wayland_drm.h b/ui/ozone/platform/wayland/host/wayland_drm.h
index df4f195..fcc9825 100644
--- a/ui/ozone/platform/wayland/host/wayland_drm.h
+++ b/ui/ozone/platform/wayland/host/wayland_drm.h
@@ -65,6 +65,9 @@
     return supported_buffer_formats_;
   }
 
+  // Says if a new buffer can be created immediately.
+  bool CanCreateBufferImmed() const;
+
  private:
   // Resets the |wl_drm| and prints the error.
   void HandleDrmFailure(const std::string& error);
diff --git a/ui/ozone/platform/wayland/host/wayland_event_source.cc b/ui/ozone/platform/wayland/host/wayland_event_source.cc
index 84fdca8c..65a9f25 100644
--- a/ui/ozone/platform/wayland/host/wayland_event_source.cc
+++ b/ui/ozone/platform/wayland/host/wayland_event_source.cc
@@ -352,7 +352,7 @@
     return;
   }
 
-  PointerDetails details(PointerDetailsForDispatching(id));
+  PointerDetails details(EventPointerType::kTouch, id);
   TouchEvent event(ET_TOUCH_PRESSED, location, location, timestamp, details,
                    keyboard_modifiers_);
   DCHECK_EQ(dispatch_policy, DispatchPolicy::kOnFrame);
@@ -424,7 +424,7 @@
     return;
   }
   it->second->last_known_location = location;
-  PointerDetails details(PointerDetailsForDispatching(id));
+  PointerDetails details(EventPointerType::kTouch, id);
   TouchEvent event(ET_TOUCH_MOVED, location, location, timestamp, details,
                    keyboard_modifiers_);
   if (dispatch_policy == DispatchPolicy::kImmediate) {
@@ -462,6 +462,17 @@
     auto touch_frame = std::move(touch_frames_.front());
     touch_frames_.pop_front();
 
+    // In case there are touch stylus information, override the current 'event'
+    // instance, given that PointerDetails is 'const'.
+    auto pointer_details_with_stylus_data =
+        AmendStylusData(touch_frame->event.pointer_details().id);
+    if (pointer_details_with_stylus_data) {
+      auto old_event = touch_frame->event;
+      touch_frame->event = TouchEvent(
+          old_event.type(), old_event.location_f(), old_event.root_location_f(),
+          old_event.time_stamp(), pointer_details_with_stylus_data.value(),
+          old_event.flags());
+    }
     DispatchEvent(&(touch_frame->event));
     if (!touch_frame->completion_cb.is_null())
       std::move(touch_frame->completion_cb).Run();
@@ -483,25 +494,6 @@
     PointerId pointer_id,
     EventPointerType pointer_type) {
   last_touch_stylus_tool_[pointer_id] = pointer_type;
-
-  // Update in-transit touch frames.
-  for (auto& touch_frame : touch_frames_) {
-    const auto& old_pointer_details = touch_frame->event.pointer_details();
-    if (old_pointer_details.id != pointer_id)
-      continue;
-
-    if (old_pointer_details.pointer_type == pointer_type)
-      break;
-
-    // Override the previous 'event' instance, given that PointerDetails
-    // is 'const'.
-    auto old_event = touch_frame->event;
-    touch_frame->event =
-        TouchEvent(old_event.type(), old_event.location_f(),
-                   old_event.root_location_f(), old_event.time_stamp(),
-                   PointerDetailsForDispatching(pointer_id), old_event.flags());
-    break;
-  }
 }
 
 const WaylandWindow* WaylandEventSource::GetTouchTarget(PointerId id) const {
@@ -651,12 +643,12 @@
   return PointerDetails(*last_pointer_stylus_tool_);
 }
 
-PointerDetails WaylandEventSource::PointerDetailsForDispatching(
+absl::optional<PointerDetails> WaylandEventSource::AmendStylusData(
     PointerId pointer_id) const {
   const auto it = last_touch_stylus_tool_.find(pointer_id);
   if (it == last_touch_stylus_tool_.end() || !it->second ||
       it->second == EventPointerType::kTouch) {
-    return PointerDetails(EventPointerType::kTouch, pointer_id);
+    return absl::nullopt;
   }
 
   return PointerDetails(it->second.value(), pointer_id);
diff --git a/ui/ozone/platform/wayland/host/wayland_event_source.h b/ui/ozone/platform/wayland/host/wayland_event_source.h
index 63e0733..83c9328 100644
--- a/ui/ozone/platform/wayland/host/wayland_event_source.h
+++ b/ui/ozone/platform/wayland/host/wayland_event_source.h
@@ -198,7 +198,7 @@
   PointerDetails PointerDetailsForDispatching() const;
 
   // For touch events.
-  PointerDetails PointerDetailsForDispatching(PointerId pointer_id) const;
+  absl::optional<PointerDetails> AmendStylusData(PointerId pointer_id) const;
 
   // Wrap up method to support async touch release processing.
   void OnTouchReleaseInternal(PointerId id);
@@ -232,7 +232,6 @@
   absl::optional<EventPointerType> last_pointer_stylus_tool_;
 
   // Last known touch stylus type (eg touch, pen or eraser).
-  // absl::optional<PointerId, EventPointerType> last_touch_stylus_tool_;
   base::flat_map<PointerId, absl::optional<EventPointerType>>
       last_touch_stylus_tool_;
 
diff --git a/ui/ozone/platform/wayland/host/wayland_frame_manager.cc b/ui/ozone/platform/wayland/host/wayland_frame_manager.cc
index 73f155e6..a609872 100644
--- a/ui/ozone/platform/wayland/host/wayland_frame_manager.cc
+++ b/ui/ozone/platform/wayland/host/wayland_frame_manager.cc
@@ -10,6 +10,7 @@
 #include "base/containers/adapters.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/size_conversions.h"
+#include "ui/ozone/platform/wayland/host/wayland_buffer_factory.h"
 #include "ui/ozone/platform/wayland/host/wayland_buffer_handle.h"
 #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
@@ -79,25 +80,24 @@
 void WaylandFrameManager::RecordFrame(std::unique_ptr<WaylandFrame> frame) {
   DCHECK_LE(pending_frames_.size(), 6u);
 
-  // Request for buffer handle creation at record time.
-  for (auto& subsurface_to_overlay : frame->subsurfaces_to_overlays) {
-    if (subsurface_to_overlay.second.buffer_id) {
-      auto* handle = connection_->buffer_manager_host()->EnsureBufferHandle(
-          subsurface_to_overlay.first->wayland_surface(),
-          subsurface_to_overlay.second.buffer_id);
-      if (!handle)
-        return;
-    }
-  }
-  if (frame->root_config.buffer_id) {
-    auto* handle = connection_->buffer_manager_host()->EnsureBufferHandle(
-        frame->root_surface, frame->root_config.buffer_id);
-    if (!handle)
-      return;
+  bool buffer_pending_creation = false;
+  // The |frame| may have buffers to be sent for submission, which might not
+  // have been created yet. This must be done now if they cannot be created
+  // immediately. Thus, dispatch this request so that buffers are created by the
+  // time this frame is played back if |pending_frames_| is not empty.
+  // Otherwise, there is no point to ensure wl_buffers exist as
+  // MaybeProcessPendingFrame will do that as well.
+  if (!connection_->wayland_buffer_factory()->CanCreateDmabufImmed() &&
+      !pending_frames_.empty()) {
+    buffer_pending_creation =
+        EnsureWlBuffersExist(*frame) && !frame->buffer_lost;
   }
 
   pending_frames_.push_back(std::move(frame));
-  MaybeProcessPendingFrame();
+  // There are wl_buffers missing, need to wait. MaybeProcessPendingFrame will
+  // be called as soon as buffers are created.
+  if (!buffer_pending_creation)
+    MaybeProcessPendingFrame();
 }
 
 void WaylandFrameManager::MaybeProcessPendingFrame() {
@@ -109,42 +109,6 @@
   if (!frame)
     return;
 
-  // Ensure wl_buffer existence.
-  WaylandBufferHandle* handle_pending_creation = nullptr;
-  for (auto& subsurface_to_overlay : frame->subsurfaces_to_overlays) {
-    if (subsurface_to_overlay.second.buffer_id) {
-      auto* handle = connection_->buffer_manager_host()->EnsureBufferHandle(
-          subsurface_to_overlay.first->wayland_surface(),
-          subsurface_to_overlay.second.buffer_id);
-      // Buffer is gone while this frame is pending, remove this config.
-      if (!handle) {
-        frame->buffer_lost = true;
-        subsurface_to_overlay.second = wl::WaylandOverlayConfig();
-      } else if (!handle->wl_buffer() && !handle_pending_creation) {
-        // Found the first not-ready buffer, let handle invoke
-        // MaybeProcessPendingFrame() when wl_buffer is created.
-        handle_pending_creation = handle;
-      }
-    }
-  }
-  if (frame->root_config.buffer_id) {
-    auto* handle = connection_->buffer_manager_host()->EnsureBufferHandle(
-        frame->root_surface, frame->root_config.buffer_id);
-    if (!handle) {
-      frame->buffer_lost = true;
-      frame->root_config = wl::WaylandOverlayConfig();
-    } else if (!handle->wl_buffer() && !handle_pending_creation) {
-      handle_pending_creation = handle;
-    }
-  }
-
-  // There are wl_buffers missing, need to wait.
-  if (handle_pending_creation) {
-    handle_pending_creation->set_buffer_created_callback(
-        base::BindOnce(&WaylandFrameManager::MaybeProcessPendingFrame,
-                       weak_factory_.GetWeakPtr()));
-    return;
-  }
   // Frame callback hasn't been acked, need to wait.
   if (!submitted_frames_.empty() &&
       submitted_frames_.back()->wl_frame_callback) {
@@ -154,6 +118,24 @@
   if (!window_->can_submit_frames())
     return;
 
+  // Ensure wl_buffer existence. This is called for the first time in the
+  // following cases:
+  // 1) if it is possible to create buffers immediately to ensure
+  // WaylandBufferHandles are not lost and to create wl_buffers if they have not
+  // existed yet (a new buffer is submitted).
+  // 2) or |pending_frames| was empty when RecordFrame for this |frame| was
+  // called regardless whether it is possible to create wl_buffers immediately
+  // or not.
+  const bool has_buffer_pending_creation = EnsureWlBuffersExist(*frame);
+  // There are wl_buffers missing, need to wait.
+  if (has_buffer_pending_creation && !frame->buffer_lost) {
+    DLOG_IF(FATAL,
+            has_buffer_pending_creation &&
+                connection_->wayland_buffer_factory()->CanCreateDmabufImmed())
+        << "Buffers should have been created immediately.";
+    return;
+  }
+
   std::unique_ptr<WaylandFrame> playback = std::move(pending_frames_.front());
   PlayBackFrame(std::move(playback));
 
@@ -441,6 +423,49 @@
   }
 }
 
+bool WaylandFrameManager::EnsureWlBuffersExist(WaylandFrame& frame) {
+  WaylandBufferHandle* handle_pending_creation = nullptr;
+  for (auto& subsurface_to_overlay : frame.subsurfaces_to_overlays) {
+    if (subsurface_to_overlay.second.buffer_id) {
+      auto* handle = connection_->buffer_manager_host()->EnsureBufferHandle(
+          subsurface_to_overlay.first->wayland_surface(),
+          subsurface_to_overlay.second.buffer_id);
+      // Buffer is gone while this frame is pending, remove this config.
+      if (!handle) {
+        frame.buffer_lost = true;
+        subsurface_to_overlay.second = wl::WaylandOverlayConfig();
+      } else if (!handle->wl_buffer() && !handle_pending_creation) {
+        // Found the first not-ready buffer, let handle invoke
+        // MaybeProcessPendingFrame() when wl_buffer is created.
+        handle_pending_creation = handle;
+      }
+    }
+  }
+  if (frame.root_config.buffer_id) {
+    auto* handle = connection_->buffer_manager_host()->EnsureBufferHandle(
+        frame.root_surface, frame.root_config.buffer_id);
+    if (!handle) {
+      frame.buffer_lost = true;
+      frame.root_config = wl::WaylandOverlayConfig();
+    } else if (!handle->wl_buffer() && !handle_pending_creation) {
+      handle_pending_creation = handle;
+    }
+  }
+
+  // Some buffers might have been lost. No need to wait.
+  if (frame.buffer_lost)
+    handle_pending_creation = nullptr;
+
+  // There are wl_buffers missing, schedule MaybeProcessPendingFrame so that
+  // it's called when buffers are created.
+  if (handle_pending_creation) {
+    handle_pending_creation->set_buffer_created_callback(
+        base::BindOnce(&WaylandFrameManager::MaybeProcessPendingFrame,
+                       weak_factory_.GetWeakPtr()));
+  }
+  return !!handle_pending_creation;
+}
+
 void WaylandFrameManager::OnExplicitBufferRelease(WaylandSurface* surface,
                                                   struct wl_buffer* wl_buffer,
                                                   base::ScopedFD fence) {
diff --git a/ui/ozone/platform/wayland/host/wayland_frame_manager.h b/ui/ozone/platform/wayland/host/wayland_frame_manager.h
index 76ff20ea..c9b904e 100644
--- a/ui/ozone/platform/wayland/host/wayland_frame_manager.h
+++ b/ui/ozone/platform/wayland/host/wayland_frame_manager.h
@@ -169,6 +169,13 @@
   // feedbacks if the number is too big.
   void VerifyNumberOfSubmittedFrames();
 
+  // Verifies wl_buffers for the given |frame| exist. If they do not yet exist,
+  // a callback to |MaybeProcessPendingFrame| is set and false is returned.
+  // If the frame contains a buffer id for an invalid WaylandBufferHandle, the
+  // |frame::buffer_lost| is set and false is returned. That means that the
+  // frame must not be used for the further submission.
+  bool EnsureWlBuffersExist(WaylandFrame& frame);
+
   const raw_ptr<WaylandWindow> window_;
 
   // When RecordFrame() is called, a Frame is pushed to |pending_frames_|. See
diff --git a/ui/ozone/platform/wayland/host/wayland_keyboard.cc b/ui/ozone/platform/wayland/host/wayland_keyboard.cc
index ef96d82d..5afac64f 100644
--- a/ui/ozone/platform/wayland/host/wayland_keyboard.cc
+++ b/ui/ozone/platform/wayland/host/wayland_keyboard.cc
@@ -289,8 +289,8 @@
   }
 
   DispatchKey(key, 0 /*scan_code*/, down, false /*repeat*/,
-              down ? absl::make_optional(serial) : absl::nullopt,
-              EventTimeForNow(), device_id(), EF_NONE, kind);
+              absl::make_optional(serial), EventTimeForNow(), device_id(),
+              EF_NONE, kind);
 }
 
 void WaylandKeyboard::DispatchKey(unsigned int key,
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
index fc59919..01ef1ae 100644
--- a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
@@ -88,8 +88,7 @@
 
   // It's possible to avoid waiting until the buffer is created and have it
   // immediately. This method is only available since the protocol version 2.
-  if (wl::get_version_of_object(zwp_linux_dmabuf_.get()) >=
-      ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_IMMED_SINCE_VERSION) {
+  if (CanCreateBufferImmed()) {
     wl::Object<wl_buffer> buffer(zwp_linux_buffer_params_v1_create_immed(
         params.get(), size.width(), size.height(), format, 0));
     std::move(callback).Run(std::move(buffer));
@@ -106,6 +105,11 @@
   connection_->ScheduleFlush();
 }
 
+bool WaylandZwpLinuxDmabuf::CanCreateBufferImmed() const {
+  return wl::get_version_of_object(zwp_linux_dmabuf_.get()) >=
+         ZWP_LINUX_BUFFER_PARAMS_V1_CREATE_IMMED_SINCE_VERSION;
+}
+
 void WaylandZwpLinuxDmabuf::AddSupportedFourCCFormatAndModifier(
     uint32_t fourcc_format,
     absl::optional<uint64_t> modifier) {
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h
index f4db7b5..03bdc70 100644
--- a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.h
@@ -64,6 +64,10 @@
     return supported_buffer_formats_with_modifiers_;
   }
 
+  // Says if a new buffer can be created immediately. Depends on the version of
+  // the |zwp_linux_dmabuf| object.
+  bool CanCreateBufferImmed() const;
+
  private:
   // Receives supported |fourcc_format| from either ::Modifers or ::Format call
   // (depending on the protocol version), and stores it as gfx::BufferFormat to
diff --git a/ui/ozone/platform/x11/gl_ozone_glx.cc b/ui/ozone/platform/x11/gl_ozone_glx.cc
index e71d8878..746adbd 100644
--- a/ui/ozone/platform/x11/gl_ozone_glx.cc
+++ b/ui/ozone/platform/x11/gl_ozone_glx.cc
@@ -98,6 +98,7 @@
     gfx::BufferFormat plane_format,
     gfx::BufferPlane plane,
     gfx::Size plane_size,
+    const gfx::ColorSpace& color_space,
     GLenum target,
     GLuint texture_id) {
   return NativePixmapGLXBinding::Create(pixmap, plane_format, plane, plane_size,
diff --git a/ui/ozone/platform/x11/gl_ozone_glx.h b/ui/ozone/platform/x11/gl_ozone_glx.h
index b6250a83..e518299d 100644
--- a/ui/ozone/platform/x11/gl_ozone_glx.h
+++ b/ui/ozone/platform/x11/gl_ozone_glx.h
@@ -33,6 +33,7 @@
       gfx::BufferFormat plane_format,
       gfx::BufferPlane plane,
       gfx::Size plane_size,
+      const gfx::ColorSpace& color_space,
       GLenum target,
       GLuint texture_id) override;
   bool GetGLWindowSystemBindingInfo(
diff --git a/ui/ozone/public/gl_ozone.h b/ui/ozone/public/gl_ozone.h
index e9d506ef..c490e0ec 100644
--- a/ui/ozone/public/gl_ozone.h
+++ b/ui/ozone/public/gl_ozone.h
@@ -71,6 +71,7 @@
       gfx::BufferFormat plane_format,
       gfx::BufferPlane plane,
       gfx::Size plane_size,
+      const gfx::ColorSpace& color_space,
       GLenum target,
       GLuint texture_id) = 0;
 
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config.js b/ui/webui/resources/cr_components/chromeos/network/network_config.js
index 486ffaf..472487ee 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config.js
@@ -310,6 +310,14 @@
       computed: 'updateWireGuardKeyType_(wireguardKeyType_)',
     },
 
+    /** @private */
+    enableHiddenNetworkMigration_: {
+      type: Boolean,
+      value() {
+        return loadTimeData.getBoolean('enableHiddenNetworkMigration');
+      }
+    },
+
     /**
      * Array of values for the EAP Method (Outer) dropdown.
      * @private {!Array<string>}
diff --git a/ui/webui/webui_features.gni b/ui/webui/webui_features.gni
index 0affd25..73ac127 100644
--- a/ui/webui/webui_features.gni
+++ b/ui/webui/webui_features.gni
@@ -12,4 +12,8 @@
 
   # Enable the WebUI version of the browser's tab strip.
   enable_webui_tab_strip = is_chromeos || is_linux || is_win
+
+  # Whether to inline source maps during build. This is an experimental feature
+  # currently only being used for New Tab Page being tracked at crbug/1337530.
+  enable_webui_inline_sourcemaps = false
 }
diff --git a/ui/wm/BUILD.gn b/ui/wm/BUILD.gn
index d006f7979..b6f0335 100644
--- a/ui/wm/BUILD.gn
+++ b/ui/wm/BUILD.gn
@@ -7,6 +7,7 @@
 import("//testing/test.gni")
 
 component("wm") {
+  output_name = "ui_wm"
   sources = [
     "core/accelerator_delegate.h",
     "core/accelerator_filter.cc",
@@ -54,7 +55,6 @@
     "core/window_properties.h",
     "core/window_util.cc",
     "core/window_util.h",
-    "core/wm_core_export.h",
     "core/wm_core_switches.cc",
     "core/wm_core_switches.h",
     "core/wm_state.cc",
@@ -62,7 +62,7 @@
   ]
 
   configs += [ "//build/config:precompiled_headers" ]
-  defines = [ "WM_CORE_IMPLEMENTATION" ]
+  defines = [ "IS_UI_WM_IMPL" ]
 
   deps = [
     "//base",
diff --git a/ui/wm/core/accelerator_filter.h b/ui/wm/core/accelerator_filter.h
index 5de3e49d..b448b06 100644
--- a/ui/wm/core/accelerator_filter.h
+++ b/ui/wm/core/accelerator_filter.h
@@ -7,15 +7,15 @@
 
 #include <memory>
 
+#include "base/component_export.h"
 #include "ui/events/event_handler.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 class AcceleratorDelegate;
 
 // AcceleratorFilter filters key events for AcceleratorControler handling global
 // keyboard accelerators.
-class WM_CORE_EXPORT AcceleratorFilter : public ui::EventHandler {
+class COMPONENT_EXPORT(UI_WM) AcceleratorFilter : public ui::EventHandler {
  public:
   // AcceleratorFilter doesn't own |accelerator_history|, it's owned by
   // AcceleratorController.
diff --git a/ui/wm/core/base_focus_rules.h b/ui/wm/core/base_focus_rules.h
index 79aba7f..bdc6a3b 100644
--- a/ui/wm/core/base_focus_rules.h
+++ b/ui/wm/core/base_focus_rules.h
@@ -5,13 +5,14 @@
 #ifndef UI_WM_CORE_BASE_FOCUS_RULES_H_
 #define UI_WM_CORE_BASE_FOCUS_RULES_H_
 
+#include "base/component_export.h"
 #include "ui/wm/core/focus_rules.h"
 
 namespace wm {
 
 // A set of basic focus and activation rules. Specializations should most likely
 // subclass this and call up to these methods rather than reimplementing them.
-class WM_CORE_EXPORT BaseFocusRules : public FocusRules {
+class COMPONENT_EXPORT(UI_WM) BaseFocusRules : public FocusRules {
  public:
   BaseFocusRules(const BaseFocusRules&) = delete;
   BaseFocusRules& operator=(const BaseFocusRules&) = delete;
diff --git a/ui/wm/core/capture_controller.h b/ui/wm/core/capture_controller.h
index 358674ef..3be249ac 100644
--- a/ui/wm/core/capture_controller.h
+++ b/ui/wm/core/capture_controller.h
@@ -7,11 +7,11 @@
 
 #include <map>
 
+#include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "base/observer_list.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/window_observer.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 namespace client {
@@ -22,7 +22,8 @@
 namespace wm {
 
 // Internal CaptureClient implementation. See ScopedCaptureClient for details.
-class WM_CORE_EXPORT CaptureController : public aura::client::CaptureClient {
+class COMPONENT_EXPORT(UI_WM) CaptureController
+    : public aura::client::CaptureClient {
  public:
   CaptureController();
 
@@ -74,9 +75,10 @@
 // ScopedCaptureClient is responsible for creating a CaptureClient for a
 // RootWindow. Specifically it creates a single CaptureController that is shared
 // among all ScopedCaptureClients and adds the RootWindow to it.
-class WM_CORE_EXPORT ScopedCaptureClient : public aura::WindowObserver {
+class COMPONENT_EXPORT(UI_WM) ScopedCaptureClient
+    : public aura::WindowObserver {
  public:
-  class WM_CORE_EXPORT TestApi {
+  class COMPONENT_EXPORT(UI_WM) TestApi {
    public:
     explicit TestApi(ScopedCaptureClient* client) : client_(client) {}
 
diff --git a/ui/wm/core/compound_event_filter.h b/ui/wm/core/compound_event_filter.h
index b0f127e4..22a531b 100644
--- a/ui/wm/core/compound_event_filter.h
+++ b/ui/wm/core/compound_event_filter.h
@@ -5,12 +5,12 @@
 #ifndef UI_WM_CORE_COMPOUND_EVENT_FILTER_H_
 #define UI_WM_CORE_COMPOUND_EVENT_FILTER_H_
 
+#include "base/component_export.h"
 #include "base/observer_list.h"
 #include "base/strings/string_piece.h"
 #include "ui/events/event.h"
 #include "ui/events/event_handler.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace ui {
 class GestureEvent;
@@ -31,7 +31,7 @@
 // consumed by any of those filters. If an event is consumed by a filter, the
 // rest of the filter(s) and CompoundEventFilter will not see the consumed
 // event.
-class WM_CORE_EXPORT CompoundEventFilter : public ui::EventHandler {
+class COMPONENT_EXPORT(UI_WM) CompoundEventFilter : public ui::EventHandler {
  public:
   CompoundEventFilter();
 
diff --git a/ui/wm/core/coordinate_conversion.h b/ui/wm/core/coordinate_conversion.h
index e719999d..363c6f8 100644
--- a/ui/wm/core/coordinate_conversion.h
+++ b/ui/wm/core/coordinate_conversion.h
@@ -5,7 +5,7 @@
 #ifndef UI_WM_CORE_COORDINATE_CONVERSION_H_
 #define UI_WM_CORE_COORDINATE_CONVERSION_H_
 
-#include "ui/wm/core/wm_core_export.h"
+#include "base/component_export.h"
 
 namespace aura {
 class Window;
@@ -23,37 +23,41 @@
 // Converts the |point| from a given |window|'s coordinates into the screen
 // coordinates.
 // TODO: Remove the integer versions of these functions. See crbug.com/773331.
-WM_CORE_EXPORT void ConvertPointToScreen(const aura::Window* window,
-                                         gfx::Point* point);
+COMPONENT_EXPORT(UI_WM)
+void ConvertPointToScreen(const aura::Window* window, gfx::Point* point);
 
-WM_CORE_EXPORT void ConvertPointToScreen(const aura::Window* window,
-                                         gfx::PointF* point);
+COMPONENT_EXPORT(UI_WM)
+void ConvertPointToScreen(const aura::Window* window, gfx::PointF* point);
 
 // Converts the |point| from the screen coordinates to a given |window|'s
 // coordinates.
-WM_CORE_EXPORT void ConvertPointFromScreen(const aura::Window* window,
-                                           gfx::Point* point_in_screen);
+COMPONENT_EXPORT(UI_WM)
+void ConvertPointFromScreen(const aura::Window* window,
+                            gfx::Point* point_in_screen);
 
-WM_CORE_EXPORT void ConvertPointFromScreen(const aura::Window* window,
-                                           gfx::PointF* point_in_screen);
+COMPONENT_EXPORT(UI_WM)
+void ConvertPointFromScreen(const aura::Window* window,
+                            gfx::PointF* point_in_screen);
 
 // Converts |rect| from |window|'s coordinates to the virtual screen
 // coordinates.
 // TODO: Change the Rect versions to TranslateRect(To|From)Screen since they
 // do not handle size changes.
-WM_CORE_EXPORT void ConvertRectToScreen(const aura::Window* window,
-                                        gfx::Rect* rect);
+COMPONENT_EXPORT(UI_WM)
+void ConvertRectToScreen(const aura::Window* window, gfx::Rect* rect);
 
-WM_CORE_EXPORT void TranslateRectToScreen(const aura::Window* window,
-                                          gfx::RectF* rect);
+COMPONENT_EXPORT(UI_WM)
+void TranslateRectToScreen(const aura::Window* window, gfx::RectF* rect);
 
 // Converts |rect| from virtual screen coordinates to the |window|'s
 // coordinates.
-WM_CORE_EXPORT void ConvertRectFromScreen(const aura::Window* window,
-                                          gfx::Rect* rect_in_screen);
+COMPONENT_EXPORT(UI_WM)
+void ConvertRectFromScreen(const aura::Window* window,
+                           gfx::Rect* rect_in_screen);
 
-WM_CORE_EXPORT void TranslateRectFromScreen(const aura::Window* window,
-                                            gfx::RectF* rect_in_screen);
+COMPONENT_EXPORT(UI_WM)
+void TranslateRectFromScreen(const aura::Window* window,
+                             gfx::RectF* rect_in_screen);
 
 }  // namespace wm
 
diff --git a/ui/wm/core/cursor_manager.h b/ui/wm/core/cursor_manager.h
index 011f2f0..3498836 100644
--- a/ui/wm/core/cursor_manager.h
+++ b/ui/wm/core/cursor_manager.h
@@ -7,13 +7,13 @@
 
 #include <memory>
 
+#include "base/component_export.h"
 #include "base/observer_list.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/display/display.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/wm/core/native_cursor_manager_delegate.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace ui {
 class KeyEvent;
@@ -32,8 +32,9 @@
 // requests to queue any further changes until a later time. It sends changes
 // to the NativeCursorManager, which communicates back to us when these changes
 // were made through the NativeCursorManagerDelegate interface.
-class WM_CORE_EXPORT CursorManager : public aura::client::CursorClient,
-                                     public NativeCursorManagerDelegate {
+class COMPONENT_EXPORT(UI_WM) CursorManager
+    : public aura::client::CursorClient,
+      public NativeCursorManagerDelegate {
  public:
   explicit CursorManager(std::unique_ptr<NativeCursorManager> delegate);
 
diff --git a/ui/wm/core/default_activation_client.h b/ui/wm/core/default_activation_client.h
index 2ddeb02..22434e2 100644
--- a/ui/wm/core/default_activation_client.h
+++ b/ui/wm/core/default_activation_client.h
@@ -7,10 +7,10 @@
 
 #include <vector>
 
+#include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "base/observer_list.h"
 #include "ui/aura/window_observer.h"
-#include "ui/wm/core/wm_core_export.h"
 #include "ui/wm/public/activation_change_observer.h"
 #include "ui/wm/public/activation_client.h"
 
@@ -22,8 +22,9 @@
 // that just need basic behavior (e.g. activate windows whenever requested,
 // restack windows at the top when they're activated, etc.). This object deletes
 // itself when the root window it is associated with is destroyed.
-class WM_CORE_EXPORT DefaultActivationClient : public ActivationClient,
-                                               public aura::WindowObserver {
+class COMPONENT_EXPORT(UI_WM) DefaultActivationClient
+    : public ActivationClient,
+      public aura::WindowObserver {
  public:
   explicit DefaultActivationClient(aura::Window* root_window);
 
diff --git a/ui/wm/core/default_screen_position_client.h b/ui/wm/core/default_screen_position_client.h
index 5d643b57..a867ff49 100644
--- a/ui/wm/core/default_screen_position_client.h
+++ b/ui/wm/core/default_screen_position_client.h
@@ -5,15 +5,15 @@
 #ifndef UI_WM_CORE_DEFAULT_SCREEN_POSITION_CLIENT_H_
 #define UI_WM_CORE_DEFAULT_SCREEN_POSITION_CLIENT_H_
 
+#include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "ui/aura/client/screen_position_client.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
 // Client that always offsets by the toplevel RootWindow of the passed
 // in child NativeWidgetAura.
-class WM_CORE_EXPORT DefaultScreenPositionClient
+class COMPONENT_EXPORT(UI_WM) DefaultScreenPositionClient
     : public aura::client::ScreenPositionClient {
  public:
   explicit DefaultScreenPositionClient(aura::Window* root_window);
diff --git a/ui/wm/core/easy_resize_window_targeter.h b/ui/wm/core/easy_resize_window_targeter.h
index 111a0de..e21fb2ae 100644
--- a/ui/wm/core/easy_resize_window_targeter.h
+++ b/ui/wm/core/easy_resize_window_targeter.h
@@ -5,8 +5,8 @@
 #ifndef UI_WM_CORE_EASY_RESIZE_WINDOW_TARGETER_H_
 #define UI_WM_CORE_EASY_RESIZE_WINDOW_TARGETER_H_
 
+#include "base/component_export.h"
 #include "ui/aura/window_targeter.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace gfx {
 class Insets;
@@ -19,7 +19,8 @@
 // windows (top level Widgets that are resizable) to outside their bounds. For
 // Ash, this correlates to ash::kResizeOutsideBoundsSize. For the interior
 // resize area, see ash::InstallResizeHandleWindowTargeterForWindow().
-class WM_CORE_EXPORT EasyResizeWindowTargeter : public aura::WindowTargeter {
+class COMPONENT_EXPORT(UI_WM) EasyResizeWindowTargeter
+    : public aura::WindowTargeter {
  public:
   // NOTE: the insets must be negative.
   EasyResizeWindowTargeter(const gfx::Insets& mouse_extend,
diff --git a/ui/wm/core/focus_controller.h b/ui/wm/core/focus_controller.h
index 1caeba4..8e08c4cd 100644
--- a/ui/wm/core/focus_controller.h
+++ b/ui/wm/core/focus_controller.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "base/observer_list.h"
 #include "base/scoped_multi_source_observation.h"
@@ -15,7 +16,6 @@
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/window_observer.h"
 #include "ui/events/event_handler.h"
-#include "ui/wm/core/wm_core_export.h"
 #include "ui/wm/public/activation_change_observer.h"
 #include "ui/wm/public/activation_client.h"
 
@@ -41,10 +41,11 @@
 // . ActivationReason::WINDOW_DISPOSITION_CHANGED: Window disposition changes
 //   (implemented here in aura::WindowObserver). (The FocusController registers
 //   itself as an observer of the active and focused windows).
-class WM_CORE_EXPORT FocusController : public ActivationClient,
-                                       public aura::client::FocusClient,
-                                       public ui::EventHandler,
-                                       public aura::WindowObserver {
+class COMPONENT_EXPORT(UI_WM) FocusController : public ActivationClient,
+                                                public aura::client::FocusClient
+    ,
+                                                public ui::EventHandler,
+                                                public aura::WindowObserver {
  public:
   // |rules| cannot be NULL.
   explicit FocusController(FocusRules* rules);
diff --git a/ui/wm/core/focus_rules.h b/ui/wm/core/focus_rules.h
index 44644c9..a30a70e 100644
--- a/ui/wm/core/focus_rules.h
+++ b/ui/wm/core/focus_rules.h
@@ -5,7 +5,7 @@
 #ifndef UI_WM_CORE_FOCUS_RULES_H_
 #define UI_WM_CORE_FOCUS_RULES_H_
 
-#include "ui/wm/core/wm_core_export.h"
+#include "base/component_export.h"
 
 namespace aura {
 class Window;
@@ -19,7 +19,7 @@
 
 // Implemented by an object that establishes the rules about what can be
 // focused or activated.
-class WM_CORE_EXPORT FocusRules {
+class COMPONENT_EXPORT(UI_WM) FocusRules {
  public:
   virtual ~FocusRules() {}
 
diff --git a/ui/wm/core/ime_util_chromeos.h b/ui/wm/core/ime_util_chromeos.h
index eb5faae..d139661 100644
--- a/ui/wm/core/ime_util_chromeos.h
+++ b/ui/wm/core/ime_util_chromeos.h
@@ -5,8 +5,8 @@
 #ifndef UI_WM_CORE_IME_UTIL_CHROMEOS_H_
 #define UI_WM_CORE_IME_UTIL_CHROMEOS_H_
 
+#include "base/component_export.h"
 #include "ui/aura/window.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace gfx {
 class Rect;
@@ -16,16 +16,18 @@
 
 // A property key to store the restore bounds for a window when moved by the
 // virtual keyboard.
-WM_CORE_EXPORT extern const aura::WindowProperty<gfx::Rect*>* const
+COMPONENT_EXPORT(UI_WM)
+extern const aura::WindowProperty<gfx::Rect*>* const
     kVirtualKeyboardRestoreBoundsKey;
 
 // Moves |window| to ensure it does not intersect with |rect_in_screen|.
-WM_CORE_EXPORT void EnsureWindowNotInRect(aura::Window* window,
-                                          const gfx::Rect& rect_in_screen);
+COMPONENT_EXPORT(UI_WM)
+void EnsureWindowNotInRect(aura::Window* window,
+                           const gfx::Rect& rect_in_screen);
 
 // Restores the window bounds when input client loses the focus on the window.
-WM_CORE_EXPORT void RestoreWindowBoundsOnClientFocusLost(
-    aura::Window* top_level_window);
+COMPONENT_EXPORT(UI_WM)
+void RestoreWindowBoundsOnClientFocusLost(aura::Window* top_level_window);
 
 }  // namespace wm
 
diff --git a/ui/wm/core/native_cursor_manager.h b/ui/wm/core/native_cursor_manager.h
index ae427fe..28aa6373 100644
--- a/ui/wm/core/native_cursor_manager.h
+++ b/ui/wm/core/native_cursor_manager.h
@@ -5,8 +5,8 @@
 #ifndef UI_WM_CORE_NATIVE_CURSOR_MANAGER_H_
 #define UI_WM_CORE_NATIVE_CURSOR_MANAGER_H_
 
+#include "base/component_export.h"
 #include "ui/wm/core/native_cursor_manager_delegate.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace display {
 class Display;
@@ -22,7 +22,7 @@
 // requested changes to cursor state. When requested, implementer should tell
 // the CursorManager of any actual state changes performed through the
 // delegate.
-class WM_CORE_EXPORT NativeCursorManager {
+class COMPONENT_EXPORT(UI_WM) NativeCursorManager {
  public:
   virtual ~NativeCursorManager() {}
 
diff --git a/ui/wm/core/native_cursor_manager_delegate.h b/ui/wm/core/native_cursor_manager_delegate.h
index d1a5540..4dfea286 100644
--- a/ui/wm/core/native_cursor_manager_delegate.h
+++ b/ui/wm/core/native_cursor_manager_delegate.h
@@ -5,8 +5,8 @@
 #ifndef UI_WM_CORE_NATIVE_CURSOR_MANAGER_DELEGATE_H_
 #define UI_WM_CORE_NATIVE_CURSOR_MANAGER_DELEGATE_H_
 
+#include "base/component_export.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace ui {
 enum class CursorSize;
@@ -17,7 +17,7 @@
 // The non-public interface that CursorManager exposes to its users. This
 // gives accessors to all the current state, and mutators to all the current
 // state.
-class WM_CORE_EXPORT NativeCursorManagerDelegate {
+class COMPONENT_EXPORT(UI_WM) NativeCursorManagerDelegate {
  public:
   virtual ~NativeCursorManagerDelegate() {}
 
diff --git a/ui/wm/core/shadow_controller.h b/ui/wm/core/shadow_controller.h
index 7584634a..49cb4b3 100644
--- a/ui/wm/core/shadow_controller.h
+++ b/ui/wm/core/shadow_controller.h
@@ -7,9 +7,9 @@
 
 #include <map>
 
+#include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
-#include "ui/wm/core/wm_core_export.h"
 #include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
@@ -30,7 +30,8 @@
 // shadows as needed. ShadowController itself is light weight and per
 // ActivationClient. ShadowController delegates to its implementation class,
 // which observes all window creation.
-class WM_CORE_EXPORT ShadowController : public ActivationChangeObserver {
+class COMPONENT_EXPORT(UI_WM) ShadowController
+    : public ActivationChangeObserver {
  public:
   // Returns the shadow for the |window|, or NULL if no shadow exists.
   static ui::Shadow* GetShadowForWindow(aura::Window* window);
diff --git a/ui/wm/core/shadow_controller_delegate.h b/ui/wm/core/shadow_controller_delegate.h
index e0ce6e2..b64eb1b 100644
--- a/ui/wm/core/shadow_controller_delegate.h
+++ b/ui/wm/core/shadow_controller_delegate.h
@@ -5,7 +5,7 @@
 #ifndef UI_WM_CORE_SHADOW_CONTROLLER_DELEGATE_H_
 #define UI_WM_CORE_SHADOW_CONTROLLER_DELEGATE_H_
 
-#include "ui/wm/core/wm_core_export.h"
+#include "base/component_export.h"
 
 namespace aura {
 class Window;
@@ -15,7 +15,7 @@
 
 // ShadowControllerDelegate allows a user to modify a shadow on certain windows
 // differently from the normal use case.
-class WM_CORE_EXPORT ShadowControllerDelegate {
+class COMPONENT_EXPORT(UI_WM) ShadowControllerDelegate {
  public:
   ShadowControllerDelegate() = default;
   virtual ~ShadowControllerDelegate() = default;
@@ -27,4 +27,4 @@
 
 }  // namespace wm
 
-#endif  // UI_WM_CORE_SHADOW_CONTROLLER_DELEGATE_H_
\ No newline at end of file
+#endif  // UI_WM_CORE_SHADOW_CONTROLLER_DELEGATE_H_
diff --git a/ui/wm/core/shadow_types.h b/ui/wm/core/shadow_types.h
index d57dda9..7ec0e3b 100644
--- a/ui/wm/core/shadow_types.h
+++ b/ui/wm/core/shadow_types.h
@@ -5,9 +5,9 @@
 #ifndef UI_WM_CORE_SHADOW_TYPES_H_
 #define UI_WM_CORE_SHADOW_TYPES_H_
 
+#include "base/component_export.h"
 #include "build/chromeos_buildflags.h"
 #include "ui/aura/window.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
@@ -31,20 +31,22 @@
 #endif
 constexpr int kShadowElevationActiveWindow = 24;
 
-WM_CORE_EXPORT void SetShadowElevation(aura::Window* window, int elevation);
+COMPONENT_EXPORT(UI_WM)
+void SetShadowElevation(aura::Window* window, int elevation);
 
 // Returns the default shadow elevaltion value for |window|.
-WM_CORE_EXPORT int GetDefaultShadowElevationForWindow(
-    const aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+int GetDefaultShadowElevationForWindow(const aura::Window* window);
 
 // Returns the shadow elevation property value for |window|, converting
 // |kShadowElevationDefault| to the appropriate value.
-WM_CORE_EXPORT int GetShadowElevationConvertDefault(const aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+int GetShadowElevationConvertDefault(const aura::Window* window);
 
 // A property key describing the drop shadow that should be displayed under the
 // window. A null value is interpreted as using the default.
-WM_CORE_EXPORT extern const aura::WindowProperty<int>* const
-    kShadowElevationKey;
+COMPONENT_EXPORT(UI_WM)
+extern const aura::WindowProperty<int>* const kShadowElevationKey;
 
 }  // namespace wm
 
diff --git a/ui/wm/core/transient_window_controller.h b/ui/wm/core/transient_window_controller.h
index 4ed44e9..99be3354 100644
--- a/ui/wm/core/transient_window_controller.h
+++ b/ui/wm/core/transient_window_controller.h
@@ -5,9 +5,9 @@
 #ifndef UI_WM_CORE_TRANSIENT_WINDOW_CONTROLLER_H_
 #define UI_WM_CORE_TRANSIENT_WINDOW_CONTROLLER_H_
 
+#include "base/component_export.h"
 #include "base/observer_list.h"
 #include "ui/aura/client/transient_window_client.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
@@ -15,7 +15,7 @@
 
 // TransientWindowClient implementation. Uses TransientWindowManager to handle
 // tracking transient per window.
-class WM_CORE_EXPORT TransientWindowController
+class COMPONENT_EXPORT(UI_WM) TransientWindowController
     : public aura::client::TransientWindowClient {
  public:
   TransientWindowController();
diff --git a/ui/wm/core/transient_window_manager.h b/ui/wm/core/transient_window_manager.h
index 5089b9d..898d67d 100644
--- a/ui/wm/core/transient_window_manager.h
+++ b/ui/wm/core/transient_window_manager.h
@@ -7,10 +7,10 @@
 
 #include <vector>
 
+#include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "base/observer_list.h"
 #include "ui/aura/window_observer.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
@@ -27,7 +27,8 @@
 // . If a transient parent is hidden, it hides all transient children.
 //   For show operation, please refer to |set_parent_controls_visibility(bool)|.
 // Transient windows are typically used for popups and menus.
-class WM_CORE_EXPORT TransientWindowManager : public aura::WindowObserver {
+class COMPONENT_EXPORT(UI_WM) TransientWindowManager
+    : public aura::WindowObserver {
  public:
   using Windows = std::vector<aura::Window*>;
 
diff --git a/ui/wm/core/transient_window_observer.h b/ui/wm/core/transient_window_observer.h
index d935a80..73a1477 100644
--- a/ui/wm/core/transient_window_observer.h
+++ b/ui/wm/core/transient_window_observer.h
@@ -5,7 +5,7 @@
 #ifndef UI_WM_CORE_TRANSIENT_WINDOW_OBSERVER_H_
 #define UI_WM_CORE_TRANSIENT_WINDOW_OBSERVER_H_
 
-#include "ui/wm/core/wm_core_export.h"
+#include "base/component_export.h"
 
 namespace aura {
 class Window;
@@ -13,7 +13,7 @@
 
 namespace wm {
 
-class WM_CORE_EXPORT TransientWindowObserver {
+class COMPONENT_EXPORT(UI_WM) TransientWindowObserver {
  public:
   // Called when a transient child is added to |window|.
   virtual void OnTransientChildAdded(aura::Window* window,
diff --git a/ui/wm/core/transient_window_stacking_client.h b/ui/wm/core/transient_window_stacking_client.h
index df788fb..c4114cb08 100644
--- a/ui/wm/core/transient_window_stacking_client.h
+++ b/ui/wm/core/transient_window_stacking_client.h
@@ -5,14 +5,14 @@
 #ifndef UI_WM_CORE_TRANSIENT_WINDOW_STACKING_CLIENT_H_
 #define UI_WM_CORE_TRANSIENT_WINDOW_STACKING_CLIENT_H_
 
+#include "base/component_export.h"
 #include "ui/aura/client/window_stacking_client.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
 class TransientWindowManager;
 
-class WM_CORE_EXPORT TransientWindowStackingClient
+class COMPONENT_EXPORT(UI_WM) TransientWindowStackingClient
     : public aura::client::WindowStackingClient {
  public:
   TransientWindowStackingClient();
diff --git a/ui/wm/core/visibility_controller.h b/ui/wm/core/visibility_controller.h
index 96efbf7..ec90784 100644
--- a/ui/wm/core/visibility_controller.h
+++ b/ui/wm/core/visibility_controller.h
@@ -5,13 +5,13 @@
 #ifndef UI_WM_CORE_VISIBILITY_CONTROLLER_H_
 #define UI_WM_CORE_VISIBILITY_CONTROLLER_H_
 
+#include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "ui/aura/client/visibility_client.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
-class WM_CORE_EXPORT VisibilityController
+class COMPONENT_EXPORT(UI_WM) VisibilityController
     : public aura::client::VisibilityClient {
  public:
   VisibilityController();
@@ -47,7 +47,7 @@
 //   // previous state.
 // }
 //
-class WM_CORE_EXPORT SuspendChildWindowVisibilityAnimations {
+class COMPONENT_EXPORT(UI_WM) SuspendChildWindowVisibilityAnimations {
  public:
   // Suspend visibility animations of child windows.
   explicit SuspendChildWindowVisibilityAnimations(aura::Window* window);
@@ -74,13 +74,14 @@
 // whose animation is already enabled either by this function, or
 // via SetChildWindowVisibilityChangesAnimatedbelow below is allowed and
 // the animation stays enabled.
-void WM_CORE_EXPORT SetWindowVisibilityChangesAnimated(aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+void SetWindowVisibilityChangesAnimated(aura::Window* window);
 
 // Enable visibility change animation for all children of the |window|.
 // Typically applied to a container whose child windows should be animated
 // when their visibility changes.
-void WM_CORE_EXPORT
-SetChildWindowVisibilityChangesAnimated(aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+void SetChildWindowVisibilityChangesAnimated(aura::Window* window);
 
 }  // namespace wm
 
diff --git a/ui/wm/core/window_animations.h b/ui/wm/core/window_animations.h
index 7580e2a2..436abd4 100644
--- a/ui/wm/core/window_animations.h
+++ b/ui/wm/core/window_animations.h
@@ -5,10 +5,10 @@
 #ifndef UI_WM_CORE_WINDOW_ANIMATIONS_H_
 #define UI_WM_CORE_WINDOW_ANIMATIONS_H_
 
+#include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/wm/core/window_properties.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 class Window;
@@ -41,35 +41,39 @@
 
 // These two methods use int for type rather than WindowVisibilityAnimationType
 // since downstream libraries can extend the set of animations.
-WM_CORE_EXPORT void SetWindowVisibilityAnimationType(aura::Window* window,
-                                                     int type);
-WM_CORE_EXPORT int GetWindowVisibilityAnimationType(aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+void SetWindowVisibilityAnimationType(aura::Window* window, int type);
+COMPONENT_EXPORT(UI_WM)
+int GetWindowVisibilityAnimationType(aura::Window* window);
 
-WM_CORE_EXPORT void SetWindowVisibilityAnimationTransition(
+COMPONENT_EXPORT(UI_WM)
+void SetWindowVisibilityAnimationTransition(
     aura::Window* window,
     WindowVisibilityAnimationTransition transition);
 
-WM_CORE_EXPORT bool HasWindowVisibilityAnimationTransition(
+COMPONENT_EXPORT(UI_WM)
+bool HasWindowVisibilityAnimationTransition(
     aura::Window* window,
     WindowVisibilityAnimationTransition transition);
 
-WM_CORE_EXPORT void SetWindowVisibilityAnimationDuration(
-    aura::Window* window,
-    const base::TimeDelta& duration);
+COMPONENT_EXPORT(UI_WM)
+void SetWindowVisibilityAnimationDuration(aura::Window* window,
+                                          const base::TimeDelta& duration);
 
-WM_CORE_EXPORT base::TimeDelta GetWindowVisibilityAnimationDuration(
+COMPONENT_EXPORT(UI_WM)
+base::TimeDelta GetWindowVisibilityAnimationDuration(
     const aura::Window& window);
 
-WM_CORE_EXPORT void SetWindowVisibilityAnimationVerticalPosition(
-    aura::Window* window,
-    float position);
+COMPONENT_EXPORT(UI_WM)
+void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,
+                                                  float position);
 
 class ImplicitHidingWindowAnimationObserver;
 // A wrapper of ui::ScopedLayerAnimationSettings for implicit hiding animations.
 // Use this to ensure that the hiding animation is visible even after
 // the window is deleted or deactivated, instead of using
 // ui::ScopedLayerAnimationSettings directly.
-class WM_CORE_EXPORT ScopedHidingAnimationSettings {
+class COMPONENT_EXPORT(UI_WM) ScopedHidingAnimationSettings {
  public:
   explicit ScopedHidingAnimationSettings(aura::Window* window);
 
@@ -90,15 +94,15 @@
 };
 
 // Returns false if the |window| didn't animate.
-WM_CORE_EXPORT bool AnimateOnChildWindowVisibilityChanged(aura::Window* window,
-                                                          bool visible);
-WM_CORE_EXPORT bool AnimateWindow(aura::Window* window,
-                                  WindowAnimationType type);
+COMPONENT_EXPORT(UI_WM)
+bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible);
+COMPONENT_EXPORT(UI_WM)
+bool AnimateWindow(aura::Window* window, WindowAnimationType type);
 
 // Returns true if window animations are disabled for |window|. Window
 // animations are enabled by default. If |window| is nullptr, this just checks
 // if the global flag disabling window animations is present.
-WM_CORE_EXPORT bool WindowAnimationsDisabled(aura::Window* window);
+COMPONENT_EXPORT(UI_WM) bool WindowAnimationsDisabled(aura::Window* window);
 
 }  // namespace wm
 
diff --git a/ui/wm/core/window_modality_controller.h b/ui/wm/core/window_modality_controller.h
index 2d1c724..437b954 100644
--- a/ui/wm/core/window_modality_controller.h
+++ b/ui/wm/core/window_modality_controller.h
@@ -7,12 +7,12 @@
 
 #include <vector>
 
+#include "base/component_export.h"
 #include "base/memory/raw_ptr.h"
 #include "base/strings/string_piece.h"
 #include "ui/aura/env_observer.h"
 #include "ui/aura/window_observer.h"
 #include "ui/events/event_handler.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 class Env;
@@ -26,20 +26,22 @@
 namespace wm {
 
 // Sets the modal parent for the child.
-WM_CORE_EXPORT void SetModalParent(aura::Window* child, aura::Window* parent);
+COMPONENT_EXPORT(UI_WM)
+void SetModalParent(aura::Window* child, aura::Window* parent);
 
 // Returns the modal transient child of |window|, or NULL if |window| does not
 // have any modal transient children.
-WM_CORE_EXPORT aura::Window* GetModalTransient(aura::Window* window);
-WM_CORE_EXPORT const aura::Window* GetModalTransient(
-    const aura::Window* window);
+COMPONENT_EXPORT(UI_WM) aura::Window* GetModalTransient(aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+const aura::Window* GetModalTransient(const aura::Window* window);
 
 // WindowModalityController is an event filter that consumes events sent to
 // windows that are the transient parents of window-modal windows. This filter
 // must be added to the CompoundEventFilter so that activation works properly.
-class WM_CORE_EXPORT WindowModalityController : public ui::EventHandler,
-                                                public aura::EnvObserver,
-                                                public aura::WindowObserver {
+class COMPONENT_EXPORT(UI_WM) WindowModalityController
+    : public ui::EventHandler,
+      public aura::EnvObserver,
+      public aura::WindowObserver {
  public:
   explicit WindowModalityController(ui::EventTarget* event_target,
                                     aura::Env* env = nullptr);
diff --git a/ui/wm/core/window_properties.cc b/ui/wm/core/window_properties.cc
index 506dd0c0..7389694 100644
--- a/ui/wm/core/window_properties.cc
+++ b/ui/wm/core/window_properties.cc
@@ -6,10 +6,10 @@
 
 #include "ui/wm/core/window_animations.h"
 
-DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_CORE_EXPORT,
+DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(COMPONENT_EXPORT(UI_WM),
                                        wm::WindowVisibilityAnimationTransition)
 
-DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_CORE_EXPORT, float)
+DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(COMPONENT_EXPORT(UI_WM), float)
 
 namespace wm {
 
diff --git a/ui/wm/core/window_properties.h b/ui/wm/core/window_properties.h
index ae131fc..62caea0f 100644
--- a/ui/wm/core/window_properties.h
+++ b/ui/wm/core/window_properties.h
@@ -5,9 +5,9 @@
 #ifndef UI_WM_CORE_WINDOW_PROPERTIES_H_
 #define UI_WM_CORE_WINDOW_PROPERTIES_H_
 
+#include "base/component_export.h"
 #include "base/time/time.h"
 #include "ui/base/class_property.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
@@ -24,28 +24,30 @@
 
 // Property to tell if the container uses screen coordinates for the child
 // windows.
-WM_CORE_EXPORT extern const ui::ClassProperty<bool>* const
-    kUsesScreenCoordinatesKey;
+COMPONENT_EXPORT(UI_WM)
+extern const ui::ClassProperty<bool>* const kUsesScreenCoordinatesKey;
 
-WM_CORE_EXPORT extern const ui::ClassProperty<base::TimeDelta>* const
+COMPONENT_EXPORT(UI_WM)
+extern const ui::ClassProperty<base::TimeDelta>* const
     kWindowVisibilityAnimationDurationKey;
 
-WM_CORE_EXPORT extern const ui::ClassProperty<
-    WindowVisibilityAnimationTransition>* const
+COMPONENT_EXPORT(UI_WM)
+extern const ui::ClassProperty<WindowVisibilityAnimationTransition>* const
     kWindowVisibilityAnimationTransitionKey;
 
-WM_CORE_EXPORT extern const ui::ClassProperty<int>* const
-    kWindowVisibilityAnimationTypeKey;
+COMPONENT_EXPORT(UI_WM)
+extern const ui::ClassProperty<int>* const kWindowVisibilityAnimationTypeKey;
 
 // Used if the animation-type is WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL.
-WM_CORE_EXPORT extern const ui::ClassProperty<float>* const
+COMPONENT_EXPORT(UI_WM)
+extern const ui::ClassProperty<float>* const
     kWindowVisibilityAnimationVerticalPositionKey;
 
 }  // namespace wm
 
 // These need to be declared here for jumbo builds.
-DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_CORE_EXPORT,
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(COMPONENT_EXPORT(UI_WM),
                                         wm::WindowVisibilityAnimationTransition)
-DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_CORE_EXPORT, float)
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(COMPONENT_EXPORT(UI_WM), float)
 
 #endif  // UI_WM_CORE_WINDOW_PROPERTIES_H_
diff --git a/ui/wm/core/window_util.h b/ui/wm/core/window_util.h
index 33b0b96..c33a30c 100644
--- a/ui/wm/core/window_util.h
+++ b/ui/wm/core/window_util.h
@@ -10,8 +10,8 @@
 #include <vector>
 
 #include "base/callback_forward.h"
+#include "base/component_export.h"
 #include "ui/base/ui_base_types.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 class Window;
@@ -25,41 +25,43 @@
 
 namespace wm {
 
-WM_CORE_EXPORT void ActivateWindow(aura::Window* window);
-WM_CORE_EXPORT void DeactivateWindow(aura::Window* window);
-WM_CORE_EXPORT bool IsActiveWindow(const aura::Window* window);
-WM_CORE_EXPORT bool CanActivateWindow(const aura::Window* window);
-WM_CORE_EXPORT void SetWindowFullscreen(aura::Window* window, bool fullscreen);
+COMPONENT_EXPORT(UI_WM) void ActivateWindow(aura::Window* window);
+COMPONENT_EXPORT(UI_WM) void DeactivateWindow(aura::Window* window);
+COMPONENT_EXPORT(UI_WM) bool IsActiveWindow(const aura::Window* window);
+COMPONENT_EXPORT(UI_WM) bool CanActivateWindow(const aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+void SetWindowFullscreen(aura::Window* window, bool fullscreen);
 
 // Returns true if |window|'s show state is |state|.
-WM_CORE_EXPORT bool WindowStateIs(const aura::Window* window,
-                                  ui::WindowShowState state);
+COMPONENT_EXPORT(UI_WM)
+bool WindowStateIs(const aura::Window* window, ui::WindowShowState state);
 
 // Sets the window state to |state|.
-WM_CORE_EXPORT void SetWindowState(aura::Window* window,
-                                   ui::WindowShowState state);
+COMPONENT_EXPORT(UI_WM)
+void SetWindowState(aura::Window* window, ui::WindowShowState state);
 
 // Restores the window state from the current state to its previous applicable
 // state. As an example, if the current state is minimized, Restore() will
 // change the window's sate to its applicable pre-minimized state, which is the
 // same as calling Unminimize() function.
-WM_CORE_EXPORT void Restore(aura::Window* window);
+COMPONENT_EXPORT(UI_WM) void Restore(aura::Window* window);
 
 // Changes a window's state to its pre-minimized state.
-WM_CORE_EXPORT void Unminimize(aura::Window* window);
+COMPONENT_EXPORT(UI_WM) void Unminimize(aura::Window* window);
 
 // Retrieves the activatable window for |window|. If |window| is activatable,
 // this will just return it, otherwise it will climb the parent/transient parent
 // chain looking for a window that is activatable, per the ActivationClient.
 // If you're looking for a function to get the activatable "top level" window,
 // this is probably the function you're looking for.
-WM_CORE_EXPORT aura::Window* GetActivatableWindow(aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+aura::Window* GetActivatableWindow(aura::Window* window);
 
 // Retrieves the toplevel window for |window|. The ActivationClient makes this
 // determination.
-WM_CORE_EXPORT aura::Window* GetToplevelWindow(aura::Window* window);
-WM_CORE_EXPORT const aura::Window* GetToplevelWindow(
-    const aura::Window* window);
+COMPONENT_EXPORT(UI_WM) aura::Window* GetToplevelWindow(aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+const aura::Window* GetToplevelWindow(const aura::Window* window);
 
 // Returns the existing Layer for |root| (and all its descendants) and creates
 // a new layer for |root| and all its descendants. This is intended for
@@ -67,8 +69,8 @@
 //
 // As a result of this |root| has freshly created layers, meaning the layers
 // have not yet been painted to.
-WM_CORE_EXPORT std::unique_ptr<ui::LayerTreeOwner> RecreateLayers(
-    ui::LayerOwner* root);
+COMPONENT_EXPORT(UI_WM)
+std::unique_ptr<ui::LayerTreeOwner> RecreateLayers(ui::LayerOwner* root);
 
 using MapLayerFunc =
     base::RepeatingCallback<std::unique_ptr<ui::Layer>(ui::LayerOwner*)>;
@@ -77,38 +79,42 @@
 // layer tree. The recursion stops at the level when |map_func| returns nullptr
 // on the owner's layer. MapLayers might return nullptr when |map_func| returns
 // nullptr on the root layer's owner.
-WM_CORE_EXPORT std::unique_ptr<ui::LayerTreeOwner> RecreateLayersWithClosure(
+COMPONENT_EXPORT(UI_WM)
+std::unique_ptr<ui::LayerTreeOwner> RecreateLayersWithClosure(
     ui::LayerOwner* root,
     const MapLayerFunc& map_func);
 
 // Returns a layer tree that mirrors |root|. Used for live window previews. If
 // |sync_bounds| is true, the bounds of all mirror layers except the root are
 // synchronized. See |sync_bounds_with_source_| in ui::Layer.
-WM_CORE_EXPORT std::unique_ptr<ui::LayerTreeOwner> MirrorLayers(
-    ui::LayerOwner* root,
-    bool sync_bounds);
+COMPONENT_EXPORT(UI_WM)
+std::unique_ptr<ui::LayerTreeOwner> MirrorLayers(ui::LayerOwner* root,
+                                                 bool sync_bounds);
 
 // Convenience functions that get the TransientWindowManager for the window and
 // redirect appropriately. These are preferable to calling functions on
 // TransientWindowManager as they handle the appropriate null checks.
-WM_CORE_EXPORT aura::Window* GetTransientParent(aura::Window* window);
-WM_CORE_EXPORT const aura::Window* GetTransientParent(
+COMPONENT_EXPORT(UI_WM) aura::Window* GetTransientParent(aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+const aura::Window* GetTransientParent(const aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+const std::vector<aura::Window*>& GetTransientChildren(
     const aura::Window* window);
-WM_CORE_EXPORT const std::vector<aura::Window*>& GetTransientChildren(
-    const aura::Window* window);
-WM_CORE_EXPORT void AddTransientChild(aura::Window* parent,
-                                      aura::Window* child);
-WM_CORE_EXPORT void RemoveTransientChild(aura::Window* parent,
-                                         aura::Window* child);
-WM_CORE_EXPORT aura::Window* GetTransientRoot(aura::Window* window);
+COMPONENT_EXPORT(UI_WM)
+void AddTransientChild(aura::Window* parent, aura::Window* child);
+COMPONENT_EXPORT(UI_WM)
+void RemoveTransientChild(aura::Window* parent, aura::Window* child);
+COMPONENT_EXPORT(UI_WM) aura::Window* GetTransientRoot(aura::Window* window);
 
 // Returns true if |window| has |ancestor| as a transient ancestor. A transient
 // ancestor is found by following the transient parent chain of the window.
-WM_CORE_EXPORT bool HasTransientAncestor(const aura::Window* window,
-                                         const aura::Window* ancestor);
+COMPONENT_EXPORT(UI_WM)
+bool HasTransientAncestor(const aura::Window* window,
+                          const aura::Window* ancestor);
 
 // Snap the window's layer to physical pixel boundary.
-WM_CORE_EXPORT void SnapWindowToPixelBoundary(aura::Window* window);
+COMPONENT_EXPORT(UI_WM) void SnapWindowToPixelBoundary(aura::Window* window);
+
 }  // namespace wm
 
 #endif  // UI_WM_CORE_WINDOW_UTIL_H_
diff --git a/ui/wm/core/wm_core_export.h b/ui/wm/core/wm_core_export.h
deleted file mode 100644
index c033ddc..0000000
--- a/ui/wm/core/wm_core_export.h
+++ /dev/null
@@ -1,32 +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.
-
-#ifndef UI_WM_CORE_WM_CORE_EXPORT_H_
-#define UI_WM_CORE_WM_CORE_EXPORT_H_
-
-// Defines WM_CORE_EXPORT so that functionality implemented by the WM module
-// can be exported to consumers.
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(WM_CORE_IMPLEMENTATION)
-#define WM_CORE_EXPORT __declspec(dllexport)
-#else
-#define WM_CORE_EXPORT __declspec(dllimport)
-#endif  // defined(WM_CORE_IMPLEMENTATION)
-
-#else  // defined(WIN32)
-#if defined(WM_CORE_IMPLEMENTATION)
-#define WM_CORE_EXPORT __attribute__((visibility("default")))
-#else
-#define WM_CORE_EXPORT
-#endif
-#endif
-
-#else  // defined(COMPONENT_BUILD)
-#define WM_CORE_EXPORT
-#endif
-
-#endif  // UI_WM_CORE_WM_CORE_EXPORT_H_
diff --git a/ui/wm/core/wm_core_switches.h b/ui/wm/core/wm_core_switches.h
index dd48025..3a9ddf4 100644
--- a/ui/wm/core/wm_core_switches.h
+++ b/ui/wm/core/wm_core_switches.h
@@ -5,8 +5,8 @@
 #ifndef UI_WM_CORE_WM_CORE_SWITCHES_H_
 #define UI_WM_CORE_WM_CORE_SWITCHES_H_
 
+#include "base/component_export.h"
 #include "build/build_config.h"
-#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 namespace switches {
@@ -16,7 +16,7 @@
 // see chromeos::LoginUtil::GetOffTheRecordCommandLine().)
 
 // Please keep alphabetized.
-WM_CORE_EXPORT extern const char kWindowAnimationsDisabled[];
+COMPONENT_EXPORT(UI_WM) extern const char kWindowAnimationsDisabled[];
 
 }  // namespace switches
 }  // namespace wm
diff --git a/ui/wm/core/wm_state.h b/ui/wm/core/wm_state.h
index a0f182a..3686b03 100644
--- a/ui/wm/core/wm_state.h
+++ b/ui/wm/core/wm_state.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "ui/wm/core/wm_core_export.h"
+#include "base/component_export.h"
 
 namespace wm {
 
@@ -16,7 +16,7 @@
 class TransientWindowStackingClient;
 
 // Installs state needed by the window manager.
-class WM_CORE_EXPORT WMState {
+class COMPONENT_EXPORT(UI_WM) WMState {
  public:
   WMState();
 
diff --git a/weblayer/browser/download_manager_delegate_impl.cc b/weblayer/browser/download_manager_delegate_impl.cc
index ff8e7a70..2b4926b 100644
--- a/weblayer/browser/download_manager_delegate_impl.cc
+++ b/weblayer/browser/download_manager_delegate_impl.cc
@@ -91,8 +91,7 @@
         download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
         download::DownloadItem::MixedContentStatus::UNKNOWN,
         item->GetForcedFilePath(), base::FilePath(),
-        std::string() /*mime_type*/, absl::nullopt /*download_schedule*/,
-        download::DOWNLOAD_INTERRUPT_REASON_NONE);
+        std::string() /*mime_type*/, download::DOWNLOAD_INTERRUPT_REASON_NONE);
     return true;
   }
 
@@ -264,7 +263,6 @@
       download::DownloadItem::MixedContentStatus::UNKNOWN,
       suggested_path.AddExtension(FILE_PATH_LITERAL(".crdownload")),
       base::FilePath(), std::string() /*mime_type*/,
-      absl::nullopt /*download_schedule*/,
       download::DOWNLOAD_INTERRUPT_REASON_NONE);
 }